diff options
353 files changed, 14657 insertions, 5737 deletions
diff --git a/StubLibraries.bp b/StubLibraries.bp index cdc0d322eedb..6927f4449054 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -181,7 +181,7 @@ droidstubs { // They however are NOT used for building the API stub. droidstubs { name: "module-app-api", - defaults: ["metalava-non-updatable-api-stubs-default"], + defaults: ["metalava-api-stubs-default"], libs: ["framework-all"], arg_files: ["core/res/AndroidManifest.xml"], args: metalava_framework_docs_args + @@ -211,7 +211,7 @@ droidstubs { droidstubs { name: "module-lib-api", - defaults: ["metalava-non-updatable-api-stubs-default"], + defaults: ["metalava-api-stubs-default"], libs: ["framework-all"], arg_files: ["core/res/AndroidManifest.xml"], args: metalava_framework_docs_args + @@ -245,7 +245,7 @@ droidstubs { // the ones with 'client=MODULE_LIBRARIES'. droidstubs { name: "module-app-api-stubs-docs", - defaults: ["metalava-non-updatable-api-stubs-default"], + defaults: ["metalava-api-stubs-default"], libs: ["framework-all"], arg_files: ["core/res/AndroidManifest.xml"], args: metalava_framework_docs_args + @@ -259,7 +259,7 @@ droidstubs { droidstubs { name: "module-lib-api-stubs-docs", - defaults: ["metalava-non-updatable-api-stubs-default"], + defaults: ["metalava-api-stubs-default"], libs: ["framework-all"], arg_files: ["core/res/AndroidManifest.xml"], args: metalava_framework_docs_args + diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearch.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearch.java index e779b69750c2..fd201866e702 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearch.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearch.java @@ -16,10 +16,11 @@ package android.app.appsearch; -import android.annotation.CurrentTimeSecondsLong; +import android.annotation.CurrentTimeMillisLong; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.appsearch.AppSearchSchema.PropertyConfig; import android.os.Bundle; import android.util.Log; @@ -32,7 +33,6 @@ import com.google.android.icing.proto.PropertyProto; import java.util.ArrayList; import java.util.Collections; import java.util.Objects; -import java.util.concurrent.TimeUnit; /** * Collection of all AppSearch Document Types. @@ -150,14 +150,14 @@ public final class AppSearch { } /** - * Get the creation timestamp in seconds of the {@link Document}. + * Get the creation timestamp in milliseconds of the {@link Document}. Value will be in the + * {@link System#currentTimeMillis()} time base. * * @hide */ - // TODO(b/143789408) Change seconds to millis with Icing library. - @CurrentTimeSecondsLong - public long getCreationTimestampSecs() { - return mProto.getCreationTimestampSecs(); + @CurrentTimeMillisLong + public long getCreationTimestampMillis() { + return mProto.getCreationTimestampMs(); } /** @@ -381,8 +381,7 @@ public final class AppSearch { mBuilderTypeInstance = (BuilderType) this; mProtoBuilder.setUri(uri).setSchema(schemaType); // Set current timestamp for creation timestamp by default. - setCreationTimestampSecs( - TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())); + setCreationTimestampMillis(System.currentTimeMillis()); } /** @@ -404,14 +403,15 @@ public final class AppSearch { } /** - * Set the creation timestamp in seconds of the {@link Document}. + * Set the creation timestamp in milliseconds of the {@link Document}. Should be set + * using a value obtained from the {@link System#currentTimeMillis()} time base. * * @hide */ @NonNull - public BuilderType setCreationTimestampSecs( - @CurrentTimeSecondsLong long creationTimestampSecs) { - mProtoBuilder.setCreationTimestampSecs(creationTimestampSecs); + public BuilderType setCreationTimestampMillis( + @CurrentTimeMillisLong long creationTimestampMillis) { + mProtoBuilder.setCreationTimestampMs(creationTimestampMillis); return mBuilderTypeInstance; } @@ -575,10 +575,6 @@ public final class AppSearch { * @hide */ public static class Email extends Document { - - /** The name of the schema type for {@link Email} documents.*/ - public static final String SCHEMA_TYPE = "builtin:Email"; - private static final String KEY_FROM = "from"; private static final String KEY_TO = "to"; private static final String KEY_CC = "cc"; @@ -586,14 +582,53 @@ public final class AppSearch { private static final String KEY_SUBJECT = "subject"; private static final String KEY_BODY = "body"; - /** - * Creates a new {@link Email} from the contents of an existing {@link Document}. - * - * @param document The {@link Document} containing the email content. - */ - public Email(@NonNull Document document) { - super(document); - } + /** The name of the schema type for {@link Email} documents.*/ + public static final String SCHEMA_TYPE = "builtin:Email"; + + public static final AppSearchSchema SCHEMA = AppSearchSchema.newBuilder(SCHEMA_TYPE) + .addProperty(AppSearchSchema.newPropertyBuilder(KEY_FROM) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build() + + ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_TO) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_REPEATED) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build() + + ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_CC) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_REPEATED) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build() + + ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_BCC) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_REPEATED) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build() + + ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_SUBJECT) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build() + + ).addProperty(AppSearchSchema.newPropertyBuilder(KEY_BODY) + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .build() + + ).build(); /** * Creates a new {@link Email.Builder}. @@ -605,6 +640,15 @@ public final class AppSearch { } /** + * Creates a new {@link Email} from the contents of an existing {@link Document}. + * + * @param document The {@link Document} containing the email content. + */ + public Email(@NonNull Document document) { + super(document); + } + + /** * Get the from address of {@link Email}. * * @return Returns the subject of {@link Email} or {@code null} if it's not been set yet. @@ -616,10 +660,10 @@ public final class AppSearch { } /** - * Get the destination address of {@link Email}. + * Get the destination addresses of {@link Email}. * - * @return Returns the destination address of {@link Email} or {@code null} if it's not been - * set yet. + * @return Returns the destination addresses of {@link Email} or {@code null} if it's not + * been set yet. * @hide */ @Nullable diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java index 0aa685d6e1bf..66cba52ae03a 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java @@ -26,9 +26,12 @@ import com.android.internal.infra.AndroidFuture; import com.google.android.icing.proto.SchemaProto; import com.google.android.icing.proto.SearchResultProto; +import com.google.android.icing.proto.StatusProto; import com.google.android.icing.protobuf.InvalidProtocolBufferException; +import java.util.Arrays; import java.util.List; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -51,77 +54,123 @@ public class AppSearchManager { } /** - * Sets the schema being used by documents provided to the #put method. + * Sets the schema being used by documents provided to the {@link #putDocuments} method. * - * <p>This operation is performed asynchronously. On success, the provided callback will be - * called with {@code null}. On failure, the provided callback will be called with a - * {@link Throwable} describing the failure. - * - * <p>It is a no-op to set the same schema as has been previously set; this is handled - * efficiently. - * - * <p>AppSearch automatically handles the following types of schema changes: + * <p>The schema provided here is compared to the stored copy of the schema previously supplied + * to {@link #setSchema}, if any, to determine how to treat existing documents. The following + * types of schema modifications are always safe and are made without deleting any existing + * documents: * <ul> - * <li>Addition of new types (No changes to storage or index) - * <li>Removal of an existing type (All documents of the removed type are deleted) - * <li>Addition of new 'optional' property to a type (No changes to storage or index) - * <li>Removal of existing property of any cardinality (All documents reindexed) + * <li>Addition of new types + * <li>Addition of new + * {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL + * OPTIONAL} or + * {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED + * REPEATED} properties to a type + * <li>Changing the cardinality of a data type to be less restrictive (e.g. changing an + * {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL + * OPTIONAL} property into a + * {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED + * REPEATED} property. * </ul> * - * <p>This method will return an error when attempting to make the following types of changes: + * <p>The following types of schema changes are not backwards-compatible. Supplying a schema + * with such changes will result in this call throwing an {@link IllegalSchemaException} + * describing the incompatibility, and the previously set schema will remain active: * <ul> - * <li>Changing the type of an existing property - * <li>Adding a 'required' property + * <li>Removal of an existing type + * <li>Removal of a property from a type + * <li>Changing the data type ({@code boolean}, {@code long}, etc.) of an existing property + * <li>For properties of {@code Document} type, changing the schema type of + * {@code Document Documents} of that property + * <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an + * {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL + * OPTIONAL} property into a + * {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED + * REQUIRED} property). + * <li>Adding a + * {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED + * REQUIRED} property. * </ul> * - * @param schema The schema config for this app. - * @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}. + * <p>If you need to make non-backwards-compatible changes as described above, instead use the + * {@link #setSchema(List, boolean)} method with the {@code forceOverride} parameter set to + * {@code true}. + * + * <p>It is a no-op to set the same schema as has been previously set; this is handled + * efficiently. + * + * @param schemas The schema configs for the types used by the calling app. + * @throws IllegalSchemaException If the provided schema is invalid, or is incompatible with the + * previous schema. * * @hide */ - // TODO(b/143789408): linkify #put after that API is created - // TODO(b/145635424): add a 'force' param to setSchema after the corresponding API is finalized - // in Icing Library - // TODO(b/145635424): Update the documentation above once the Schema mutation APIs of Icing - // Library are finalized - public void setSchema( - @NonNull AppSearchSchema schema, - @NonNull @CallbackExecutor Executor executor, - @NonNull Consumer<? super Throwable> callback) { - SchemaProto schemaProto = schema.getProto(); - byte[] schemaBytes = schemaProto.toByteArray(); + public void setSchema(@NonNull AppSearchSchema... schemas) { + setSchema(Arrays.asList(schemas), /*forceOverride=*/false); + } + + /** + * Sets the schema being used by documents provided to the {@link #putDocuments} method. + * + * <p>This method is similar to {@link #setSchema(AppSearchSchema...)}, except for the + * {@code forceOverride} parameter. If a backwards-incompatible schema is specified but the + * {@code forceOverride} parameter is set to {@code true}, instead of throwing an + * {@link IllegalSchemaException}, all documents which are not compatible with the new schema + * will be deleted and the incompatible schema will be applied. + * + * @param schemas The schema configs for the types used by the calling app. + * @param forceOverride Whether to force the new schema to be applied even if there are + * incompatible changes versus the previously set schema. Documents which are incompatible + * with the new schema will be deleted. + * @throws IllegalSchemaException If the provided schema is invalid, or is incompatible with the + * previous schema and the {@code forceOverride} parameter is set to {@code false}. + * + * @hide + */ + public void setSchema(@NonNull List<AppSearchSchema> schemas, boolean forceOverride) { + // Prepare the merged schema for transmission. + SchemaProto.Builder schemaProtoBuilder = SchemaProto.newBuilder(); + for (AppSearchSchema schema : schemas) { + schemaProtoBuilder.addTypes(schema.getProto()); + } + + // Serialize and send the schema. + // TODO: This should use com.android.internal.infra.RemoteStream or another mechanism to + // avoid binder limits. + byte[] schemaBytes = schemaProtoBuilder.build().toByteArray(); AndroidFuture<Void> future = new AndroidFuture<>(); try { - mService.setSchema(schemaBytes, future); + mService.setSchema(schemaBytes, forceOverride, future); } catch (RemoteException e) { future.completeExceptionally(e); } - future.whenCompleteAsync((noop, err) -> callback.accept(err), executor); + getFutureOrThrow(future); } /** - * Index {@link Document} to AppSearch + * Index {@link android.app.appsearch.AppSearch.Document Documents} into AppSearch. * - * <p>You should not call this method directly; instead, use the {@code AppSearch#put()} API - * provided by JetPack. + * <p>You should not call this method directly; instead, use the + * {@code AppSearch#putDocuments()} API provided by JetPack. * - * <p>The schema should be set via {@link #setSchema} method. + * <p>Each {@link AppSearch.Document Document's} {@code schemaType} field must be set to the + * name of a schema type previously registered via the {@link #setSchema} method. * * @param documents {@link Document Documents} that need to be indexed. * @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}. + * @param callback Callback to receive errors. On success, it will be called with {@code null}. + * On failure, it will be called with a {@link Throwable} describing the failure. */ - public void put(@NonNull List<Document> documents, + public void putDocuments( + @NonNull List<Document> documents, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<? super Throwable> callback) { AndroidFuture<Void> future = new AndroidFuture<>(); for (Document document : documents) { // TODO(b/146386470) batching Document protos try { - mService.put(document.getProto().toByteArray(), future); + mService.putDocument(document.getProto().toByteArray(), future); } catch (RemoteException e) { future.completeExceptionally(e); break; @@ -197,11 +246,11 @@ public class AppSearchManager { callback.accept(null, e); return; } - if (searchResultProto.hasError()) { + if (searchResultProto.getStatus().getCode() != StatusProto.Code.OK) { // TODO(sidchhabra): Add better exception handling. callback.accept( null, - new RuntimeException(searchResultProto.getError().getErrorMessage())); + new RuntimeException(searchResultProto.getStatus().getMessage())); return; } SearchResults searchResults = new SearchResults(searchResultProto); @@ -220,4 +269,21 @@ public class AppSearchManager { future.completeExceptionally(e); } } + + private static <T> T getFutureOrThrow(@NonNull AndroidFuture<T> future) { + try { + return future.get(); + } catch (Throwable e) { + if (e instanceof ExecutionException) { + e = e.getCause(); + } + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + if (e instanceof Error) { + throw (Error) e; + } + throw new RuntimeException(e); + } + } } diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java index 7e5f187b88c9..1d54dc4971a6 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java @@ -18,41 +18,38 @@ package android.app.appsearch; import android.annotation.IntDef; import android.annotation.NonNull; +import android.util.ArraySet; import com.android.internal.annotations.VisibleForTesting; import com.google.android.icing.proto.PropertyConfigProto; -import com.google.android.icing.proto.SchemaProto; import com.google.android.icing.proto.SchemaTypeConfigProto; +import com.google.android.icing.proto.TermMatchType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Set; /** - * Representation of the AppSearch Schema. + * The AppSearch Schema for a particular type of document. * - * <p>The schema is the set of document types, properties, and config (like tokenization type) - * understood by AppSearch for this app. + * <p>For example, an e-mail message or a music recording could be a schema type. + * + * <p>The schema consists of type information, properties, and config (like tokenization type). * * @hide */ public final class AppSearchSchema { - private final SchemaProto mProto; + private final SchemaTypeConfigProto mProto; - private AppSearchSchema(SchemaProto proto) { + private AppSearchSchema(SchemaTypeConfigProto proto) { mProto = proto; } /** Creates a new {@link AppSearchSchema.Builder}. */ @NonNull - public static AppSearchSchema.Builder newBuilder() { - return new AppSearchSchema.Builder(); - } - - /** Creates a new {@link SchemaType.Builder}. */ - @NonNull - public static SchemaType.Builder newSchemaTypeBuilder(@NonNull String typeName) { - return new SchemaType.Builder(typeName); + public static AppSearchSchema.Builder newBuilder(@NonNull String typeName) { + return new AppSearchSchema.Builder(typeName); } /** Creates a new {@link PropertyConfig.Builder}. */ @@ -61,32 +58,34 @@ public final class AppSearchSchema { return new PropertyConfig.Builder(propertyName); } - /** Creates a new {@link IndexingConfig.Builder}. */ - @NonNull - public static IndexingConfig.Builder newIndexingConfigBuilder() { - return new IndexingConfig.Builder(); - } - /** - * Returns the schema proto populated by the {@link AppSearchSchema} builders. + * Returns the {@link SchemaTypeConfigProto} populated by this builder. * @hide */ @NonNull @VisibleForTesting - public SchemaProto getProto() { + public SchemaTypeConfigProto getProto() { return mProto; } + @Override + public String toString() { + return mProto.toString(); + } + /** Builder for {@link AppSearchSchema objects}. */ public static final class Builder { - private final SchemaProto.Builder mProtoBuilder = SchemaProto.newBuilder(); + private final SchemaTypeConfigProto.Builder mProtoBuilder = + SchemaTypeConfigProto.newBuilder(); - private Builder() {} + private Builder(@NonNull String typeName) { + mProtoBuilder.setSchemaType(typeName); + } - /** Adds a supported type to this app's AppSearch schema. */ + /** Adds a property to the given type. */ @NonNull - public AppSearchSchema.Builder addType(@NonNull SchemaType schemaType) { - mProtoBuilder.addTypes(schemaType.mProto); + public AppSearchSchema.Builder addProperty(@NonNull PropertyConfig propertyConfig) { + mProtoBuilder.addProperties(propertyConfig.mProto); return this; } @@ -97,47 +96,15 @@ public final class AppSearchSchema { */ @NonNull public AppSearchSchema build() { - return new AppSearchSchema(mProtoBuilder.build()); - } - } - - /** - * Represents a type of a document. - * - * <p>For example, an e-mail message or a music recording could be a schema type. - */ - public static final class SchemaType { - private final SchemaTypeConfigProto mProto; - - private SchemaType(SchemaTypeConfigProto proto) { - mProto = proto; - } - - /** Builder for {@link SchemaType} objects. */ - public static final class Builder { - private final SchemaTypeConfigProto.Builder mProtoBuilder = - SchemaTypeConfigProto.newBuilder(); - - private Builder(@NonNull String typeName) { - mProtoBuilder.setSchemaType(typeName); - } - - /** Adds a property to the given type. */ - @NonNull - public SchemaType.Builder addProperty(@NonNull PropertyConfig propertyConfig) { - mProtoBuilder.addProperties(propertyConfig.mProto); - return this; - } - - /** - * Constructs a new {@link SchemaType} from the contents of this builder. - * - * <p>After calling this method, the builder must no longer be used. - */ - @NonNull - public SchemaType build() { - return new SchemaType(mProtoBuilder.build()); + Set<String> propertyNames = new ArraySet<>(); + for (PropertyConfigProto propertyConfigProto : mProtoBuilder.getPropertiesList()) { + if (!propertyNames.add(propertyConfigProto.getPropertyName())) { + throw new IllegalSchemaException( + "Property defined more than once: " + + propertyConfigProto.getPropertyName()); + } } + return new AppSearchSchema(mProtoBuilder.build()); } } @@ -197,12 +164,71 @@ public final class AppSearchSchema { /** Exactly one value [1]. */ public static final int CARDINALITY_REQUIRED = 3; + /** Encapsulates the configurations on how AppSearch should query/index these terms. */ + @IntDef(prefix = {"INDEXING_TYPE_"}, value = { + INDEXING_TYPE_NONE, + INDEXING_TYPE_EXACT_TERMS, + INDEXING_TYPE_PREFIXES, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface IndexingType {} + + /** + * Content in this property will not be tokenized or indexed. + * + * <p>Useful if the data type is not made up of terms (e.g. + * {@link PropertyConfig#DATA_TYPE_DOCUMENT} or {@link PropertyConfig#DATA_TYPE_BYTES} + * type). All the properties inside the nested property won't be indexed regardless of the + * value of {@code indexingType} for the nested properties. + */ + public static final int INDEXING_TYPE_NONE = 0; + + /** + * Content in this property should only be returned for queries matching the exact tokens + * appearing in this property. + * + * <p>Ex. A property with "fool" should NOT match a query for "foo". + */ + public static final int INDEXING_TYPE_EXACT_TERMS = 1; + + /** + * Content in this property should be returned for queries that are either exact matches or + * query matches of the tokens appearing in this property. + * + * <p>Ex. A property with "fool" <b>should</b> match a query for "foo". + */ + public static final int INDEXING_TYPE_PREFIXES = 2; + + /** Configures how tokens should be extracted from this property. */ + // NOTE: The integer values of these constants must match the proto enum constants in + // com.google.android.icing.proto.IndexingConfig.TokenizerType.Code. + @IntDef(prefix = {"TOKENIZER_TYPE_"}, value = { + TOKENIZER_TYPE_NONE, + TOKENIZER_TYPE_PLAIN, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TokenizerType {} + + /** + * It is only valid for tokenizer_type to be 'NONE' if the data type is + * {@link PropertyConfig#DATA_TYPE_DOCUMENT}. + */ + public static final int TOKENIZER_TYPE_NONE = 0; + + /** Tokenization for plain text. */ + public static final int TOKENIZER_TYPE_PLAIN = 1; + private final PropertyConfigProto mProto; private PropertyConfig(PropertyConfigProto proto) { mProto = proto; } + @Override + public String toString() { + return mProto.toString(); + } + /** * Builder for {@link PropertyConfig}. * @@ -217,11 +243,14 @@ public final class AppSearchSchema { * is also required. */ public static final class Builder { - private final PropertyConfigProto.Builder mProtoBuilder = + private final PropertyConfigProto.Builder mPropertyConfigProto = PropertyConfigProto.newBuilder(); + private final com.google.android.icing.proto.IndexingConfig.Builder + mIndexingConfigProto = + com.google.android.icing.proto.IndexingConfig.newBuilder(); private Builder(String propertyName) { - mProtoBuilder.setPropertyName(propertyName); + mPropertyConfigProto.setPropertyName(propertyName); } /** @@ -236,7 +265,7 @@ public final class AppSearchSchema { if (dataTypeProto == null) { throw new IllegalArgumentException("Invalid dataType: " + dataType); } - mProtoBuilder.setDataType(dataTypeProto); + mPropertyConfigProto.setDataType(dataTypeProto); return this; } @@ -248,7 +277,7 @@ public final class AppSearchSchema { */ @NonNull public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) { - mProtoBuilder.setSchemaType(schemaType); + mPropertyConfigProto.setSchemaType(schemaType); return this; } @@ -264,19 +293,44 @@ public final class AppSearchSchema { if (cardinalityProto == null) { throw new IllegalArgumentException("Invalid cardinality: " + cardinality); } - mProtoBuilder.setCardinality(cardinalityProto); + mPropertyConfigProto.setCardinality(cardinalityProto); return this; } /** - * Configures how this property should be indexed. - * - * <p>If this is not supplied, the property will not be indexed at all. + * Configures how a property should be indexed so that it can be retrieved by queries. */ @NonNull - public PropertyConfig.Builder setIndexingConfig( - @NonNull IndexingConfig indexingConfig) { - mProtoBuilder.setIndexingConfig(indexingConfig.mProto); + public PropertyConfig.Builder setIndexingType(@IndexingType int indexingType) { + TermMatchType.Code termMatchTypeProto; + switch (indexingType) { + case INDEXING_TYPE_NONE: + termMatchTypeProto = TermMatchType.Code.UNKNOWN; + break; + case INDEXING_TYPE_EXACT_TERMS: + termMatchTypeProto = TermMatchType.Code.EXACT_ONLY; + break; + case INDEXING_TYPE_PREFIXES: + termMatchTypeProto = TermMatchType.Code.PREFIX; + break; + default: + throw new IllegalArgumentException("Invalid indexingType: " + indexingType); + } + mIndexingConfigProto.setTermMatchType(termMatchTypeProto); + return this; + } + + /** Configures how this property should be tokenized (split into words). */ + @NonNull + public PropertyConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) { + com.google.android.icing.proto.IndexingConfig.TokenizerType.Code + tokenizerTypeProto = + com.google.android.icing.proto.IndexingConfig + .TokenizerType.Code.forNumber(tokenizerType); + if (tokenizerTypeProto == null) { + throw new IllegalArgumentException("Invalid tokenizerType: " + tokenizerType); + } + mIndexingConfigProto.setTokenizerType(tokenizerTypeProto); return this; } @@ -290,136 +344,25 @@ public final class AppSearchSchema { */ @NonNull public PropertyConfig build() { - if (mProtoBuilder.getDataType() == PropertyConfigProto.DataType.Code.UNKNOWN) { + mPropertyConfigProto.setIndexingConfig(mIndexingConfigProto); + // TODO(b/147692920): Send the schema to Icing Lib for official validation, instead + // of partially reimplementing some of the validation Icing does here. + if (mPropertyConfigProto.getDataType() + == PropertyConfigProto.DataType.Code.UNKNOWN) { throw new IllegalSchemaException("Missing field: dataType"); } - if (mProtoBuilder.getSchemaType().isEmpty() - && mProtoBuilder.getDataType() - == PropertyConfigProto.DataType.Code.DOCUMENT) { + if (mPropertyConfigProto.getSchemaType().isEmpty() + && mPropertyConfigProto.getDataType() + == PropertyConfigProto.DataType.Code.DOCUMENT) { throw new IllegalSchemaException( "Missing field: schemaType (required for configs with " + "dataType = DOCUMENT)"); } - if (mProtoBuilder.getCardinality() + if (mPropertyConfigProto.getCardinality() == PropertyConfigProto.Cardinality.Code.UNKNOWN) { throw new IllegalSchemaException("Missing field: cardinality"); } - return new PropertyConfig(mProtoBuilder.build()); - } - } - } - - /** Configures how a property should be indexed so that it can be retrieved by queries. */ - public static final class IndexingConfig { - /** Encapsulates the configurations on how AppSearch should query/index these terms. */ - // NOTE: The integer values of these constants must match the proto enum constants in - // com.google.android.icing.proto.TermMatchType.Code. - @IntDef(prefix = {"TERM_MATCH_TYPE_"}, value = { - TERM_MATCH_TYPE_UNKNOWN, - TERM_MATCH_TYPE_EXACT_ONLY, - TERM_MATCH_TYPE_PREFIX, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface TermMatchType {} - - /** - * Content in this property will not be tokenized or indexed. - * - * <p>Useful if the data type is not made up of terms (e.g. - * {@link PropertyConfig#DATA_TYPE_DOCUMENT} or {@link PropertyConfig#DATA_TYPE_BYTES} - * type). All the properties inside the nested property won't be indexed regardless of the - * value of {@code termMatchType} for the nested properties. - */ - public static final int TERM_MATCH_TYPE_UNKNOWN = 0; - - /** - * Content in this property should only be returned for queries matching the exact tokens - * appearing in this property. - * - * <p>Ex. A property with "fool" should NOT match a query for "foo". - */ - public static final int TERM_MATCH_TYPE_EXACT_ONLY = 1; - - /** - * Content in this property should be returned for queries that are either exact matches or - * query matches of the tokens appearing in this property. - * - * <p>Ex. A property with "fool" <b>should</b> match a query for "foo". - */ - public static final int TERM_MATCH_TYPE_PREFIX = 2; - - /** Configures how tokens should be extracted from this property. */ - // NOTE: The integer values of these constants must match the proto enum constants in - // com.google.android.icing.proto.IndexingConfig.TokenizerType.Code. - @IntDef(prefix = {"TOKENIZER_TYPE_"}, value = { - TOKENIZER_TYPE_NONE, - TOKENIZER_TYPE_PLAIN, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface TokenizerType {} - - /** - * It is only valid for tokenizer_type to be 'NONE' if the data type is - * {@link PropertyConfig#DATA_TYPE_DOCUMENT}. - */ - public static final int TOKENIZER_TYPE_NONE = 0; - - /** Tokenization for plain text. */ - public static final int TOKENIZER_TYPE_PLAIN = 1; - - private final com.google.android.icing.proto.IndexingConfig mProto; - - private IndexingConfig(com.google.android.icing.proto.IndexingConfig proto) { - mProto = proto; - } - - /** - * Builder for {@link IndexingConfig} objects. - * - * <p>You may skip adding an {@link IndexingConfig} for a property, which is equivalent to - * an {@link IndexingConfig} having {@code termMatchType} equal to - * {@link #TERM_MATCH_TYPE_UNKNOWN}. In this case the property will not be indexed. - */ - public static final class Builder { - private final com.google.android.icing.proto.IndexingConfig.Builder mProtoBuilder = - com.google.android.icing.proto.IndexingConfig.newBuilder(); - - private Builder() {} - - /** Configures how the content of this property should be matched in the index. */ - @NonNull - public IndexingConfig.Builder setTermMatchType(@TermMatchType int termMatchType) { - com.google.android.icing.proto.TermMatchType.Code termMatchTypeProto = - com.google.android.icing.proto.TermMatchType.Code.forNumber(termMatchType); - if (termMatchTypeProto == null) { - throw new IllegalArgumentException("Invalid termMatchType: " + termMatchType); - } - mProtoBuilder.setTermMatchType(termMatchTypeProto); - return this; - } - - /** Configures how this property should be tokenized (split into words). */ - @NonNull - public IndexingConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) { - com.google.android.icing.proto.IndexingConfig.TokenizerType.Code - tokenizerTypeProto = - com.google.android.icing.proto.IndexingConfig - .TokenizerType.Code.forNumber(tokenizerType); - if (tokenizerTypeProto == null) { - throw new IllegalArgumentException("Invalid tokenizerType: " + tokenizerType); - } - mProtoBuilder.setTokenizerType(tokenizerTypeProto); - return this; - } - - /** - * Constructs a new {@link IndexingConfig} from the contents of this builder. - * - * <p>After calling this method, the builder must no longer be used. - */ - @NonNull - public IndexingConfig build() { - return new IndexingConfig(mProtoBuilder.build()); + return new PropertyConfig(mPropertyConfigProto.build()); } } } diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl index 22250f4cc3ec..c9c5d7fbfda4 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl @@ -22,13 +22,25 @@ interface IAppSearchManager { /** * Sets the schema. * - * @param schemaProto serialized SchemaProto + * @param schemaBytes Serialized SchemaProto. + * @param forceOverride Whether to apply the new schema even if it is incompatible. All + * incompatible documents will be deleted. * @param callback {@link AndroidFuture}<{@link Void}>. Will be completed with - * {@code null} upon successful completion of the setSchema call, or completed exceptionally - * if setSchema fails. + * {@code null} upon successful completion of the setSchema call, or completed + * exceptionally if setSchema fails. */ - void setSchema(in byte[] schemaProto, in AndroidFuture callback); - void put(in byte[] documentBytes, in AndroidFuture callback); + void setSchema(in byte[] schemaBytes, boolean forceOverride, in AndroidFuture callback); + + /** + * Inserts a document into the index. + * + * @param documentBytes serialized DocumentProto + * @param callback {@link AndroidFuture}<{@link Void}>. Will be completed with + * {@code null} upon successful completion of the put call, or completed exceptionally if + * put fails. + */ + void putDocument(in byte[] documentBytes, in AndroidFuture callback); + /** * Searches a document based on a given query string. * diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java index ec4258d08655..d763103f1217 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java @@ -60,7 +60,7 @@ public final class SearchResults { public AppSearch.Document getDocument() { return AppSearch.Document.newBuilder(mResultProto.getDocument().getUri(), mResultProto.getDocument().getSchema()) - .setCreationTimestampSecs(mResultProto.getDocument().getCreationTimestampSecs()) + .setCreationTimestampMillis(mResultProto.getDocument().getCreationTimestampMs()) .setScore(mResultProto.getDocument().getScore()) .build(); } 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 f63abd945bdd..6929202445e9 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -28,6 +28,7 @@ import com.android.server.appsearch.impl.AppSearchImpl; import com.android.server.appsearch.impl.FakeIcing; import com.android.server.appsearch.impl.ImplInstanceManager; +import com.google.android.icing.proto.DocumentProto; import com.google.android.icing.proto.SchemaProto; import com.google.android.icing.proto.SearchResultProto; import com.google.android.icing.proto.SearchSpecProto; @@ -52,7 +53,7 @@ public class AppSearchManagerService extends SystemService { private class Stub extends IAppSearchManager.Stub { @Override - public void setSchema(byte[] schemaBytes, AndroidFuture callback) { + public void setSchema(byte[] schemaBytes, boolean forceOverride, AndroidFuture callback) { Preconditions.checkNotNull(schemaBytes); Preconditions.checkNotNull(callback); int callingUid = Binder.getCallingUidOrThrow(); @@ -61,7 +62,7 @@ public class AppSearchManagerService extends SystemService { try { SchemaProto schema = SchemaProto.parseFrom(schemaBytes); AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - impl.setSchema(callingUid, schema); + impl.setSchema(callingUid, schema, forceOverride); callback.complete(null); } catch (Throwable t) { callback.completeExceptionally(t); @@ -71,11 +72,21 @@ public class AppSearchManagerService extends SystemService { } @Override - public void put(byte[] documentBytes, AndroidFuture callback) { + public void putDocument(byte[] documentBytes, AndroidFuture callback) { + Preconditions.checkNotNull(documentBytes); + Preconditions.checkNotNull(callback); + int callingUid = Binder.getCallingUidOrThrow(); + int callingUserId = UserHandle.getUserId(callingUid); + long callingIdentity = Binder.clearCallingIdentity(); try { - throw new UnsupportedOperationException("Put document not yet implemented"); + DocumentProto document = DocumentProto.parseFrom(documentBytes); + AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); + impl.putDocument(callingUid, document); + callback.complete(null); } catch (Throwable t) { callback.completeExceptionally(t); + } finally { + Binder.restoreCallingIdentity(callingIdentity); } } // TODO(sidchhabra):Init FakeIcing properly. diff --git a/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java index 7c97b0b8cf30..04b4b1427328 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java @@ -22,7 +22,9 @@ import android.content.Context; import com.android.internal.annotations.VisibleForTesting; +import com.google.android.icing.proto.DocumentProto; import com.google.android.icing.proto.PropertyConfigProto; +import com.google.android.icing.proto.PropertyProto; import com.google.android.icing.proto.SchemaProto; import com.google.android.icing.proto.SchemaTypeConfigProto; @@ -45,8 +47,10 @@ public final class AppSearchImpl { * * @param callingUid The uid of the app calling AppSearch. * @param origSchema The schema to set for this app. + * @param forceOverride Whether to force-apply the schema even if it is incompatible. Documents + * which do not comply with the new schema will be deleted. */ - public void setSchema(int callingUid, @NonNull SchemaProto origSchema) { + public void setSchema(int callingUid, @NonNull SchemaProto origSchema, boolean forceOverride) { // Rewrite schema type names to include the calling app's package and uid. String typePrefix = getTypePrefix(callingUid); SchemaProto.Builder schemaBuilder = origSchema.toBuilder(); @@ -93,6 +97,60 @@ public final class AppSearchImpl { } /** + * Adds a document to the AppSearch index. + * + * @param callingUid The uid of the app calling AppSearch. + * @param origDocument The document to index. + */ + public void putDocument(int callingUid, @NonNull DocumentProto origDocument) { + // Rewrite the type names to include the app's prefix + String typePrefix = getTypePrefix(callingUid); + DocumentProto.Builder documentBuilder = origDocument.toBuilder(); + rewriteDocumentTypes(typePrefix, documentBuilder); + mFakeIcing.put(documentBuilder.build()); + } + + /** + * Rewrites all types mentioned anywhere in {@code documentBuilder} to prepend + * {@code typePrefix}. + * + * @param typePrefix The prefix to add + * @param documentBuilder The document to mutate + */ + @VisibleForTesting + void rewriteDocumentTypes( + @NonNull String typePrefix, + @NonNull DocumentProto.Builder documentBuilder) { + // Rewrite the type name to include the app's prefix + String newSchema = typePrefix + documentBuilder.getSchema(); + documentBuilder.setSchema(newSchema); + + // Add namespace. If we ever allow users to set their own namespaces, this will have + // to change to prepend the prefix instead of setting the whole namespace. We will also have + // to store the namespaces in a map similar to the type map so we can rewrite queries with + // empty namespaces. + documentBuilder.setNamespace(typePrefix); + + // Recurse into derived documents + for (int propertyIdx = 0; + propertyIdx < documentBuilder.getPropertiesCount(); + propertyIdx++) { + int documentCount = documentBuilder.getProperties(propertyIdx).getDocumentValuesCount(); + if (documentCount > 0) { + PropertyProto.Builder propertyBuilder = + documentBuilder.getProperties(propertyIdx).toBuilder(); + for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) { + DocumentProto.Builder derivedDocumentBuilder = + propertyBuilder.getDocumentValues(documentIdx).toBuilder(); + rewriteDocumentTypes(typePrefix, derivedDocumentBuilder); + propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder); + } + documentBuilder.setProperties(propertyIdx, propertyBuilder); + } + } + } + + /** * Returns a type prefix in a format like {@code com.example.package@1000/} or * {@code com.example.sharedname:5678@1000/}. */ diff --git a/apex/extservices/Android.bp b/apex/extservices/Android.bp new file mode 100644 index 000000000000..c89f694c09d2 --- /dev/null +++ b/apex/extservices/Android.bp @@ -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. + +apex { + name: "com.android.extservices", + defaults: ["com.android.extservices-defaults"], + manifest: "apex_manifest.json", +} + +apex_defaults { + name: "com.android.extservices-defaults", + key: "com.android.extservices.key", + certificate: ":com.android.extservices.certificate", + apps: ["ExtServices"], +} + +apex_key { + name: "com.android.extservices.key", + public_key: "com.android.extservices.avbpubkey", + private_key: "com.android.extservices.pem", +} + +android_app_certificate { + name: "com.android.extservices.certificate", + certificate: "com.android.extservices", +} diff --git a/apex/extservices/apex_manifest.json b/apex/extservices/apex_manifest.json new file mode 100644 index 000000000000..7ba21575df4a --- /dev/null +++ b/apex/extservices/apex_manifest.json @@ -0,0 +1,4 @@ +{ + "name": "com.android.extservices", + "version": 1 +} diff --git a/apex/extservices/com.android.extservices.avbpubkey b/apex/extservices/com.android.extservices.avbpubkey Binary files differnew file mode 100644 index 000000000000..f37d3e4a14d4 --- /dev/null +++ b/apex/extservices/com.android.extservices.avbpubkey diff --git a/apex/extservices/com.android.extservices.pem b/apex/extservices/com.android.extservices.pem new file mode 100644 index 000000000000..7bfbd34ff9b9 --- /dev/null +++ b/apex/extservices/com.android.extservices.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAuYshVDiRkt3tmBhqcWkKOm5GcviKpLbHSPpYQDHGDwS0dqqL +SqAd1/BgT/bVVtUkAciFApPnXn96WhNYCypptyC5FHCxM21uBCGmow+3WermD++w +5dQk4QP2ONPIpG+KzOWBl9SiBud4SpOHDyr0JycBsrXS89Tln9kAsTDuDEFfXL/J +8cX/S3IUwhPV0pAlgUIHdDp0DGFjZaJlEZBZ+HmImriC/AUNUMVb5lfbczXOEZPF +0A9+JzYschfXUxn8nu1N7RN5GDbq+chszx1FMVhuFUheukkd4dLNSDl0O0RlUnD+ +C/xz1ilDzEVZhnMtMnxS9oJ8bA/HUVMfsFnaQbgGmQ0CcxFxnfbYyGXGG1H+b8vA +MTVQi5rZXG2p+VgHIAKVrYmpETVnRPgoMqp18KuGtp5SDngi13G3YEzS7iFbqfYh +6iW2G974nD/Dq0cSire8Oljd9PEaMCMZiP5PTFJp0G/mtw7ROoyZqsSM6rX3XVTo +Y5dBmBMctSJ8rgDMi0ZNvRH+rq/E5+RT6yMAJ7DDbOJzBnQ3IIoGn8NzUT3P1FCB +HYEp1U2N7QNirIQMAuVz3IlHae9N1kl3eGAO6f2CjV7vZmFpDeWw+KSYs71mRkOb +WBgl6D9FFq4u1azrU3AwV0dj3x1eU6yVnKUy1J7ppF/mcR+VzH7ThzTdV7cCAwEA +AQKCAgEApWFU2Mv/PYhg0bPZlLLKsiA+3RWaBo0AfpTd+oIjBpnr/OWweFjVoPcZ +8cyShe4/RPOlUxHgJcO8m/MoA/PO/LLHJWf5GlzMthQEgs1sYVJVtBiydXitUn+E +hUyIR8FAV7et1lZqAXtqJhbvSF7B9u/2vIMCv+GgtuTmkAmL9RKD3Jj6eG1CS84o +oICrkx52v4rKOBgt/icEQMAKFCi1eRti3n3eCqK6JqdzbZIcAcoQnmw34mccy/im +jx+fBuxf1oywa8NyqVmyAehazBVL6lrm7ENwY9zuLK4H2fuUFYu2QFCEsMxZt6da +TgX2cTfSLnDQRfcyzeMWhu9vjHHabjpLNjiCKhIhGyO0rO1rtea8ajZHgM/2sxXq +6gLynW0dlatlxmjANlN9WQPGNdzvcIFJ0TLnI4mlJnWpqCsN9iW1d4ey13WiZUVR +DgtnR60zao+LRCCM4D3cuVLq0DjL2BlHGXnOPK/LpQG1LbI1TroZpgSEHSZlQRzT +ql9txgNqTHxijXuPL2VhhwhW7cqDoO8sLwV3BqDMIH56U0cbUBiSA/G9fKeI/DEG +i7LcrMgrBk+xnuAWoFHuzfBMAdD9i3kYyk+41tOmcza2TNJgxadVYp5woHFvYvS/ +GKaNiRz0XmcijO5Ir0yxgCq21BdkWzo5zVrTFABiKeR7YXiee8kCggEBAOeULWgR +spolJJrACWJspRvKb9FGnbGiYOnCGJoAc751kuXmNxoyWnEwgcjrSEoayNPUfOtz +IgA+twqjgl0Zec2XFPfUcgWUBrrvvUEV4NIH5ibaR7ezHGeovCWs9XoDyzHHvhDr +c6T5kXFZ60rS5h6LGUnE1hkHFJoHuTIBbn9j7eIbri8S71i7HWQ04s4KuQ+Bwbxm +UnkEhbc+zMWHXfXy7rx4/eEZcZwtEybIORcHXYNPGeqMfOlcEMHpKEOi+NvDA6cp +vTaTSwJ6ZBgYh7Tw3bNgRxSknaIhcGwMD0ojStjC5xzXT1Zr2Z3GXwYvOGcq3MeZ +z+V2cx5xuwyp7R0CggEBAM0cKKNZEZwi/1zBPUDMFB4iJoX12BxQX6e5wdlHGXgF +XeZwCnaIxOxMDxH79M5Svmpdu/jkUijI/pRvcE1iohFyIBvTUSDmlAoy4keXqMEQ +M2hA+TwVA3JLmMcV8HKy/MFlwwKJB1JDcoxGjnXsM5UjVTD2jilO7vlJZs3+0ws0 +R7qzRT3ED25QTpZyDYcKE2otc5bzIZG3yAaJtWd3NugWsKpxDgr2RFUGJiHBq72n +48FkSjfgaDTn83zYcPvS0Uykb2ho8G/N+EurstL41n3nQo0I7FLbyptOopDDwsSp +Ndejn08NVAQ+xFAafOyqHkA3Ytpl0QCZDpMBuLdvw+MCggEAOVMt1kgjPRMat4/4 +ArxANtvqyBRB7vnyIYthiaW5ARmbrntJgpuaVdCbIABWGbn9oqpD7gjHDuZ3axPE +roUi6KiQkTSusQDOlbHI2Haw+2znJRD9ldSpoGNdh7oD3htYTk9Sll+ideEthrCq +lRAV1NO8A83M7c8Z43Mr/dvq3XAAL+uIN7DpPL687NRGnJh87QDC039ExR5Ad3b9 +O5xhvwNO46rTtcgVnoJt7ji8IR46oMmQ8cWrGh0nLMkppWyPS98/ZT7ozryxYcCo +TGquFTVWvBOGJO8G8l5ytNxbYI/R9Exy52nJAuyZpvu3BBHmVWt/0Y0asIOcxZmD +owPhZQKCAQAfWAFBzReq05JQe1s/7q/YVwGqEQKgeQvVFsbvzDSxKajK0S5YJNhq +/8iByA4GBZEBsidKhqGjh+uXhVwVB1Ca9+S+O9G3BGV1FYeMxzlLn40rjlpH+zIW +okTLj6e5724+o61kUspioNn9Y77beGf9j3OyUsswttZAFB54tktL+AZKGqEnKjHt +eqo3xWAZ1clXvXBfjfIAUaRok1y8XfRvDSCcO0CZHj8c+x6SpAT5q5FbeVb6KPnj +s9p6ppzFbtb7Llm0C+1KOKCL98YRBWPJw7Bg2w86LkpM53xiQPgfk3gd5uwuaWwA +ZhMb5qBWjjynNY+OrmZ8/+bBQk8XASZfAoIBAFkHOnZOD1JJQ0QvaJ9tuCgHi216 +I8QPMMTdm3ZEDHSYMNwl7ayeseBcmB2zaqBKYz75qcU0SK4lnZkR2wIpbsHZNSVM +J0WpN6r9G4JdnVi11J04RsfSMjCUr/PTVMmPvw8xPHrCxkJmB+d56olSE80I1Jrx +djCv1LtSsT10W7FIcY82/cOi4xxGLOA70lDCf+szofQgVP8WvuOA1YaFw98ca8zc +A401CyNexk24/c3d6C19YW/MppdE0uGMxL/oHsPgwkZAf6LmvF/UF71PsBUEniLc +YFaJl3wn1cPfBBo9L4sZzyP2qokL8YHdg+wW7b4IOsYwbeqceBvqPtcUUPs= +-----END RSA PRIVATE KEY----- diff --git a/apex/extservices/com.android.extservices.pk8 b/apex/extservices/com.android.extservices.pk8 Binary files differnew file mode 100644 index 000000000000..59585a212592 --- /dev/null +++ b/apex/extservices/com.android.extservices.pk8 diff --git a/apex/extservices/com.android.extservices.x509.pem b/apex/extservices/com.android.extservices.x509.pem new file mode 100644 index 000000000000..e0343b81d279 --- /dev/null +++ b/apex/extservices/com.android.extservices.x509.pem @@ -0,0 +1,36 @@ +-----BEGIN CERTIFICATE----- +MIIGLTCCBBWgAwIBAgIUdqdMmx/5OsCP3Ew3/hcr7+1ACHEwDQYJKoZIhvcNAQEL +BQAwgaQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH +DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy +b2lkMSAwHgYDVQQDDBdjb20uYW5kcm9pZC5leHRzZXJ2aWNlczEiMCAGCSqGSIb3 +DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAgFw0yMDAxMTcxMDIxMzZaGA80NzU3 +MTIxMzEwMjEzNlowgaQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh +MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD +VQQLDAdBbmRyb2lkMSAwHgYDVQQDDBdjb20uYW5kcm9pZC5leHRzZXJ2aWNlczEi +MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBANKaSeLGaFRRt779vAtTfG3t2aQZrWOByUYc7yUN +RdmJqWxU47OL5urYmanWPbz2f972Q9oi8x+8y4ny9SEY3wg0pUbzvKNTXpkxWyG1 +HE2C2zTfzuDDLpDIf2usWynt1wLVhpYC3k+7Yv2vOIK5dKkezh6PfdKmsbDae5DE +d22tTSYZ5KwNpIWrgQle26cRG5sqhAFdkpgGMF00Huz06cjUoTjs2sNSlXTRBOTP +CCy8UoRjBivQZkwHbddfsn+Z22ARPG8JDg/n4mEi8C0T6bJeQeirSPkBCkD6Djgq +7RddJ2eLYZII8l8r6A6x+6cnTkXHaV5g3LUwPvi8XEn9IUuT9WJNRje/vfYLycTQ +kP415CZMxDvsi1Ul4YsbL3enE89ryGMTpVZPogch/36DG5Sye28yISItNUy3urJa +OXbg7mh+MwPd4bQaW4CJk+AUweKaF4aV0SZFT+nCewL4xLdGdy889KazlW98NqtK +hOSxIg1jHkZq48ajuq2A+ns1yDKt1l0f9IYCz3mz/IXInokbkjPvHahJTJ+OMHXO +THD8e5gBzcK841jJk+H3EsIYOHsp66uy2IgEHN+9pAS6vI0xfrXOYuKzuSL3oxcV +FlVTimt4xokMMerdcW4KD+MC5NFEip4DUS4JKCyG0wRI3ffEs9Zcpxi3QSibrjLW +rz+hAgMBAAGjUzBRMB0GA1UdDgQWBBTP2AhZzEUUgtAFlkaMaq+RvY06fDAfBgNV +HSMEGDAWgBTP2AhZzEUUgtAFlkaMaq+RvY06fDAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQCbwtfo37j62Sudmt32PCfRN/r5ZNDNNA2JhR8uDUmX +xXfF5YfDvSKsNLiQKcDagu6a+0C+QnzXHXCBlXZFrTJ8NAVMlmqdHGwoFoYMfJZH +R1lCTidyFMoMLJ8GRGPJjzDkKnOeAqKMCtKvXoH2r12+JB2/ov4ooLREu/wPkEXT +OymkyWNP5XLQTKWqfEQyXXFpuwZ+m35Wkr0Fm92mZeJpVeIZPK7M7aK3zyoj7XJP +YLMsR/AQs8OULdpfNMddAuN3ndlYu03LZlsF6LG5bduaDDcESJ5hdJrgBa/NBKRU +IbS+q/6WAjYKMNRT/fPGew4wUzlWKi1Ihdk79oaqKKijE1b2JSJD1/SEYiBf+JPE +bXobUrMbBwFpdhT+YLMF9FsuPQKsUIONaWiO4QcQoY/rQwGxPP6fV8ZbBrUWJewj +MpSdU9foZNa/TmOAgfS/JxH+nXnG4+H1m8mdNBsxvsYmF2ZuGb/jdEeA2cuHIJDZ +FJeWwCFxzlCGZJaUsxsnZByADBuufUVaO/9gGs0YQC/JP1i9hK4DyZdKwZpXdLi2 +Nw27Qma4WEIZnMb6Rgk1nTV+7ALcOSIhGgFOOeDTuCGfnEcz2coai5fbD/K6Q7Xu +IRNyxHQjheZPdei2x912Ex/KqKGfaFaZJxrvCSKdhzxcTFIsO4JuZs+SDpRTKcI7 +Cw== +-----END CERTIFICATE----- diff --git a/apex/permission/framework/Android.bp b/apex/permission/framework/Android.bp index 8b03da3a9530..09571a1cd111 100644 --- a/apex/permission/framework/Android.bp +++ b/apex/permission/framework/Android.bp @@ -26,7 +26,13 @@ java_library { srcs: [ ":framework-permission-sources", ], - sdk_version: "system_current", + // TODO(b/146758669): Use "system_current" after nullability annotations are system APIs. + sdk_version: "core_current", + libs: [ + "framework-annotations-lib", + // TODO(b/146758669): Remove this line after nullability annotations are system APIs. + "android_system_stubs_current", + ], apex_available: [ "com.android.permission", "test_com.android.permission", diff --git a/apex/permission/service/Android.bp b/apex/permission/service/Android.bp index 972b362509c0..4172e95bca5b 100644 --- a/apex/permission/service/Android.bp +++ b/apex/permission/service/Android.bp @@ -12,13 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. +filegroup { + name: "service-permission-sources", + srcs: [ + "java/**/*.java", + ], +} + java_library { name: "service-permission", srcs: [ - "java/**/*.java", + ":service-permission-sources", ], - sdk_version: "system_current", + // TODO(b/146758669): Use "system_current" after nullability annotations are system APIs. + sdk_version: "core_current", libs: [ + "framework-annotations-lib", + // TODO(b/146758669): Remove this line after nullability annotations are system APIs. + "android_system_stubs_current", "framework-permission", ], apex_available: [ diff --git a/apex/permission/service/java/com/android/permission/persistence/IoUtils.java b/apex/permission/service/java/com/android/permission/persistence/IoUtils.java new file mode 100644 index 000000000000..0ae44603516e --- /dev/null +++ b/apex/permission/service/java/com/android/permission/persistence/IoUtils.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.permission.persistence; + +import android.annotation.NonNull; + +/** + * Utility class for IO. + */ +public class IoUtils { + + private IoUtils() {} + + /** + * Close 'closeable' ignoring any exceptions. + */ + public static void closeQuietly(@NonNull AutoCloseable closeable) { + try { + closeable.close(); + } catch (Exception ignored) { + // Ignored. + } + } +} diff --git a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistence.java b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistence.java new file mode 100644 index 000000000000..5f2d94441965 --- /dev/null +++ b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistence.java @@ -0,0 +1,72 @@ +/* + * 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.permission.persistence; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.UserHandle; + +/** + * Persistence for runtime permissions. + * + * TODO(b/147914847): Remove @hide when it becomes the default. + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES, process = SystemApi.Process.SYSTEM_SERVER) +public interface RuntimePermissionsPersistence { + + /** + * Read the runtime permissions from persistence. + * + * This will perform I/O operations synchronously. + * + * @param user the user to read for + * @return the runtime permissions read + */ + @Nullable + RuntimePermissionsState read(@NonNull UserHandle user); + + /** + * Write the runtime permissions to persistence. + * + * This will perform I/O operations synchronously. + * + * @param runtimePermissions the runtime permissions to write + * @param user the user to write for + */ + void write(@NonNull RuntimePermissionsState runtimePermissions, @NonNull UserHandle user); + + /** + * Delete the runtime permissions from persistence. + * + * This will perform I/O operations synchronously. + * + * @param user the user to delete for + */ + void delete(@NonNull UserHandle user); + + /** + * Create a new instance of {@link RuntimePermissionsPersistence} implementation. + * + * @return the new instance. + */ + @NonNull + static RuntimePermissionsPersistence createInstance() { + return new RuntimePermissionsPersistenceImpl(); + } +} diff --git a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java new file mode 100644 index 000000000000..51b911a94edc --- /dev/null +++ b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java @@ -0,0 +1,261 @@ +/* + * 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.permission.persistence; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.UserHandle; +import android.util.ArrayMap; +import android.util.AtomicFile; +import android.util.Log; +import android.util.Xml; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Persistence implementation for runtime permissions. + * + * TODO(b/147914847): Remove @hide when it becomes the default. + * @hide + */ +public class RuntimePermissionsPersistenceImpl implements RuntimePermissionsPersistence { + + private static final String LOG_TAG = RuntimePermissionsPersistenceImpl.class.getSimpleName(); + + private static final String RUNTIME_PERMISSIONS_FILE_NAME = "runtime-permissions.xml"; + + private static final String TAG_PACKAGE = "package"; + private static final String TAG_PERMISSION = "permission"; + private static final String TAG_RUNTIME_PERMISSIONS = "runtime-permissions"; + private static final String TAG_SHARED_USER = "shared-user"; + + private static final String ATTRIBUTE_FINGERPRINT = "fingerprint"; + private static final String ATTRIBUTE_FLAGS = "flags"; + private static final String ATTRIBUTE_GRANTED = "granted"; + private static final String ATTRIBUTE_NAME = "name"; + private static final String ATTRIBUTE_VERSION = "version"; + + @Nullable + @Override + public RuntimePermissionsState read(@NonNull UserHandle user) { + File file = getFile(user); + try (FileInputStream inputStream = new AtomicFile(file).openRead()) { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(inputStream, null); + return parseXml(parser); + } catch (FileNotFoundException e) { + Log.i(LOG_TAG, "runtime-permissions.xml not found"); + return null; + } catch (XmlPullParserException | IOException e) { + throw new IllegalStateException("Failed to read runtime-permissions.xml: " + file , e); + } + } + + @NonNull + private static RuntimePermissionsState parseXml(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + int type; + int depth; + int innerDepth = parser.getDepth() + 1; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { + if (depth > innerDepth || type != XmlPullParser.START_TAG) { + continue; + } + + if (parser.getName().equals(TAG_RUNTIME_PERMISSIONS)) { + return parseRuntimePermissions(parser); + } + } + throw new IllegalStateException("Missing <" + TAG_RUNTIME_PERMISSIONS + + "> in runtime-permissions.xml"); + } + + @NonNull + private static RuntimePermissionsState parseRuntimePermissions(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + String versionValue = parser.getAttributeValue(null, ATTRIBUTE_VERSION); + int version = versionValue != null ? Integer.parseInt(versionValue) + : RuntimePermissionsState.NO_VERSION; + String fingerprint = parser.getAttributeValue(null, ATTRIBUTE_FINGERPRINT); + + Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions = + new ArrayMap<>(); + Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions = + new ArrayMap<>(); + int type; + int depth; + int innerDepth = parser.getDepth() + 1; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { + if (depth > innerDepth || type != XmlPullParser.START_TAG) { + continue; + } + + switch (parser.getName()) { + case TAG_PACKAGE: { + String packageName = parser.getAttributeValue(null, ATTRIBUTE_NAME); + List<RuntimePermissionsState.PermissionState> permissions = parsePermissions( + parser); + packagePermissions.put(packageName, permissions); + break; + } + case TAG_SHARED_USER: { + String sharedUserName = parser.getAttributeValue(null, ATTRIBUTE_NAME); + List<RuntimePermissionsState.PermissionState> permissions = parsePermissions( + parser); + sharedUserPermissions.put(sharedUserName, permissions); + break; + } + } + } + + return new RuntimePermissionsState(version, fingerprint, packagePermissions, + sharedUserPermissions); + } + + @NonNull + private static List<RuntimePermissionsState.PermissionState> parsePermissions( + @NonNull XmlPullParser parser) throws IOException, XmlPullParserException { + List<RuntimePermissionsState.PermissionState> permissions = new ArrayList<>(); + int type; + int depth; + int innerDepth = parser.getDepth() + 1; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { + if (depth > innerDepth || type != XmlPullParser.START_TAG) { + continue; + } + + if (parser.getName().equals(TAG_PERMISSION)) { + String name = parser.getAttributeValue(null, ATTRIBUTE_NAME); + boolean granted = Boolean.parseBoolean(parser.getAttributeValue(null, + ATTRIBUTE_GRANTED)); + int flags = Integer.parseInt(parser.getAttributeValue(null, + ATTRIBUTE_FLAGS), 16); + RuntimePermissionsState.PermissionState permission = + new RuntimePermissionsState.PermissionState(name, granted, flags); + permissions.add(permission); + } + } + return permissions; + } + + @Override + public void write(@NonNull RuntimePermissionsState runtimePermissions, + @NonNull UserHandle user) { + File file = getFile(user); + AtomicFile atomicFile = new AtomicFile(file); + FileOutputStream outputStream = null; + try { + outputStream = atomicFile.startWrite(); + + XmlSerializer serializer = Xml.newSerializer(); + serializer.setOutput(outputStream, StandardCharsets.UTF_8.name()); + serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); + serializer.startDocument(null, true); + + serializeRuntimePermissions(serializer, runtimePermissions); + + serializer.endDocument(); + atomicFile.finishWrite(outputStream); + } catch (Exception e) { + Log.wtf(LOG_TAG, "Failed to write runtime-permissions.xml, restoring backup: " + file, + e); + atomicFile.failWrite(outputStream); + } finally { + IoUtils.closeQuietly(outputStream); + } + } + + private static void serializeRuntimePermissions(@NonNull XmlSerializer serializer, + @NonNull RuntimePermissionsState runtimePermissions) throws IOException { + serializer.startTag(null, TAG_RUNTIME_PERMISSIONS); + + int version = runtimePermissions.getVersion(); + serializer.attribute(null, ATTRIBUTE_VERSION, Integer.toString(version)); + String fingerprint = runtimePermissions.getFingerprint(); + if (fingerprint != null) { + serializer.attribute(null, ATTRIBUTE_FINGERPRINT, fingerprint); + } + + for (Map.Entry<String, List<RuntimePermissionsState.PermissionState>> entry + : runtimePermissions.getPackagePermissions().entrySet()) { + String packageName = entry.getKey(); + List<RuntimePermissionsState.PermissionState> permissions = entry.getValue(); + + serializer.startTag(null, TAG_PACKAGE); + serializer.attribute(null, ATTRIBUTE_NAME, packageName); + serializePermissions(serializer, permissions); + serializer.endTag(null, TAG_PACKAGE); + } + + for (Map.Entry<String, List<RuntimePermissionsState.PermissionState>> entry + : runtimePermissions.getSharedUserPermissions().entrySet()) { + String sharedUserName = entry.getKey(); + List<RuntimePermissionsState.PermissionState> permissions = entry.getValue(); + + serializer.startTag(null, TAG_SHARED_USER); + serializer.attribute(null, ATTRIBUTE_NAME, sharedUserName); + serializePermissions(serializer, permissions); + serializer.endTag(null, TAG_SHARED_USER); + } + + serializer.endTag(null, TAG_RUNTIME_PERMISSIONS); + } + + private static void serializePermissions(@NonNull XmlSerializer serializer, + @NonNull List<RuntimePermissionsState.PermissionState> permissions) throws IOException { + int permissionsSize = permissions.size(); + for (int i = 0; i < permissionsSize; i++) { + RuntimePermissionsState.PermissionState permissionState = permissions.get(i); + + serializer.startTag(null, TAG_PERMISSION); + serializer.attribute(null, ATTRIBUTE_NAME, permissionState.getName()); + serializer.attribute(null, ATTRIBUTE_GRANTED, Boolean.toString( + permissionState.isGranted())); + serializer.attribute(null, ATTRIBUTE_FLAGS, Integer.toHexString( + permissionState.getFlags())); + serializer.endTag(null, TAG_PERMISSION); + } + } + + @Override + public void delete(@NonNull UserHandle user) { + getFile(user).delete(); + } + + @NonNull + private static File getFile(@NonNull UserHandle user) { + // TODO: Use an API for this. + File dataDirectory = new File("/data/misc_de/" + user.getIdentifier() + + "/apexdata/com.android.permission"); + return new File(dataDirectory, RUNTIME_PERMISSIONS_FILE_NAME); + } +} diff --git a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsState.java b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsState.java new file mode 100644 index 000000000000..2a939e51b98e --- /dev/null +++ b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsState.java @@ -0,0 +1,131 @@ +/* + * 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.permission.persistence; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; + +import java.util.List; +import java.util.Map; + +/** + * State of all runtime permissions. + * + * TODO(b/147914847): Remove @hide when it becomes the default. + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES, process = SystemApi.Process.SYSTEM_SERVER) +public final class RuntimePermissionsState { + + /** + * Special value for {@link #mVersion} to indicate that no version was read. + */ + public static final int NO_VERSION = -1; + + /** + * The version of the runtime permissions. + */ + private final int mVersion; + + /** + * The fingerprint of the runtime permissions. + */ + @Nullable + private final String mFingerprint; + + /** + * The runtime permissions by packages. + */ + @NonNull + private final Map<String, List<PermissionState>> mPackagePermissions; + + /** + * The runtime permissions by shared users. + */ + @NonNull + private final Map<String, List<PermissionState>> mSharedUserPermissions; + + public RuntimePermissionsState(int version, @Nullable String fingerprint, + @NonNull Map<String, List<PermissionState>> packagePermissions, + @NonNull Map<String, List<PermissionState>> sharedUserPermissions) { + mVersion = version; + mFingerprint = fingerprint; + mPackagePermissions = packagePermissions; + mSharedUserPermissions = sharedUserPermissions; + } + + public int getVersion() { + return mVersion; + } + + @Nullable + public String getFingerprint() { + return mFingerprint; + } + + @NonNull + public Map<String, List<PermissionState>> getPackagePermissions() { + return mPackagePermissions; + } + + @NonNull + public Map<String, List<PermissionState>> getSharedUserPermissions() { + return mSharedUserPermissions; + } + + /** + * State of a single permission. + */ + public static class PermissionState { + + /** + * Name of the permission. + */ + @NonNull + private final String mName; + + /** + * Whether the permission is granted. + */ + private final boolean mGranted; + + /** + * Flags of the permission. + */ + private final int mFlags; + + public PermissionState(@NonNull String name, boolean granted, int flags) { + mName = name; + mGranted = granted; + mFlags = flags; + } + + @NonNull + public String getName() { + return mName; + } + + public boolean isGranted() { + return mGranted; + } + + public int getFlags() { + return mFlags; + } + } +} diff --git a/apex/permission/service/java/com/android/role/persistence/RolesPersistence.java b/apex/permission/service/java/com/android/role/persistence/RolesPersistence.java new file mode 100644 index 000000000000..63c8eedd6285 --- /dev/null +++ b/apex/permission/service/java/com/android/role/persistence/RolesPersistence.java @@ -0,0 +1,72 @@ +/* + * 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.role.persistence; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.UserHandle; + +/** + * Persistence for roles. + * + * TODO(b/147914847): Remove @hide when it becomes the default. + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES, process = SystemApi.Process.SYSTEM_SERVER) +public interface RolesPersistence { + + /** + * Read the roles from persistence. + * + * This will perform I/O operations synchronously. + * + * @param user the user to read for + * @return the roles read + */ + @Nullable + RolesState read(@NonNull UserHandle user); + + /** + * Write the roles to persistence. + * + * This will perform I/O operations synchronously. + * + * @param roles the roles to write + * @param user the user to write for + */ + void write(@NonNull RolesState roles, @NonNull UserHandle user); + + /** + * Delete the roles from persistence. + * + * This will perform I/O operations synchronously. + * + * @param user the user to delete for + */ + void delete(@NonNull UserHandle user); + + /** + * Create a new instance of {@link RolesPersistence} implementation. + * + * @return the new instance. + */ + @NonNull + static RolesPersistence createInstance() { + return new RolesPersistenceImpl(); + } +} diff --git a/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java b/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java new file mode 100644 index 000000000000..5061742f4c58 --- /dev/null +++ b/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.role.persistence; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.UserHandle; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.AtomicFile; +import android.util.Log; +import android.util.Xml; + +import com.android.permission.persistence.IoUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Set; + +/** + * Persistence implementation for roles. + * + * TODO(b/147914847): Remove @hide when it becomes the default. + * @hide + */ +public class RolesPersistenceImpl implements RolesPersistence { + + private static final String LOG_TAG = RolesPersistenceImpl.class.getSimpleName(); + + private static final String ROLES_FILE_NAME = "roles.xml"; + + private static final String TAG_ROLES = "roles"; + private static final String TAG_ROLE = "role"; + private static final String TAG_HOLDER = "holder"; + + private static final String ATTRIBUTE_VERSION = "version"; + private static final String ATTRIBUTE_NAME = "name"; + private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash"; + + @Nullable + @Override + public RolesState read(@NonNull UserHandle user) { + File file = getFile(user); + try (FileInputStream inputStream = new AtomicFile(file).openRead()) { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(inputStream, null); + return parseXml(parser); + } catch (FileNotFoundException e) { + Log.i(LOG_TAG, "roles.xml not found"); + return null; + } catch (XmlPullParserException | IOException e) { + throw new IllegalStateException("Failed to read roles.xml: " + file , e); + } + } + + @NonNull + private static RolesState parseXml(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + int type; + int depth; + int innerDepth = parser.getDepth() + 1; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { + if (depth > innerDepth || type != XmlPullParser.START_TAG) { + continue; + } + + if (parser.getName().equals(TAG_ROLES)) { + return parseRoles(parser); + } + } + throw new IllegalStateException("Missing <" + TAG_ROLES + "> in roles.xml"); + } + + @NonNull + private static RolesState parseRoles(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + int version = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION)); + String packagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH); + + Map<String, Set<String>> roles = new ArrayMap<>(); + int type; + int depth; + int innerDepth = parser.getDepth() + 1; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { + if (depth > innerDepth || type != XmlPullParser.START_TAG) { + continue; + } + + if (parser.getName().equals(TAG_ROLE)) { + String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME); + Set<String> roleHolders = parseRoleHolders(parser); + roles.put(roleName, roleHolders); + } + } + + return new RolesState(version, packagesHash, roles); + } + + @NonNull + private static Set<String> parseRoleHolders(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + Set<String> roleHolders = new ArraySet<>(); + int type; + int depth; + int innerDepth = parser.getDepth() + 1; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { + if (depth > innerDepth || type != XmlPullParser.START_TAG) { + continue; + } + + if (parser.getName().equals(TAG_HOLDER)) { + String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME); + roleHolders.add(roleHolder); + } + } + return roleHolders; + } + + @Override + public void write(@NonNull RolesState roles, + @NonNull UserHandle user) { + File file = getFile(user); + AtomicFile atomicFile = new AtomicFile(file); + FileOutputStream outputStream = null; + try { + outputStream = atomicFile.startWrite(); + + XmlSerializer serializer = Xml.newSerializer(); + serializer.setOutput(outputStream, StandardCharsets.UTF_8.name()); + serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); + serializer.startDocument(null, true); + + serializeRoles(serializer, roles); + + serializer.endDocument(); + atomicFile.finishWrite(outputStream); + } catch (Exception e) { + Log.wtf(LOG_TAG, "Failed to write roles.xml, restoring backup: " + file, + e); + atomicFile.failWrite(outputStream); + } finally { + IoUtils.closeQuietly(outputStream); + } + } + + private static void serializeRoles(@NonNull XmlSerializer serializer, + @NonNull RolesState roles) throws IOException { + serializer.startTag(null, TAG_ROLES); + + int version = roles.getVersion(); + serializer.attribute(null, ATTRIBUTE_VERSION, Integer.toString(version)); + String packagesHash = roles.getPackagesHash(); + if (packagesHash != null) { + serializer.attribute(null, ATTRIBUTE_PACKAGES_HASH, packagesHash); + } + + for (Map.Entry<String, Set<String>> entry : roles.getRoles().entrySet()) { + String roleName = entry.getKey(); + Set<String> roleHolders = entry.getValue(); + + serializer.startTag(null, TAG_ROLE); + serializer.attribute(null, ATTRIBUTE_NAME, roleName); + serializeRoleHolders(serializer, roleHolders); + serializer.endTag(null, TAG_ROLE); + } + + serializer.endTag(null, TAG_ROLES); + } + + private static void serializeRoleHolders(@NonNull XmlSerializer serializer, + @NonNull Set<String> roleHolders) throws IOException { + for (String roleHolder : roleHolders) { + serializer.startTag(null, TAG_HOLDER); + serializer.attribute(null, ATTRIBUTE_NAME, roleHolder); + serializer.endTag(null, TAG_HOLDER); + } + } + + @Override + public void delete(@NonNull UserHandle user) { + getFile(user).delete(); + } + + @NonNull + private static File getFile(@NonNull UserHandle user) { + // TODO: Use an API for this. + File dataDirectory = new File("/data/misc_de/" + user.getIdentifier() + + "/apexdata/com.android.permission"); + return new File(dataDirectory, ROLES_FILE_NAME); + } +} diff --git a/apex/permission/service/java/com/android/role/persistence/RolesState.java b/apex/permission/service/java/com/android/role/persistence/RolesState.java new file mode 100644 index 000000000000..bff980e2e126 --- /dev/null +++ b/apex/permission/service/java/com/android/role/persistence/RolesState.java @@ -0,0 +1,72 @@ +/* + * 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.role.persistence; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; + +import java.util.Map; +import java.util.Set; + +/** + * State of all roles. + * + * TODO(b/147914847): Remove @hide when it becomes the default. + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES, process = SystemApi.Process.SYSTEM_SERVER) +public final class RolesState { + + /** + * The version of the roles. + */ + private final int mVersion; + + /** + * The hash of all packages in the system. + */ + @Nullable + private final String mPackagesHash; + + /** + * The roles. + */ + @NonNull + private final Map<String, Set<String>> mRoles; + + public RolesState(int version, @Nullable String packagesHash, + @NonNull Map<String, Set<String>> roles) { + mVersion = version; + mPackagesHash = packagesHash; + mRoles = roles; + } + + public int getVersion() { + return mVersion; + } + + @Nullable + public String getPackagesHash() { + return mPackagesHash; + } + + @NonNull + public Map<String, Set<String>> getRoles() { + return mRoles; + } +} diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp index f8325d47e268..cc5172c6018a 100644 --- a/apex/statsd/aidl/Android.bp +++ b/apex/statsd/aidl/Android.bp @@ -23,7 +23,6 @@ filegroup { "android/os/IPullAtomResultReceiver.aidl", "android/os/IStatsCompanionService.aidl", "android/os/IStatsd.aidl", - "android/os/IStatsPullerCallback.aidl", "android/util/StatsEventParcel.aidl", ], } diff --git a/apex/statsd/aidl/android/os/IStatsPullerCallback.aidl b/apex/statsd/aidl/android/os/IStatsPullerCallback.aidl deleted file mode 100644 index c3e1e55dde06..000000000000 --- a/apex/statsd/aidl/android/os/IStatsPullerCallback.aidl +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -import android.os.StatsLogEventWrapper; - -/** - * DEPRECATED - * Binder interface to pull atoms for the stats service. - * {@hide} - */ -interface IStatsPullerCallback { - /** - * Pull data for the specified atom tag. Returns an array of StatsLogEventWrapper containing - * the data. - * - * Note: These pulled atoms should not have uid/attribution chain. Additionally, the event - * timestamps will be truncated to the nearest 5 minutes. - */ - StatsLogEventWrapper[] pullData(int atomTag, long elapsedNanos, long wallClocknanos); - -} diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl index 0ecf2f0b4851..a2564212366f 100644 --- a/apex/statsd/aidl/android/os/IStatsd.aidl +++ b/apex/statsd/aidl/android/os/IStatsd.aidl @@ -16,7 +16,6 @@ package android.os; -import android.os.IStatsPullerCallback; import android.os.IPendingIntentRef; import android.os.IPullAtomCallback; import android.os.ParcelFileDescriptor; @@ -183,16 +182,6 @@ interface IStatsd { */ void sendAppBreadcrumbAtom(int label, int state); - /** - * Registers a puller callback function that, when invoked, pulls the data - * for the specified vendor atom tag. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS - * @deprecated please use registerPullAtomCallback. - */ - oneway void registerPullerCallback(int atomTag, IStatsPullerCallback pullerCallback, - String packageName); - /** * Registers a puller callback function that, when invoked, pulls the data * for the specified atom tag. @@ -207,13 +196,6 @@ interface IStatsd { oneway void registerNativePullAtomCallback(int atomTag, long coolDownNs, long timeoutNs, in int[] additiveFields, IPullAtomCallback pullerCallback); - /** - * Unregisters a puller callback function for the given vendor atom. - * - * Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS - */ - oneway void unregisterPullerCallback(int atomTag, String packageName); - /** * Unregisters any pullAtomCallback for the given uid/atom. */ diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java index 17573bb22fea..e5d1182903f4 100644 --- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java +++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java @@ -714,265 +714,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } - private void pullSystemElapsedRealtime( - int tagId, long elapsedNanos, long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeLong(SystemClock.elapsedRealtime()); - pulledData.add(e); - } - - private void pullLooperStats(int tagId, long elapsedNanos, long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - LooperStats looperStats = LocalServices.getService(LooperStats.class); - if (looperStats == null) { - throw new IllegalStateException("looperStats null"); - } - - List<LooperStats.ExportedEntry> entries = looperStats.getEntries(); - looperStats.reset(); - for (LooperStats.ExportedEntry entry : entries) { - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(entry.workSourceUid); - e.writeString(entry.handlerClassName); - e.writeString(entry.threadName); - e.writeString(entry.messageName); - e.writeLong(entry.messageCount); - e.writeLong(entry.exceptionCount); - e.writeLong(entry.recordedMessageCount); - e.writeLong(entry.totalLatencyMicros); - e.writeLong(entry.cpuUsageMicros); - e.writeBoolean(entry.isInteractive); - e.writeLong(entry.maxCpuUsageMicros); - e.writeLong(entry.maxLatencyMicros); - e.writeLong(entry.recordedDelayMessageCount); - e.writeLong(entry.delayMillis); - e.writeLong(entry.maxDelayMillis); - pulledData.add(e); - } - } - - private void pullDiskStats(int tagId, long elapsedNanos, long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - // Run a quick-and-dirty performance test: write 512 bytes - byte[] junk = new byte[512]; - for (int i = 0; i < junk.length; i++) junk[i] = (byte) i; // Write nonzero bytes - - File tmp = new File(Environment.getDataDirectory(), "system/statsdperftest.tmp"); - FileOutputStream fos = null; - IOException error = null; - - long before = SystemClock.elapsedRealtime(); - try { - fos = new FileOutputStream(tmp); - fos.write(junk); - } catch (IOException e) { - error = e; - } finally { - try { - if (fos != null) fos.close(); - } catch (IOException e) { - // Do nothing. - } - } - - long latency = SystemClock.elapsedRealtime() - before; - if (tmp.exists()) tmp.delete(); - - if (error != null) { - Slog.e(TAG, "Error performing diskstats latency test"); - latency = -1; - } - // File based encryption. - boolean fileBased = StorageManager.isFileEncryptedNativeOnly(); - - //Recent disk write speed. Binder call to storaged. - int writeSpeed = -1; - try { - IBinder binder = ServiceManager.getService("storaged"); - if (binder == null) { - Slog.e(TAG, "storaged not found"); - } - IStoraged storaged = IStoraged.Stub.asInterface(binder); - writeSpeed = storaged.getRecentPerf(); - } catch (RemoteException e) { - Slog.e(TAG, "storaged not found"); - } - - // Add info pulledData. - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeLong(latency); - e.writeBoolean(fileBased); - e.writeInt(writeSpeed); - pulledData.add(e); - } - - private void pullDirectoryUsage(int tagId, long elapsedNanos, long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath()); - StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath()); - StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath()); - - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__DATA); - e.writeLong(statFsData.getAvailableBytes()); - e.writeLong(statFsData.getTotalBytes()); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE); - e.writeLong(statFsCache.getAvailableBytes()); - e.writeLong(statFsCache.getTotalBytes()); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM); - e.writeLong(statFsSystem.getAvailableBytes()); - e.writeLong(statFsSystem.getTotalBytes()); - pulledData.add(e); - } - - private void pullAppSize(int tagId, long elapsedNanos, long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - try { - String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH); - JSONObject json = new JSONObject(jsonStr); - long cache_time = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L); - JSONArray pkg_names = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY); - JSONArray app_sizes = json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY); - JSONArray app_data_sizes = json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY); - JSONArray app_cache_sizes = json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY); - // Sanity check: Ensure all 4 lists have the same length. - int length = pkg_names.length(); - if (app_sizes.length() != length || app_data_sizes.length() != length - || app_cache_sizes.length() != length) { - Slog.e(TAG, "formatting error in diskstats cache file!"); - return; - } - for (int i = 0; i < length; i++) { - StatsLogEventWrapper e = - new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeString(pkg_names.getString(i)); - e.writeLong(app_sizes.optLong(i, -1L)); - e.writeLong(app_data_sizes.optLong(i, -1L)); - e.writeLong(app_cache_sizes.optLong(i, -1L)); - e.writeLong(cache_time); - pulledData.add(e); - } - } catch (IOException | JSONException e) { - Slog.e(TAG, "exception reading diskstats cache file", e); - } - } - - private void pullCategorySize(int tagId, long elapsedNanos, long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - try { - String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH); - JSONObject json = new JSONObject(jsonStr); - long cacheTime = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L); - - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE); - e.writeLong(json.optLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY, -1L)); - e.writeLong(cacheTime); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE); - e.writeLong(json.optLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY, -1L)); - e.writeLong(cacheTime); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE); - e.writeLong(json.optLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY, -1L)); - e.writeLong(cacheTime); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS); - e.writeLong(json.optLong(DiskStatsFileLogger.PHOTOS_KEY, -1L)); - e.writeLong(cacheTime); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS); - e.writeLong(json.optLong(DiskStatsFileLogger.VIDEOS_KEY, -1L)); - e.writeLong(cacheTime); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__AUDIO); - e.writeLong(json.optLong(DiskStatsFileLogger.AUDIO_KEY, -1L)); - e.writeLong(cacheTime); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS); - e.writeLong(json.optLong(DiskStatsFileLogger.DOWNLOADS_KEY, -1L)); - e.writeLong(cacheTime); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM); - e.writeLong(json.optLong(DiskStatsFileLogger.SYSTEM_KEY, -1L)); - e.writeLong(cacheTime); - pulledData.add(e); - - e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__OTHER); - e.writeLong(json.optLong(DiskStatsFileLogger.MISC_KEY, -1L)); - e.writeLong(cacheTime); - pulledData.add(e); - } catch (IOException | JSONException e) { - Slog.e(TAG, "exception reading diskstats cache file", e); - } - } - - private void pullNumBiometricsEnrolled(int modality, int tagId, long elapsedNanos, - long wallClockNanos, List<StatsLogEventWrapper> pulledData) { - final PackageManager pm = mContext.getPackageManager(); - FingerprintManager fingerprintManager = null; - FaceManager faceManager = null; - - if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { - fingerprintManager = mContext.getSystemService( - FingerprintManager.class); - } - if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) { - faceManager = mContext.getSystemService(FaceManager.class); - } - - if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT && fingerprintManager == null) { - return; - } - if (modality == BiometricsProtoEnums.MODALITY_FACE && faceManager == null) { - return; - } - UserManager userManager = mContext.getSystemService(UserManager.class); - if (userManager == null) { - return; - } - - final long token = Binder.clearCallingIdentity(); - for (UserInfo user : userManager.getUsers()) { - final int userId = user.getUserHandle().getIdentifier(); - int numEnrolled = 0; - if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT) { - numEnrolled = fingerprintManager.getEnrolledFingerprints(userId).size(); - } else if (modality == BiometricsProtoEnums.MODALITY_FACE) { - numEnrolled = faceManager.getEnrolledFaces(userId).size(); - } else { - return; - } - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(userId); - e.writeInt(numEnrolled); - pulledData.add(e); - } - Binder.restoreCallingIdentity(token); - } - // read high watermark for section private long readProcStatsHighWaterMark(int section) { try { @@ -1024,39 +765,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } - private INotificationManager mNotificationManager = - INotificationManager.Stub.asInterface( - ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - - private void pullNotificationStats(int reportId, int tagId, long elapsedNanos, - long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - final long callingToken = Binder.clearCallingIdentity(); - try { - // determine last pull tine. Copy file trick from pullProcessStats? - long lastNotificationStatsNs = wallClockNanos - - TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS); - - List<ParcelFileDescriptor> statsFiles = new ArrayList<>(); - long notificationStatsNs = mNotificationManager.pullStats( - lastNotificationStatsNs, reportId, true, statsFiles); - if (statsFiles.size() != 1) { - return; - } - unpackStreamedData(tagId, elapsedNanos, wallClockNanos, pulledData, statsFiles); - } catch (IOException e) { - Log.e(TAG, "Getting notistats failed: ", e); - - } catch (RemoteException e) { - Log.e(TAG, "Getting notistats failed: ", e); - } catch (SecurityException e) { - Log.e(TAG, "Getting notistats failed: ", e); - } finally { - Binder.restoreCallingIdentity(callingToken); - } - - } - static void unpackStreamedData(int tagId, long elapsedNanos, long wallClockNanos, List<StatsLogEventWrapper> pulledData, List<ParcelFileDescriptor> statsFiles) throws IOException { @@ -1098,104 +806,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } - private void pullDiskIo(int tagId, long elapsedNanos, final long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead, - fgBytesWrite, bgCharsRead, bgCharsWrite, bgBytesRead, bgBytesWrite, - fgFsync, bgFsync) -> { - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, - wallClockNanos); - e.writeInt(uid); - e.writeLong(fgCharsRead); - e.writeLong(fgCharsWrite); - e.writeLong(fgBytesRead); - e.writeLong(fgBytesWrite); - e.writeLong(bgCharsRead); - e.writeLong(bgCharsWrite); - e.writeLong(bgBytesRead); - e.writeLong(bgBytesWrite); - e.writeLong(fgFsync); - e.writeLong(bgFsync); - pulledData.add(e); - }); - } - - private void pullProcessCpuTime(int tagId, long elapsedNanos, final long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - synchronized (this) { - if (mProcessCpuTracker == null) { - mProcessCpuTracker = new ProcessCpuTracker(false); - mProcessCpuTracker.init(); - } - mProcessCpuTracker.update(); - for (int i = 0; i < mProcessCpuTracker.countStats(); i++) { - ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, - wallClockNanos); - e.writeInt(st.uid); - e.writeString(st.name); - e.writeLong(st.base_utime); - e.writeLong(st.base_stime); - pulledData.add(e); - } - } - } - - private void pullCpuTimePerThreadFreq(int tagId, long elapsedNanos, long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - if (this.mKernelCpuThreadReader == null) { - throw new IllegalStateException("mKernelCpuThreadReader is null"); - } - ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsages = - this.mKernelCpuThreadReader.getProcessCpuUsageDiffed(); - if (processCpuUsages == null) { - throw new IllegalStateException("processCpuUsages is null"); - } - int[] cpuFrequencies = mKernelCpuThreadReader.getCpuFrequenciesKhz(); - if (cpuFrequencies.length > CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES) { - String message = "Expected maximum " + CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES - + " frequencies, but got " + cpuFrequencies.length; - Slog.w(TAG, message); - throw new IllegalStateException(message); - } - for (int i = 0; i < processCpuUsages.size(); i++) { - KernelCpuThreadReader.ProcessCpuUsage processCpuUsage = processCpuUsages.get(i); - ArrayList<KernelCpuThreadReader.ThreadCpuUsage> threadCpuUsages = - processCpuUsage.threadCpuUsages; - for (int j = 0; j < threadCpuUsages.size(); j++) { - KernelCpuThreadReader.ThreadCpuUsage threadCpuUsage = threadCpuUsages.get(j); - if (threadCpuUsage.usageTimesMillis.length != cpuFrequencies.length) { - String message = "Unexpected number of usage times," - + " expected " + cpuFrequencies.length - + " but got " + threadCpuUsage.usageTimesMillis.length; - Slog.w(TAG, message); - throw new IllegalStateException(message); - } - - StatsLogEventWrapper e = - new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(processCpuUsage.uid); - e.writeInt(processCpuUsage.processId); - e.writeInt(threadCpuUsage.threadId); - e.writeString(processCpuUsage.processName); - e.writeString(threadCpuUsage.threadName); - for (int k = 0; k < CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES; k++) { - if (k < cpuFrequencies.length) { - e.writeInt(cpuFrequencies[k]); - e.writeInt(threadCpuUsage.usageTimesMillis[k]); - } else { - // If we have no more frequencies to write, we still must write empty data. - // We know that this data is empty (and not just zero) because all - // frequencies are expected to be greater than zero - e.writeInt(0); - e.writeInt(0); - } - } - pulledData.add(e); - } - } - } - private void pullDebugElapsedClock(int tagId, long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) { final long elapsedMillis = SystemClock.elapsedRealtime(); @@ -1246,283 +856,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { pulledData.add(e); } - private void pullDangerousPermissionState(int atomId, long elapsedNanos, - final long wallClockNanos, List<StatsLogEventWrapper> pulledData) { - long token = Binder.clearCallingIdentity(); - Set<Integer> reportedUids = new HashSet<>(); - try { - PackageManager pm = mContext.getPackageManager(); - - List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); - - int numUsers = users.size(); - for (int userNum = 0; userNum < numUsers; userNum++) { - UserHandle user = users.get(userNum).getUserHandle(); - - List<PackageInfo> pkgs = pm.getInstalledPackagesAsUser( - PackageManager.GET_PERMISSIONS, user.getIdentifier()); - - int numPkgs = pkgs.size(); - for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) { - PackageInfo pkg = pkgs.get(pkgNum); - - if (pkg.requestedPermissions == null) { - continue; - } - - if (reportedUids.contains(pkg.applicationInfo.uid)) { - // do not report same uid twice - continue; - } - reportedUids.add(pkg.applicationInfo.uid); - - if (atomId == StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED - && ThreadLocalRandom.current().nextFloat() > 0.2f) { - continue; - } - - int numPerms = pkg.requestedPermissions.length; - for (int permNum = 0; permNum < numPerms; permNum++) { - String permName = pkg.requestedPermissions[permNum]; - - PermissionInfo permissionInfo; - int permissionFlags = 0; - try { - permissionInfo = pm.getPermissionInfo(permName, 0); - permissionFlags = - pm.getPermissionFlags(permName, pkg.packageName, user); - - } catch (PackageManager.NameNotFoundException ignored) { - continue; - } - - if (permissionInfo.getProtection() != PROTECTION_DANGEROUS) { - continue; - } - - StatsLogEventWrapper e = new StatsLogEventWrapper( - atomId, elapsedNanos, wallClockNanos); - - e.writeString(permName); - e.writeInt(pkg.applicationInfo.uid); - if (atomId == StatsLog.DANGEROUS_PERMISSION_STATE) { - e.writeString(null); - } - e.writeBoolean((pkg.requestedPermissionsFlags[permNum] - & REQUESTED_PERMISSION_GRANTED) != 0); - e.writeInt(permissionFlags); - - pulledData.add(e); - } - } - } - } catch (Throwable t) { - Log.e(TAG, "Could not read permissions", t); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - private void pullAppOps(long elapsedNanos, final long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - long token = Binder.clearCallingIdentity(); - try { - AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); - - CompletableFuture<HistoricalOps> ops = new CompletableFuture<>(); - HistoricalOpsRequest histOpsRequest = - new HistoricalOpsRequest.Builder(0, Long.MAX_VALUE).build(); - appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete); - - HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS, - TimeUnit.MILLISECONDS); - - for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) { - final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx); - final int uid = uidOps.getUid(); - for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) { - final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx); - for (int opIdx = 0; opIdx < packageOps.getOpCount(); opIdx++) { - final AppOpsManager.HistoricalOp op = packageOps.getOpAt(opIdx); - StatsLogEventWrapper e = new StatsLogEventWrapper(StatsLog.APP_OPS, - elapsedNanos, wallClockNanos); - - e.writeInt(uid); - e.writeString(packageOps.getPackageName()); - e.writeInt(op.getOpCode()); - e.writeLong(op.getForegroundAccessCount(OP_FLAGS_ALL_TRUSTED)); - e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_ALL_TRUSTED)); - e.writeLong(op.getForegroundRejectCount(OP_FLAGS_ALL_TRUSTED)); - e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_ALL_TRUSTED)); - e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_ALL_TRUSTED)); - e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_ALL_TRUSTED)); - - String perm = AppOpsManager.opToPermission(op.getOpCode()); - if (perm == null) { - e.writeBoolean(false); - } else { - PermissionInfo permInfo; - try { - permInfo = mContext.getPackageManager().getPermissionInfo(perm, 0); - e.writeBoolean(permInfo.getProtection() == PROTECTION_DANGEROUS); - } catch (PackageManager.NameNotFoundException exception) { - e.writeBoolean(false); - } - } - - pulledData.add(e); - } - } - } - } catch (Throwable t) { - Log.e(TAG, "Could not read appops", t); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - - /** - * Add a RoleHolder atom for each package that holds a role. - * - * @param elapsedNanos the time since boot - * @param wallClockNanos the time on the clock - * @param pulledData the data sink to write to - */ - private void pullRoleHolders(long elapsedNanos, final long wallClockNanos, - @NonNull List<StatsLogEventWrapper> pulledData) { - long callingToken = Binder.clearCallingIdentity(); - try { - PackageManager pm = mContext.getPackageManager(); - RoleManagerInternal rmi = LocalServices.getService(RoleManagerInternal.class); - - List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); - - int numUsers = users.size(); - for (int userNum = 0; userNum < numUsers; userNum++) { - int userId = users.get(userNum).getUserHandle().getIdentifier(); - - ArrayMap<String, ArraySet<String>> roles = rmi.getRolesAndHolders( - userId); - - int numRoles = roles.size(); - for (int roleNum = 0; roleNum < numRoles; roleNum++) { - String roleName = roles.keyAt(roleNum); - ArraySet<String> holders = roles.valueAt(roleNum); - - int numHolders = holders.size(); - for (int holderNum = 0; holderNum < numHolders; holderNum++) { - String holderName = holders.valueAt(holderNum); - - PackageInfo pkg; - try { - pkg = pm.getPackageInfoAsUser(holderName, 0, userId); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Role holder " + holderName + " not found"); - return; - } - - StatsLogEventWrapper e = new StatsLogEventWrapper(StatsLog.ROLE_HOLDER, - elapsedNanos, wallClockNanos); - e.writeInt(pkg.applicationInfo.uid); - e.writeString(holderName); - e.writeString(roleName); - pulledData.add(e); - } - } - } - } finally { - Binder.restoreCallingIdentity(callingToken); - } - } - - private void pullTimeZoneDataInfo(int tagId, - long elapsedNanos, long wallClockNanos, List<StatsLogEventWrapper> pulledData) { - String tzDbVersion = "Unknown"; - try { - tzDbVersion = android.icu.util.TimeZone.getTZDataVersion(); - } catch (Exception e) { - Log.e(TAG, "Getting tzdb version failed: ", e); - } - - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeString(tzDbVersion); - pulledData.add(e); - } - - private void pullExternalStorageInfo(int tagId, long elapsedNanos, long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - StorageManager storageManager = mContext.getSystemService(StorageManager.class); - if (storageManager != null) { - List<VolumeInfo> volumes = storageManager.getVolumes(); - for (VolumeInfo vol : volumes) { - final String envState = VolumeInfo.getEnvironmentForState(vol.getState()); - final DiskInfo diskInfo = vol.getDisk(); - if (diskInfo != null) { - if (envState.equals(Environment.MEDIA_MOUNTED)) { - // Get the type of the volume, if it is adoptable or portable. - int volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__OTHER; - if (vol.getType() == TYPE_PUBLIC) { - volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PUBLIC; - } else if (vol.getType() == TYPE_PRIVATE) { - volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PRIVATE; - } - // Get the type of external storage inserted in the device (sd cards, - // usb, etc) - int externalStorageType; - if (diskInfo.isSd()) { - externalStorageType = StorageEnums.SD_CARD; - } else if (diskInfo.isUsb()) { - externalStorageType = StorageEnums.USB; - } else { - externalStorageType = StorageEnums.OTHER; - } - StatsLogEventWrapper e = - new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(externalStorageType); - e.writeInt(volumeType); - e.writeLong(diskInfo.size); - pulledData.add(e); - } - } - } - } - } - - private void pullAppsOnExternalStorageInfo(int tagId, long elapsedNanos, long wallClockNanos, - List<StatsLogEventWrapper> pulledData) { - PackageManager pm = mContext.getPackageManager(); - StorageManager storage = mContext.getSystemService(StorageManager.class); - List<ApplicationInfo> apps = pm.getInstalledApplications(/* flags = */ 0); - for (ApplicationInfo appInfo : apps) { - UUID storageUuid = appInfo.storageUuid; - if (storageUuid != null) { - VolumeInfo volumeInfo = storage.findVolumeByUuid(appInfo.storageUuid.toString()); - if (volumeInfo != null) { - DiskInfo diskInfo = volumeInfo.getDisk(); - if (diskInfo != null) { - int externalStorageType = -1; - if (diskInfo.isSd()) { - externalStorageType = StorageEnums.SD_CARD; - } else if (diskInfo.isUsb()) { - externalStorageType = StorageEnums.USB; - } else if (appInfo.isExternal()) { - externalStorageType = StorageEnums.OTHER; - } - // App is installed on external storage. - if (externalStorageType != -1) { - StatsLogEventWrapper e = - new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(externalStorageType); - e.writeString(appInfo.packageName); - pulledData.add(e); - } - } - } - } - } - } - private void pullFaceSettings(int tagId, long elapsedNanos, long wallClockNanos, List<StatsLogEventWrapper> pulledData) { long callingToken = Binder.clearCallingIdentity(); @@ -1574,48 +907,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { long wallClockNanos = SystemClock.currentTimeMicro() * 1000L; switch (tagId) { - case StatsLog.SYSTEM_ELAPSED_REALTIME: { - pullSystemElapsedRealtime(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.LOOPER_STATS: { - pullLooperStats(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.DISK_STATS: { - pullDiskStats(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.DIRECTORY_USAGE: { - pullDirectoryUsage(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.APP_SIZE: { - pullAppSize(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.CATEGORY_SIZE: { - pullCategorySize(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.NUM_FINGERPRINTS_ENROLLED: { - pullNumBiometricsEnrolled(BiometricsProtoEnums.MODALITY_FINGERPRINT, tagId, - elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.NUM_FACES_ENROLLED: { - pullNumBiometricsEnrolled(BiometricsProtoEnums.MODALITY_FACE, tagId, elapsedNanos, - wallClockNanos, ret); - break; - } - case StatsLog.PROC_STATS: { pullProcessStats(ProcessStats.REPORT_ALL, tagId, elapsedNanos, wallClockNanos, ret); break; @@ -1627,20 +918,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { break; } - case StatsLog.DISK_IO: { - pullDiskIo(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.PROCESS_CPU_TIME: { - pullProcessCpuTime(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - case StatsLog.CPU_TIME_PER_THREAD_FREQ: { - pullCpuTimePerThreadFreq(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - case StatsLog.DEBUG_ELAPSED_CLOCK: { pullDebugElapsedClock(tagId, elapsedNanos, wallClockNanos, ret); break; @@ -1651,54 +928,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { break; } - case StatsLog.ROLE_HOLDER: { - pullRoleHolders(elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.DANGEROUS_PERMISSION_STATE: { - pullDangerousPermissionState(StatsLog.DANGEROUS_PERMISSION_STATE, elapsedNanos, - wallClockNanos, ret); - break; - } - - case StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED: { - pullDangerousPermissionState(StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED, - elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.TIME_ZONE_DATA_INFO: { - pullTimeZoneDataInfo(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.EXTERNAL_STORAGE_INFO: { - pullExternalStorageInfo(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.APPS_ON_EXTERNAL_STORAGE_INFO: { - pullAppsOnExternalStorageInfo(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - case StatsLog.FACE_SETTINGS: { pullFaceSettings(tagId, elapsedNanos, wallClockNanos, ret); break; } - case StatsLog.APP_OPS: { - pullAppOps(elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.NOTIFICATION_REMOTE_VIEWS: { - pullNotificationStats(NotificationManagerService.REPORT_REMOTE_VIEWS, - tagId, elapsedNanos, wallClockNanos, ret); - break; - } - default: Slog.w(TAG, "No such tagId data as " + tagId); return null; diff --git a/api/current.txt b/api/current.txt index b071cd2e1d00..923506e5d1d8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3977,6 +3977,7 @@ package android.app { method public android.util.Size getAppTaskThumbnailSize(); method public java.util.List<android.app.ActivityManager.AppTask> getAppTasks(); method public android.content.pm.ConfigurationInfo getDeviceConfigurationInfo(); + method @Nullable public java.util.List<android.app.ApplicationExitInfo> getHistoricalProcessExitReasons(@Nullable String, @IntRange(from=0) int, @IntRange(from=0) int); method public int getLargeMemoryClass(); method public int getLauncherLargeIconDensity(); method public int getLauncherLargeIconSize(); @@ -3994,6 +3995,7 @@ package android.app { method public boolean isActivityStartAllowedOnDisplay(@NonNull android.content.Context, int, @NonNull android.content.Intent); method public boolean isBackgroundRestricted(); method @Deprecated public boolean isInLockTaskMode(); + method public static boolean isLowMemoryKillReportSupported(); method public boolean isLowRamDevice(); method @Deprecated public static boolean isRunningInTestHarness(); method public static boolean isRunningInUserTestHarness(); @@ -4507,6 +4509,35 @@ package android.app { field public String serviceDetails; } + public final class ApplicationExitInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getDefiningUid(); + method @Nullable public String getDescription(); + method public int getImportance(); + method public int getPackageUid(); + method public int getPid(); + method @NonNull public String getProcessName(); + method public int getPss(); + method public int getRealUid(); + method public int getReason(); + method public int getRss(); + method public int getStatus(); + method public long getTimestamp(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.app.ApplicationExitInfo> CREATOR; + field public static final int REASON_ANR = 6; // 0x6 + field public static final int REASON_CRASH = 4; // 0x4 + field public static final int REASON_CRASH_NATIVE = 5; // 0x5 + field public static final int REASON_EXCESSIVE_RESOURCE_USAGE = 9; // 0x9 + field public static final int REASON_EXIT_SELF = 1; // 0x1 + field public static final int REASON_INITIALIZATION_FAILURE = 7; // 0x7 + field public static final int REASON_LOW_MEMORY = 3; // 0x3 + field public static final int REASON_OTHER = 10; // 0xa + field public static final int REASON_PERMISSION_CHANGE = 8; // 0x8 + field public static final int REASON_SIGNALED = 2; // 0x2 + field public static final int REASON_UNKNOWN = 0; // 0x0 + } + public final class AsyncNotedAppOp implements android.os.Parcelable { method public int describeContents(); method @Nullable public String getFeatureId(); @@ -11669,11 +11700,8 @@ package android.content.pm { field public static final int STATUS_FAILURE_ABORTED = 3; // 0x3 field public static final int STATUS_FAILURE_BLOCKED = 2; // 0x2 field public static final int STATUS_FAILURE_CONFLICT = 5; // 0x5 - field public static final int STATUS_FAILURE_ILLEGAL_STATE = 9; // 0x9 field public static final int STATUS_FAILURE_INCOMPATIBLE = 7; // 0x7 field public static final int STATUS_FAILURE_INVALID = 4; // 0x4 - field public static final int STATUS_FAILURE_NAME_NOT_FOUND = 8; // 0x8 - field public static final int STATUS_FAILURE_SECURITY = 10; // 0xa field public static final int STATUS_FAILURE_STORAGE = 6; // 0x6 field public static final int STATUS_PENDING_USER_ACTION = -1; // 0xffffffff field public static final int STATUS_SUCCESS = 0; // 0x0 @@ -11695,7 +11723,6 @@ package android.content.pm { method public void removeChildSessionId(int); method public void removeSplit(@NonNull String) throws java.io.IOException; method public void setStagingProgress(float); - method public void transfer(@NonNull String, @NonNull android.content.IntentSender) throws android.content.pm.PackageManager.NameNotFoundException; method public void transfer(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException; } @@ -13251,6 +13278,8 @@ package android.database.sqlite { method public static int releaseMemory(); method public long replace(String, String, android.content.ContentValues); method public long replaceOrThrow(String, String, android.content.ContentValues) throws android.database.SQLException; + method public void setCustomAggregateFunction(@NonNull String, @NonNull java.util.function.BinaryOperator<java.lang.String>) throws android.database.sqlite.SQLiteException; + method public void setCustomScalarFunction(@NonNull String, @NonNull java.util.function.UnaryOperator<java.lang.String>) throws android.database.sqlite.SQLiteException; method public void setForeignKeyConstraintsEnabled(boolean); method public void setLocale(java.util.Locale); method @Deprecated public void setLockingEnabled(boolean); @@ -24399,28 +24428,39 @@ package android.media { method public static boolean hasProfile(int, int); field public static final int QUALITY_1080P = 6; // 0x6 field public static final int QUALITY_2160P = 8; // 0x8 + field public static final int QUALITY_2K = 12; // 0xc field public static final int QUALITY_480P = 4; // 0x4 + field public static final int QUALITY_4KDCI = 10; // 0xa field public static final int QUALITY_720P = 5; // 0x5 field public static final int QUALITY_CIF = 3; // 0x3 field public static final int QUALITY_HIGH = 1; // 0x1 field public static final int QUALITY_HIGH_SPEED_1080P = 2004; // 0x7d4 field public static final int QUALITY_HIGH_SPEED_2160P = 2005; // 0x7d5 field public static final int QUALITY_HIGH_SPEED_480P = 2002; // 0x7d2 + field public static final int QUALITY_HIGH_SPEED_4KDCI = 2008; // 0x7d8 field public static final int QUALITY_HIGH_SPEED_720P = 2003; // 0x7d3 + field public static final int QUALITY_HIGH_SPEED_CIF = 2006; // 0x7d6 field public static final int QUALITY_HIGH_SPEED_HIGH = 2001; // 0x7d1 field public static final int QUALITY_HIGH_SPEED_LOW = 2000; // 0x7d0 + field public static final int QUALITY_HIGH_SPEED_VGA = 2007; // 0x7d7 field public static final int QUALITY_LOW = 0; // 0x0 field public static final int QUALITY_QCIF = 2; // 0x2 + field public static final int QUALITY_QHD = 11; // 0xb field public static final int QUALITY_QVGA = 7; // 0x7 field public static final int QUALITY_TIME_LAPSE_1080P = 1006; // 0x3ee field public static final int QUALITY_TIME_LAPSE_2160P = 1008; // 0x3f0 + field public static final int QUALITY_TIME_LAPSE_2K = 1012; // 0x3f4 field public static final int QUALITY_TIME_LAPSE_480P = 1004; // 0x3ec + field public static final int QUALITY_TIME_LAPSE_4KDCI = 1010; // 0x3f2 field public static final int QUALITY_TIME_LAPSE_720P = 1005; // 0x3ed field public static final int QUALITY_TIME_LAPSE_CIF = 1003; // 0x3eb field public static final int QUALITY_TIME_LAPSE_HIGH = 1001; // 0x3e9 field public static final int QUALITY_TIME_LAPSE_LOW = 1000; // 0x3e8 field public static final int QUALITY_TIME_LAPSE_QCIF = 1002; // 0x3ea + field public static final int QUALITY_TIME_LAPSE_QHD = 1011; // 0x3f3 field public static final int QUALITY_TIME_LAPSE_QVGA = 1007; // 0x3ef + field public static final int QUALITY_TIME_LAPSE_VGA = 1009; // 0x3f1 + field public static final int QUALITY_VGA = 9; // 0x9 field public int audioBitRate; field public int audioChannels; field public int audioCodec; @@ -30256,6 +30296,7 @@ package android.net.sip { method public void close(); method public void continueCall(int) throws android.net.sip.SipException; method public void endCall() throws android.net.sip.SipException; + method @Nullable public android.net.rtp.AudioGroup getAudioGroup(); method public android.net.sip.SipProfile getLocalProfile(); method public android.net.sip.SipProfile getPeerProfile(); method public int getState(); @@ -30266,6 +30307,7 @@ package android.net.sip { method public void makeCall(android.net.sip.SipProfile, android.net.sip.SipSession, int) throws android.net.sip.SipException; method public void sendDtmf(int); method public void sendDtmf(int, android.os.Message); + method public void setAudioGroup(@NonNull android.net.rtp.AudioGroup); method public void setListener(android.net.sip.SipAudioCall.Listener); method public void setListener(android.net.sip.SipAudioCall.Listener, boolean); method public void setSpeakerMode(boolean); @@ -30314,6 +30356,7 @@ package android.net.sip { method public void close(String) throws android.net.sip.SipException; method public android.net.sip.SipSession createSipSession(android.net.sip.SipProfile, android.net.sip.SipSession.Listener) throws android.net.sip.SipException; method public static String getCallId(android.content.Intent); + method @NonNull public java.util.List<android.net.sip.SipProfile> getListOfProfiles() throws android.net.sip.SipException; method public static String getOfferSessionDescription(android.content.Intent); method public android.net.sip.SipSession getSessionFor(android.content.Intent) throws android.net.sip.SipException; method public static boolean isApiSupported(android.content.Context); @@ -30331,6 +30374,11 @@ package android.net.sip { method public void setRegistrationListener(String, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; method public android.net.sip.SipAudioCall takeAudioCall(android.content.Intent, android.net.sip.SipAudioCall.Listener) throws android.net.sip.SipException; method public void unregister(android.net.sip.SipProfile, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException; + field public static final String ACTION_SIP_CALL_OPTION_CHANGED = "android.net.sip.action.SIP_CALL_OPTION_CHANGED"; + field public static final String ACTION_SIP_INCOMING_CALL = "android.net.sip.action.SIP_INCOMING_CALL"; + field public static final String ACTION_SIP_REMOVE_PROFILE = "android.net.sip.action.SIP_REMOVE_PROFILE"; + field public static final String ACTION_SIP_SERVICE_UP = "android.net.sip.action.SIP_SERVICE_UP"; + field public static final String ACTION_START_SIP = "android.net.sip.action.START_SIP"; field public static final String EXTRA_CALL_ID = "android:sipCallID"; field public static final String EXTRA_OFFER_SD = "android:sipOfferSD"; field public static final int INCOMING_CALL_RESULT_CODE = 101; // 0x65 @@ -30340,6 +30388,7 @@ package android.net.sip { method public int describeContents(); method public String getAuthUserName(); method public boolean getAutoRegistration(); + method public int getCallingUid(); method public String getDisplayName(); method public String getPassword(); method public int getPort(); @@ -30350,6 +30399,7 @@ package android.net.sip { method public String getSipDomain(); method public String getUriString(); method public String getUserName(); + method public void setCallingUid(int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.sip.SipProfile> CREATOR; } @@ -30485,6 +30535,21 @@ package android.net.wifi { field public CharSequence venueName; } + public final class SoftApConfiguration implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public android.net.MacAddress getBssid(); + method @Nullable public String getPassphrase(); + method public int getSecurityType(); + method @Nullable public String getSsid(); + method public boolean isHiddenSsid(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApConfiguration> CREATOR; + field public static final int SECURITY_TYPE_OPEN = 0; // 0x0 + field public static final int SECURITY_TYPE_WPA2_PSK = 1; // 0x1 + field public static final int SECURITY_TYPE_WPA3_SAE = 3; // 0x3 + field public static final int SECURITY_TYPE_WPA3_SAE_TRANSITION = 2; // 0x2 + } + public enum SupplicantState implements android.os.Parcelable { method public int describeContents(); method public static boolean isValidState(android.net.wifi.SupplicantState); @@ -30736,6 +30801,7 @@ package android.net.wifi { method public boolean isTdlsSupported(); method public boolean isWapiSupported(); method public boolean isWifiEnabled(); + method public boolean isWifiStandardSupported(int); method public boolean isWpa3SaeSupported(); method public boolean isWpa3SuiteBSupported(); method @Deprecated public boolean pingSupplicant(); @@ -30778,6 +30844,7 @@ package android.net.wifi { field public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 3; // 0x3 field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 4; // 0x4 + field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED = 6; // 0x6 field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED = 2; // 0x2 field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1; // 0x1 field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5; // 0x5 @@ -30819,7 +30886,8 @@ package android.net.wifi { public class WifiManager.LocalOnlyHotspotReservation implements java.lang.AutoCloseable { method public void close(); - method public android.net.wifi.WifiConfiguration getWifiConfiguration(); + method @NonNull public android.net.wifi.SoftApConfiguration getSoftApConfiguration(); + method @Deprecated @Nullable public android.net.wifi.WifiConfiguration getWifiConfiguration(); } public class WifiManager.MulticastLock { @@ -30894,6 +30962,7 @@ package android.net.wifi { method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPasspointConfig(@NonNull android.net.wifi.hotspot2.PasspointConfiguration); method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(@IntRange(from=0) int); method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String); + method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setUntrusted(boolean); method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiEnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig); method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiPassphrase(@NonNull String); method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig); @@ -41699,6 +41768,7 @@ package android.se.omapi { public final class SEService { ctor public SEService(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.se.omapi.SEService.OnConnectedListener); method @NonNull public android.se.omapi.Reader[] getReaders(); + method @NonNull public android.se.omapi.Reader getUiccReader(int); method @NonNull public String getVersion(); method public boolean isConnected(); method public void shutdown(); @@ -46522,6 +46592,7 @@ package android.telephony { method @Deprecated public String iccTransmitApduBasicChannel(int, int, int, int, int, String); method @Deprecated public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String); method public boolean isConcurrentVoiceAndDataSupported(); + method public boolean isDataCapable(); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean isDataEnabled(); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled(); method public boolean isEmergencyNumber(@NonNull String); @@ -47028,6 +47099,37 @@ package android.telephony.gsm { package android.telephony.ims { + public final class ImsException extends java.lang.Exception { + method public int getCode(); + field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1 + field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0 + field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2 + } + + public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { + method @NonNull @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getVoWiFiModeSetting(); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isAdvancedCallingSettingEnabled(); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isTtyOverVolteEnabled(); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVoWiFiRoamingSettingEnabled(); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVoWiFiSettingEnabled(); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVtSettingEnabled(); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback); + field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1 + field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0 + field public static final int WIFI_MODE_WIFI_PREFERRED = 2; // 0x2 + } + + public static class ImsMmTelManager.CapabilityCallback { + ctor public ImsMmTelManager.CapabilityCallback(); + method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); + } + public final class ImsReasonInfo implements android.os.Parcelable { ctor public ImsReasonInfo(int, int, @Nullable String); method public int describeContents(); @@ -47211,6 +47313,38 @@ package android.telephony.ims { field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2 } + public interface RegistrationManager { + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); + field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0 + field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2 + field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1 + } + + public static class RegistrationManager.RegistrationCallback { + ctor public RegistrationManager.RegistrationCallback(); + method public void onRegistered(int); + method public void onRegistering(int); + method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo); + method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo); + } + +} + +package android.telephony.ims.feature { + + public class MmTelFeature { + } + + public static class MmTelFeature.MmTelCapabilities { + field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8 + field public static final int CAPABILITY_TYPE_UT = 4; // 0x4 + field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2 + field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1 + } + } package android.telephony.mbms { @@ -50484,6 +50618,7 @@ package android.view { public final class DisplayCutout { ctor public DisplayCutout(@NonNull android.graphics.Insets, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect); + ctor public DisplayCutout(@NonNull android.graphics.Insets, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @NonNull android.graphics.Insets); ctor @Deprecated public DisplayCutout(@Nullable android.graphics.Rect, @Nullable java.util.List<android.graphics.Rect>); method @NonNull public android.graphics.Rect getBoundingRectBottom(); method @NonNull public android.graphics.Rect getBoundingRectLeft(); @@ -50494,6 +50629,7 @@ package android.view { method public int getSafeInsetLeft(); method public int getSafeInsetRight(); method public int getSafeInsetTop(); + method @NonNull public android.graphics.Insets getWaterfallInsets(); } public final class DragAndDropPermissions implements android.os.Parcelable { @@ -53794,6 +53930,7 @@ package android.view { field public static final int LAST_SUB_WINDOW = 1999; // 0x7cf field public static final int LAST_SYSTEM_WINDOW = 2999; // 0xbb7 field public static final int LAYOUT_CHANGED = 1; // 0x1 + field public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 3; // 0x3 field public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0; // 0x0 field public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2; // 0x2 field public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES = 1; // 0x1 diff --git a/api/system-current.txt b/api/system-current.txt index 6c23ef671d0e..c9de97ed4a9a 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -326,6 +326,8 @@ package android.app { method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getPackageImportance(String); method @NonNull public java.util.Collection<java.util.Locale> getSupportedLocales(); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, "android.permission.CREATE_USERS"}) public boolean isProfileForeground(@NonNull android.os.UserHandle); + method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void killProcessesWhenImperceptible(@NonNull int[], @NonNull String); method @RequiresPermission(android.Manifest.permission.KILL_UID) public void killUid(int, String); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener); method public void setDeviceLocales(@NonNull android.os.LocaleList); @@ -566,6 +568,10 @@ package android.app { field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.PackageOps> CREATOR; } + public final class ApplicationExitInfo implements android.os.Parcelable { + method @NonNull public android.os.UserHandle getUserHandle(); + } + public class BroadcastOptions { method public static android.app.BroadcastOptions makeBasic(); method @RequiresPermission("android.permission.START_ACTIVITIES_FROM_BACKGROUND") public void setBackgroundActivityStartsAllowed(boolean); @@ -1819,6 +1825,7 @@ package android.content { field public static final String EXTRA_PERMISSION_GROUP_NAME = "android.intent.extra.PERMISSION_GROUP_NAME"; field public static final String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME"; field public static final String EXTRA_REASON = "android.intent.extra.REASON"; + field @Deprecated public static final String EXTRA_REBROADCAST_ON_UNLOCK = "rebroadcastOnUnlock"; field public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK"; field public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED"; field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME"; @@ -4665,11 +4672,6 @@ package android.media.tv.tuner { method public int getVideoFilterCount(); } - public abstract class FrontendSettings { - method public final int getFrequency(); - method public abstract int getType(); - } - public class Lnb implements java.lang.AutoCloseable { method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void close(); method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int sendDiseqcMessage(@NonNull byte[]); @@ -4698,7 +4700,7 @@ package android.media.tv.tuner { method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Tuner.Descrambler openDescrambler(); method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void setOnTuneEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.OnTuneEventListener); method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int stopTune(); - method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int tune(@NonNull android.media.tv.tuner.FrontendSettings); + method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings); } public class Tuner.Descrambler { @@ -4781,6 +4783,60 @@ package android.media.tv.tuner.filter { package android.media.tv.tuner.frontend { + public class AnalogFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings { + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder builder(@NonNull android.content.Context); + method public int getSifStandard(); + method public int getSignalType(); + method public int getType(); + field public static final int SIF_BG = 1; // 0x1 + field public static final int SIF_BG_A2 = 2; // 0x2 + field public static final int SIF_BG_NICAM = 4; // 0x4 + field public static final int SIF_DK = 16; // 0x10 + field public static final int SIF_DK1 = 32; // 0x20 + field public static final int SIF_DK2 = 64; // 0x40 + field public static final int SIF_DK3 = 128; // 0x80 + field public static final int SIF_DK_NICAM = 256; // 0x100 + field public static final int SIF_I = 8; // 0x8 + field public static final int SIF_I_NICAM = 16384; // 0x4000 + field public static final int SIF_L = 512; // 0x200 + field public static final int SIF_L_NICAM = 32768; // 0x8000 + field public static final int SIF_L_PRIME = 65536; // 0x10000 + field public static final int SIF_M = 1024; // 0x400 + field public static final int SIF_M_A2 = 4096; // 0x1000 + field public static final int SIF_M_BTSC = 2048; // 0x800 + field public static final int SIF_M_EIA_J = 8192; // 0x2000 + field public static final int SIF_UNDEFINED = 0; // 0x0 + field public static final int SIGNAL_TYPE_NTSC = 4; // 0x4 + field public static final int SIGNAL_TYPE_PAL = 1; // 0x1 + field public static final int SIGNAL_TYPE_SECAM = 2; // 0x2 + field public static final int SIGNAL_TYPE_UNDEFINED = 0; // 0x0 + } + + public static class AnalogFrontendSettings.Builder extends android.media.tv.tuner.frontend.FrontendSettings.Builder<android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder> { + method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings build(); + method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setASignalType(int); + method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSifStandard(int); + } + + public abstract class FrontendSettings { + method public int getFrequency(); + method public abstract int getType(); + field public static final int TYPE_ANALOG = 1; // 0x1 + field public static final int TYPE_ATSC = 2; // 0x2 + field public static final int TYPE_ATSC3 = 3; // 0x3 + field public static final int TYPE_DVBC = 4; // 0x4 + field public static final int TYPE_DVBS = 5; // 0x5 + field public static final int TYPE_DVBT = 6; // 0x6 + field public static final int TYPE_ISDBS = 7; // 0x7 + field public static final int TYPE_ISDBS3 = 8; // 0x8 + field public static final int TYPE_ISDBT = 9; // 0x9 + field public static final int TYPE_UNDEFINED = 0; // 0x0 + } + + public abstract static class FrontendSettings.Builder<T extends android.media.tv.tuner.frontend.FrontendSettings.Builder<T>> { + method @IntRange(from=1) @NonNull public T setFrequency(int); + } + public interface OnTuneEventListener { method public void onTuneEvent(int); field public static final int SIGNAL_LOCKED = 0; // 0x0 @@ -5022,6 +5078,8 @@ package android.net { } public abstract class NetworkAgent { + ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider); + method @Nullable public android.net.Network getNetwork(); method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData); method public void onAutomaticReconnectDisabled(); method public void onBandwidthUpdateRequested(); @@ -5032,18 +5090,24 @@ package android.net { method public void onStartSocketKeepalive(int, int, @NonNull android.net.KeepalivePacketData); method public void onStopSocketKeepalive(int); method public void onValidationStatus(int, @Nullable String); + method @NonNull public android.net.Network register(); method public void sendLinkProperties(@NonNull android.net.LinkProperties); method public void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities); method public void sendNetworkScore(int); method public void sendSocketKeepaliveEvent(int, int); + method public void setConnected(); + method @Deprecated public void setLegacyExtraInfo(@Nullable String); + method @Deprecated public void setLegacySubtype(int, @NonNull String); + method public void unregister(); field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2 field public static final int VALIDATION_STATUS_VALID = 1; // 0x1 - field @NonNull public final android.net.Network network; field public final int providerId; } public final class NetworkAgentConfig implements android.os.Parcelable { method public int describeContents(); + method public int getLegacyType(); + method @NonNull public String getLegacyTypeName(); method @Nullable public String getSubscriberId(); method public boolean isNat64DetectionEnabled(); method public boolean isProvisioningNotificationEnabled(); @@ -5056,6 +5120,8 @@ package android.net { method @NonNull public android.net.NetworkAgentConfig build(); method @NonNull public android.net.NetworkAgentConfig.Builder disableNat64Detection(); method @NonNull public android.net.NetworkAgentConfig.Builder disableProvisioningNotification(); + method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int); + method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String); method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String); } @@ -5235,6 +5301,15 @@ package android.net { method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress); } + public final class StringNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { + ctor public StringNetworkSpecifier(@NonNull String); + method public int describeContents(); + method public boolean satisfiedBy(android.net.NetworkSpecifier); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.StringNetworkSpecifier> CREATOR; + field @NonNull public final String specifier; + } + public final class TelephonyNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { method public boolean satisfiedBy(android.net.NetworkSpecifier); } @@ -5364,9 +5439,11 @@ package android.net.ipsec.ike { } public abstract class ChildSessionParams { + method public long getHardLifetime(); method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getLocalTrafficSelectors(); method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getRemoteTrafficSelectors(); method @NonNull public java.util.List<android.net.ipsec.ike.ChildSaProposal> getSaProposals(); + method public long getSoftLifetime(); } public class IkeFqdnIdentification extends android.net.ipsec.ike.IkeIdentification { @@ -5435,12 +5512,14 @@ package android.net.ipsec.ike { } public final class IkeSessionParams { + method public long getHardLifetime(); method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getLocalAuthConfig(); method @NonNull public android.net.ipsec.ike.IkeIdentification getLocalIdentification(); method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getRemoteAuthConfig(); method @NonNull public android.net.ipsec.ike.IkeIdentification getRemoteIdentification(); method @NonNull public java.util.List<android.net.ipsec.ike.IkeSaProposal> getSaProposals(); method @NonNull public java.net.InetAddress getServerAddress(); + method public long getSoftLifetime(); method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket getUdpEncapsulationSocket(); } @@ -5452,6 +5531,7 @@ package android.net.ipsec.ike { method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@Nullable java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.util.List<java.security.cert.X509Certificate>, @NonNull java.security.PrivateKey); method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthEap(@Nullable java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig); method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthPsk(@NonNull byte[]); + method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setLifetime(long, long); method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setLocalIdentification(@NonNull android.net.ipsec.ike.IkeIdentification); method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setRemoteIdentification(@NonNull android.net.ipsec.ike.IkeIdentification); method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setServerAddress(@NonNull java.net.InetAddress); @@ -5522,6 +5602,7 @@ package android.net.ipsec.ike { method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal); method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams build(); + method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder setLifetime(long, long); } public final class TunnelModeChildSessionParams extends android.net.ipsec.ike.ChildSessionParams { @@ -5539,6 +5620,7 @@ package android.net.ipsec.ike { method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal); method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams build(); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder setLifetime(long, long); } public static interface TunnelModeChildSessionParams.ConfigRequest { @@ -6041,29 +6123,18 @@ package android.net.wifi { } public final class SoftApConfiguration implements android.os.Parcelable { - method public int describeContents(); method @NonNull public java.util.List<android.net.MacAddress> getAllowedClientList(); method public int getBand(); method @NonNull public java.util.List<android.net.MacAddress> getBlockedClientList(); - method @Nullable public android.net.MacAddress getBssid(); method public int getChannel(); method public int getMaxNumberOfClients(); - method @Nullable public String getPassphrase(); - method public int getSecurityType(); method public int getShutdownTimeoutMillis(); - method @Nullable public String getSsid(); method public boolean isClientControlByUserEnabled(); - method public boolean isHiddenSsid(); - method public void writeToParcel(@NonNull android.os.Parcel, int); + 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_6GHZ = 4; // 0x4 field public static final int BAND_ANY = 7; // 0x7 - field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApConfiguration> CREATOR; - field public static final int SECURITY_TYPE_OPEN = 0; // 0x0 - field public static final int SECURITY_TYPE_WPA2_PSK = 1; // 0x1 - field public static final int SECURITY_TYPE_WPA3_SAE = 3; // 0x3 - field public static final int SECURITY_TYPE_WPA3_SAE_TRANSITION = 2; // 0x2 } public static final class SoftApConfiguration.Builder { @@ -6262,7 +6333,7 @@ package android.net.wifi { method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.SoftApConfiguration getSoftApConfiguration(); method public int getVerboseLoggingLevel(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void getWifiActivityEnergyInfoAsync(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiActivityEnergyInfoListener); - method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration(); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState(); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(@NonNull java.util.List<android.net.wifi.ScanResult>); method public boolean isApMacRandomizationSupported(); @@ -8337,6 +8408,7 @@ package android.provider { public static final class Telephony.SimInfo { field public static final String ACCESS_RULES = "access_rules"; field public static final String ACCESS_RULES_FROM_CARRIER_CONFIGS = "access_rules_from_carrier_configs"; + field public static final String ALLOWED_NETWORK_TYPES = "allowed_network_types"; field public static final String CARD_ID = "card_id"; field public static final String CARRIER_ID = "carrier_id"; field public static final String CARRIER_NAME = "carrier_name"; @@ -10287,6 +10359,19 @@ package android.telephony { field public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000 } + public final class PinResult implements android.os.Parcelable { + ctor public PinResult(int, int); + method public int describeContents(); + method public int getAttemptsRemaining(); + method @NonNull public static android.telephony.PinResult getDefaultFailedResult(); + method public int getType(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PinResult> CREATOR; + field public static final int PIN_RESULT_TYPE_FAILURE = 2; // 0x2 + field public static final int PIN_RESULT_TYPE_INCORRECT = 1; // 0x1 + field public static final int PIN_RESULT_TYPE_SUCCESS = 0; // 0x0 + } + public final class PreciseCallState implements android.os.Parcelable { ctor public PreciseCallState(int, int, int, int, int); method public int describeContents(); @@ -10655,6 +10740,7 @@ package android.telephony { public class TelephonyManager { method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting); method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int changeIccLockPassword(@NonNull String, @NonNull String); method public int checkCarrierPrivilegesForPackage(String); method public int checkCarrierPrivilegesForPackageAnyPhone(String); method public void dial(String); @@ -10664,6 +10750,7 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); @@ -10717,11 +10804,13 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int); method public boolean isCurrentSimOperator(@NonNull String, int, @Nullable String); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataAllowedInVoiceCall(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataConnectionEnabled(); method public boolean isDataConnectivityPossible(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isGlobalModeEnabled(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isInEmergencySmsMode(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isManualNetworkSelectionAllowed(); @@ -10747,14 +10836,17 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig(); method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings(); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAlwaysAllowMmsData(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCdmaRoamingMode(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCdmaSubscriptionMode(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setDataAllowedDuringVoiceCall(boolean); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setIccLockEnabled(boolean, @NonNull String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPolicyDataEnabled(boolean); @@ -10768,9 +10860,11 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String); + method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult supplyPinReportPinResult(@NonNull String); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String); + method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult supplyPukReportPinResult(@NonNull String, @NonNull String); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff(); method public void updateServiceLocation(); @@ -10801,6 +10895,7 @@ package android.telephony { field public static final int CDMA_SUBSCRIPTION_NV = 1; // 0x1 field public static final int CDMA_SUBSCRIPTION_RUIM_SIM = 0; // 0x0 field public static final int CDMA_SUBSCRIPTION_UNKNOWN = -1; // 0xffffffff + field public static final int CHANGE_ICC_LOCK_SUCCESS = 2147483647; // 0x7fffffff field public static final int DEFAULT_PREFERRED_NETWORK_MODE = 0; // 0x0 field public static final String EXTRA_ANOMALY_DESCRIPTION = "android.telephony.extra.ANOMALY_DESCRIPTION"; field public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID"; @@ -10946,6 +11041,23 @@ package android.telephony.cdma { package android.telephony.data { + public class ApnSetting implements android.os.Parcelable { + method @NonNull public static String getApnTypesStringFromBitmask(int); + field public static final String TYPE_ALL_STRING = "*"; + field public static final String TYPE_CBS_STRING = "cbs"; + field public static final String TYPE_DEFAULT_STRING = "default"; + field public static final String TYPE_DUN_STRING = "dun"; + field public static final String TYPE_EMERGENCY_STRING = "emergency"; + field public static final String TYPE_FOTA_STRING = "fota"; + field public static final String TYPE_HIPRI_STRING = "hipri"; + field public static final String TYPE_IA_STRING = "ia"; + field public static final String TYPE_IMS_STRING = "ims"; + field public static final String TYPE_MCX_STRING = "mcx"; + field public static final String TYPE_MMS_STRING = "mms"; + field public static final String TYPE_SUPL_STRING = "supl"; + field public static final String TYPE_XCAP_STRING = "xcap"; + } + public final class DataCallResponse implements android.os.Parcelable { method public int describeContents(); method @NonNull public java.util.List<android.net.LinkAddress> getAddresses(); @@ -11258,6 +11370,7 @@ package android.telephony.ims { method public int getEmergencyServiceCategories(); method @NonNull public java.util.List<java.lang.String> getEmergencyUrns(); method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile(); + method @Nullable public android.os.Bundle getProprietaryCallExtras(); method public int getRestrictCause(); method public int getServiceType(); method public static int getVideoStateFromCallType(int); @@ -11396,10 +11509,6 @@ package android.telephony.ims { ctor public ImsException(@Nullable String); ctor public ImsException(@Nullable String, int); ctor public ImsException(@Nullable String, int, @Nullable Throwable); - method public int getCode(); - field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1 - field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0 - field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2 } public final class ImsExternalCallState implements android.os.Parcelable { @@ -11425,23 +11534,13 @@ package android.telephony.ims { } public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { - method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException; - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTtyOverVolteEnabled(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled(); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled(); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int); @@ -11451,16 +11550,6 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback); - field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1 - field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0 - field public static final int WIFI_MODE_WIFI_PREFERRED = 2; // 0x2 - } - - public static class ImsMmTelManager.CapabilityCallback { - ctor public ImsMmTelManager.CapabilityCallback(); - method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); } @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback { @@ -11800,24 +11889,6 @@ package android.telephony.ims { method @NonNull public android.telephony.ims.RcsContactUceCapability build(); } - public interface RegistrationManager { - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); - field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0 - field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2 - field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1 - } - - public static class RegistrationManager.RegistrationCallback { - ctor public RegistrationManager.RegistrationCallback(); - method public void onRegistered(int); - method public void onRegistering(int); - method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo); - method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo); - } - } package android.telephony.ims.feature { @@ -11880,7 +11951,7 @@ package android.telephony.ims.feature { method public void onFeatureReady(); method public void onFeatureRemoved(); method public boolean queryCapabilityConfiguration(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); - method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); + method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); method public void setUiTtyMode(int, @Nullable android.os.Message); method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]); field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; @@ -11896,10 +11967,6 @@ package android.telephony.ims.feature { method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); - field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8 - field public static final int CAPABILITY_TYPE_UT = 4; // 0x4 - field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2 - field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1 } @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.MmTelCapabilities.MmTelCapability { diff --git a/api/system-removed.txt b/api/system-removed.txt index 973d827e4889..07b896905986 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -121,18 +121,6 @@ package android.media.tv { } -package android.net { - - @Deprecated public final class StringNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { - ctor public StringNetworkSpecifier(@NonNull String); - method public int describeContents(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.StringNetworkSpecifier> CREATOR; - field @NonNull public final String specifier; - } - -} - package android.net.wifi { @Deprecated public class BatchedScanResult implements android.os.Parcelable { diff --git a/api/test-current.txt b/api/test-current.txt index c8bfa469d114..519ead8394b9 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -70,6 +70,7 @@ package android.app { method public long getTotalRam(); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int); method public static boolean isHighEndGfx(); + method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void killProcessesWhenImperceptible(@NonNull int[], @NonNull String); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener); 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); @@ -1119,6 +1120,7 @@ package android.hardware.display { method @RequiresPermission(android.Manifest.permission.BRIGHTNESS_SLIDER_USAGE) public java.util.List<android.hardware.display.BrightnessChangeEvent> getBrightnessEvents(); method @Nullable @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public android.hardware.display.BrightnessConfiguration getDefaultBrightnessConfiguration(); method public android.graphics.Point getStableDisplaySize(); + method public boolean isMinimalPostProcessingRequested(int); method @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration); } @@ -3373,6 +3375,7 @@ package android.telephony.ims { method public int getEmergencyServiceCategories(); method @NonNull public java.util.List<java.lang.String> getEmergencyUrns(); method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile(); + method @Nullable public android.os.Bundle getProprietaryCallExtras(); method public int getRestrictCause(); method public int getServiceType(); method public static int getVideoStateFromCallType(int); @@ -3426,6 +3429,7 @@ package android.telephony.ims { field public static final String EXTRA_DISPLAY_TEXT = "DisplayText"; field public static final String EXTRA_EMERGENCY_CALL = "e_call"; field public static final String EXTRA_IS_CALL_PULL = "CallPull"; + field public static final String EXTRA_OEM_EXTRAS = "android.telephony.ims.extra.OEM_EXTRAS"; field public static final String EXTRA_OI = "oi"; field public static final String EXTRA_OIR = "oir"; field public static final String EXTRA_REMOTE_URI = "remote_uri"; @@ -3511,10 +3515,6 @@ package android.telephony.ims { ctor public ImsException(@Nullable String); ctor public ImsException(@Nullable String, int); ctor public ImsException(@Nullable String, int, @Nullable Throwable); - method public int getCode(); - field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1 - field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0 - field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2 } public final class ImsExternalCallState implements android.os.Parcelable { @@ -3540,23 +3540,13 @@ package android.telephony.ims { } public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { - method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiModeSetting(); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiRoamingModeSetting(); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAdvancedCallingSettingEnabled(); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException; - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isTtyOverVolteEnabled(); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiRoamingSettingEnabled(); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiSettingEnabled(); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVtSettingEnabled(); method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int); @@ -3566,16 +3556,6 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean); method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback); - field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1 - field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0 - field public static final int WIFI_MODE_WIFI_PREFERRED = 2; // 0x2 - } - - public static class ImsMmTelManager.CapabilityCallback { - ctor public ImsMmTelManager.CapabilityCallback(); - method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); } @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback { @@ -3863,24 +3843,6 @@ package android.telephony.ims { method public void onProvisioningStringChanged(int, @NonNull String); } - public interface RegistrationManager { - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback); - field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0 - field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2 - field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1 - } - - public static class RegistrationManager.RegistrationCallback { - ctor public RegistrationManager.RegistrationCallback(); - method public void onRegistered(int); - method public void onRegistering(int); - method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo); - method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo); - } - } package android.telephony.ims.feature { @@ -3943,7 +3905,7 @@ package android.telephony.ims.feature { method public void onFeatureReady(); method public void onFeatureRemoved(); method public boolean queryCapabilityConfiguration(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int); - method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); + method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); method public void setUiTtyMode(int, @Nullable android.os.Message); method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]); field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; @@ -3959,10 +3921,6 @@ package android.telephony.ims.feature { method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); - field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8 - field public static final int CAPABILITY_TYPE_UT = 4; // 0x4 - field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2 - field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1 } @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.MmTelCapabilities.MmTelCapability { @@ -4493,7 +4451,7 @@ package android.view { field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000 field public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 64; // 0x40 field public CharSequence accessibilityTitle; - field @android.view.ViewDebug.ExportedProperty(flagMapping={@android.view.ViewDebug.FlagToString(mask=0x1, equals=0x1, name="FAKE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x2, equals=0x2, name="FORCE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x4, equals=0x4, name="WANTS_OFFSET_NOTIFICATIONS"), @android.view.ViewDebug.FlagToString(mask=0x10, equals=0x10, name="SHOW_FOR_ALL_USERS"), @android.view.ViewDebug.FlagToString(mask=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, equals=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, name="NO_MOVE_ANIMATION"), @android.view.ViewDebug.FlagToString(mask=0x80, equals=0x80, name="COMPATIBLE_WINDOW"), @android.view.ViewDebug.FlagToString(mask=0x100, equals=0x100, name="SYSTEM_ERROR"), @android.view.ViewDebug.FlagToString(mask=0x400, equals=0x400, name="KEYGUARD"), @android.view.ViewDebug.FlagToString(mask=0x800, equals=0x800, name="DISABLE_WALLPAPER_TOUCH_EVENTS"), @android.view.ViewDebug.FlagToString(mask=0x1000, equals=0x1000, name="FORCE_STATUS_BAR_VISIBLE_TRANSPARENT"), @android.view.ViewDebug.FlagToString(mask=0x2000, equals=0x2000, name="PRESERVE_GEOMETRY"), @android.view.ViewDebug.FlagToString(mask=0x4000, equals=0x4000, name="FORCE_DECOR_VIEW_VISIBILITY"), @android.view.ViewDebug.FlagToString(mask=0x8000, equals=0x8000, name="WILL_NOT_REPLACE_ON_RELAUNCH"), @android.view.ViewDebug.FlagToString(mask=0x10000, equals=0x10000, name="LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), @android.view.ViewDebug.FlagToString(mask=0x20000, equals=0x20000, name="FORCE_DRAW_STATUS_BAR_BACKGROUND"), @android.view.ViewDebug.FlagToString(mask=0x40000, equals=0x40000, name="SUSTAINED_PERFORMANCE_MODE"), @android.view.ViewDebug.FlagToString(mask=0x80000, equals=0x80000, name="HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @android.view.ViewDebug.FlagToString(mask=0x100000, equals=0x100000, name="IS_ROUNDED_CORNERS_OVERLAY"), @android.view.ViewDebug.FlagToString(mask=0x400000, equals=0x400000, name="IS_SCREEN_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x800000, equals=0x800000, name="STATUS_FORCE_SHOW_NAVIGATION"), @android.view.ViewDebug.FlagToString(mask=0x1000000, equals=0x1000000, name="COLOR_SPACE_AGNOSTIC"), @android.view.ViewDebug.FlagToString(mask=0x4000000, equals=0x4000000, name="FIT_INSETS_CONTROLLED"), @android.view.ViewDebug.FlagToString(mask=0x8000000, equals=0x8000000, name="ONLY_DRAW_BOTTOM_BAR_BACKGROUND")}) public int privateFlags; + field @android.view.ViewDebug.ExportedProperty(flagMapping={@android.view.ViewDebug.FlagToString(mask=0x1, equals=0x1, name="FAKE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x2, equals=0x2, name="FORCE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x4, equals=0x4, name="WANTS_OFFSET_NOTIFICATIONS"), @android.view.ViewDebug.FlagToString(mask=0x10, equals=0x10, name="SHOW_FOR_ALL_USERS"), @android.view.ViewDebug.FlagToString(mask=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, equals=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, name="NO_MOVE_ANIMATION"), @android.view.ViewDebug.FlagToString(mask=0x80, equals=0x80, name="COMPATIBLE_WINDOW"), @android.view.ViewDebug.FlagToString(mask=0x100, equals=0x100, name="SYSTEM_ERROR"), @android.view.ViewDebug.FlagToString(mask=0x800, equals=0x800, name="DISABLE_WALLPAPER_TOUCH_EVENTS"), @android.view.ViewDebug.FlagToString(mask=0x1000, equals=0x1000, name="FORCE_STATUS_BAR_VISIBLE"), @android.view.ViewDebug.FlagToString(mask=0x2000, equals=0x2000, name="PRESERVE_GEOMETRY"), @android.view.ViewDebug.FlagToString(mask=0x4000, equals=0x4000, name="FORCE_DECOR_VIEW_VISIBILITY"), @android.view.ViewDebug.FlagToString(mask=0x8000, equals=0x8000, name="WILL_NOT_REPLACE_ON_RELAUNCH"), @android.view.ViewDebug.FlagToString(mask=0x10000, equals=0x10000, name="LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), @android.view.ViewDebug.FlagToString(mask=0x20000, equals=0x20000, name="FORCE_DRAW_STATUS_BAR_BACKGROUND"), @android.view.ViewDebug.FlagToString(mask=0x40000, equals=0x40000, name="SUSTAINED_PERFORMANCE_MODE"), @android.view.ViewDebug.FlagToString(mask=0x80000, equals=0x80000, name="HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @android.view.ViewDebug.FlagToString(mask=0x100000, equals=0x100000, name="IS_ROUNDED_CORNERS_OVERLAY"), @android.view.ViewDebug.FlagToString(mask=0x400000, equals=0x400000, name="IS_SCREEN_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x800000, equals=0x800000, name="STATUS_FORCE_SHOW_NAVIGATION"), @android.view.ViewDebug.FlagToString(mask=0x1000000, equals=0x1000000, name="COLOR_SPACE_AGNOSTIC"), @android.view.ViewDebug.FlagToString(mask=0x4000000, equals=0x4000000, name="FIT_INSETS_CONTROLLED"), @android.view.ViewDebug.FlagToString(mask=0x8000000, equals=0x8000000, name="ONLY_DRAW_BOTTOM_BAR_BACKGROUND")}) public int privateFlags; } } diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 8fac31a05c49..2537edaf9e81 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -100,6 +100,7 @@ static constexpr size_t FONT_NUM_ROWS = FONT_NUM_CHARS / FONT_NUM_COLS; static const int TEXT_CENTER_VALUE = INT_MAX; static const int TEXT_MISSING_VALUE = INT_MIN; static const char EXIT_PROP_NAME[] = "service.bootanim.exit"; +static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; @@ -291,10 +292,10 @@ status_t BootAnimation::readyToRun() { // this guest property specifies multi-display IDs to show the boot animation // multiple ids can be set with comma (,) as separator, for example: - // setprop boot.animation.displays 19260422155234049,19261083906282754 + // setprop persist.boot.animation.displays 19260422155234049,19261083906282754 Vector<uint64_t> physicalDisplayIds; char displayValue[PROPERTY_VALUE_MAX] = ""; - property_get("boot.animation.displays", displayValue, ""); + property_get(DISPLAYS_PROP_NAME, displayValue, ""); bool isValid = displayValue[0] != '\0'; if (isValid) { char *p = displayValue; @@ -306,7 +307,7 @@ status_t BootAnimation::readyToRun() { p ++; } if (!isValid) - SLOGE("Invalid syntax for the value of system prop: boot.animation.displays"); + SLOGE("Invalid syntax for the value of system prop: %s", DISPLAYS_PROP_NAME); } if (isValid) { std::istringstream stream(displayValue); diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 1c6867c39790..6eafbd8bb3f1 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -73,7 +73,6 @@ cc_defaults { "src/external/puller_util.cpp", "src/external/ResourceHealthManagerPuller.cpp", "src/external/StatsCallbackPuller.cpp", - "src/external/StatsCallbackPullerDeprecated.cpp", "src/external/StatsCompanionServicePuller.cpp", "src/external/StatsPuller.cpp", "src/external/StatsPullerManager.cpp", diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index ada2f2de28f4..c1a8d69191d2 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -1265,16 +1265,6 @@ Status StatsService::sendAppBreadcrumbAtom(int32_t label, int32_t state) { return Status::ok(); } -Status StatsService::registerPullerCallback(int32_t atomTag, - const sp<android::os::IStatsPullerCallback>& pullerCallback, - const String16& packageName) { - ENFORCE_DUMP_AND_USAGE_STATS(packageName); - - VLOG("StatsService::registerPullerCallback called."); - mPullerManager->RegisterPullerCallback(atomTag, pullerCallback); - return Status::ok(); -} - Status StatsService::registerPullAtomCallback(int32_t uid, int32_t atomTag, int64_t coolDownNs, int64_t timeoutNs, const std::vector<int32_t>& additiveFields, const sp<android::os::IPullAtomCallback>& pullerCallback) { @@ -1297,14 +1287,6 @@ Status StatsService::registerNativePullAtomCallback(int32_t atomTag, int64_t coo return Status::ok(); } -Status StatsService::unregisterPullerCallback(int32_t atomTag, const String16& packageName) { - ENFORCE_DUMP_AND_USAGE_STATS(packageName); - - VLOG("StatsService::unregisterPullerCallback called."); - mPullerManager->UnregisterPullerCallback(atomTag); - return Status::ok(); -} - Status StatsService::unregisterPullAtomCallback(int32_t uid, int32_t atomTag) { ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::unregisterPullAtomCallback called."); diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h index 7990e5e7d018..f2079d9f278f 100644 --- a/cmds/statsd/src/StatsService.h +++ b/cmds/statsd/src/StatsService.h @@ -171,14 +171,6 @@ public: virtual Status sendAppBreadcrumbAtom(int32_t label, int32_t state) override; /** - * Binder call to register a callback function for a vendor pulled atom. - * Note: this atom must NOT have uid as a field. - */ - virtual Status registerPullerCallback(int32_t atomTag, - const sp<android::os::IStatsPullerCallback>& pullerCallback, - const String16& packageName) override; - - /** * Binder call to register a callback function for a pulled atom. */ virtual Status registerPullAtomCallback(int32_t uid, int32_t atomTag, int64_t coolDownNs, @@ -193,11 +185,6 @@ public: const sp<android::os::IPullAtomCallback>& pullerCallback) override; /** - * Binder call to unregister any existing callback function for a vendor pulled atom. - */ - virtual Status unregisterPullerCallback(int32_t atomTag, const String16& packageName) override; - - /** * Binder call to unregister any existing callback for the given uid and atom. */ virtual Status unregisterPullAtomCallback(int32_t uid, int32_t atomTag) override; diff --git a/cmds/statsd/src/external/StatsCallbackPullerDeprecated.cpp b/cmds/statsd/src/external/StatsCallbackPullerDeprecated.cpp deleted file mode 100644 index 4f88a91f9ec6..000000000000 --- a/cmds/statsd/src/external/StatsCallbackPullerDeprecated.cpp +++ /dev/null @@ -1,63 +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. - */ - -#define DEBUG false // STOPSHIP if true -#include "Log.h" - -#include "StatsCallbackPullerDeprecated.h" - -#include <android/os/IStatsPullerCallback.h> - -#include "logd/LogEvent.h" -#include "stats_log_util.h" - -using namespace android::binder; - -namespace android { -namespace os { -namespace statsd { - -StatsCallbackPullerDeprecated::StatsCallbackPullerDeprecated( - int tagId, const sp<IStatsPullerCallback>& callback) - : StatsPuller(tagId), mCallback(callback) { - VLOG("StatsCallbackPuller created for tag %d", tagId); -} - -bool StatsCallbackPullerDeprecated::PullInternal(vector<shared_ptr<LogEvent>>* data) { - VLOG("StatsCallbackPuller called for tag %d", mTagId) - if (mCallback == nullptr) { - ALOGW("No callback registered"); - return false; - } - int64_t wallClockTimeNs = getWallClockNs(); - int64_t elapsedTimeNs = getElapsedRealtimeNs(); - vector<StatsLogEventWrapper> returned_value; - Status status = mCallback->pullData(mTagId, elapsedTimeNs, wallClockTimeNs, &returned_value); - if (!status.isOk()) { - ALOGW("StatsCallbackPuller::pull failed for %d", mTagId); - return false; - } - data->clear(); - for (const StatsLogEventWrapper& it : returned_value) { - LogEvent::createLogEvents(it, *data); - } - VLOG("StatsCallbackPuller::pull succeeded for %d", mTagId); - return true; -} - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/cmds/statsd/src/external/StatsCallbackPullerDeprecated.h b/cmds/statsd/src/external/StatsCallbackPullerDeprecated.h deleted file mode 100644 index 028902975923..000000000000 --- a/cmds/statsd/src/external/StatsCallbackPullerDeprecated.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. - */ - -#pragma once - -#include <android/os/IStatsPullerCallback.h> -#include <utils/String16.h> - -#include "StatsPuller.h" - -namespace android { -namespace os { -namespace statsd { - -class StatsCallbackPullerDeprecated : public StatsPuller { -public: - explicit StatsCallbackPullerDeprecated(int tagId, const sp<IStatsPullerCallback>& callback); - -private: - bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override; - const sp<IStatsPullerCallback> mCallback; -}; - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index d5cda85f412a..b4fde1666b17 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -21,7 +21,6 @@ #include <android/os/IPullAtomCallback.h> #include <android/os/IStatsCompanionService.h> -#include <android/os/IStatsPullerCallback.h> #include <cutils/log.h> #include <math.h> #include <stdint.h> @@ -38,7 +37,6 @@ #include "PowerStatsPuller.h" #include "ResourceHealthManagerPuller.h" #include "StatsCallbackPuller.h" -#include "StatsCallbackPullerDeprecated.h" #include "StatsCompanionServicePuller.h" #include "SubsystemSleepStatePuller.h" #include "TrainInfoPuller.h" @@ -68,13 +66,6 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { {{.atomTag = android::util::ON_DEVICE_POWER_MEASUREMENT}, {.puller = new PowerStatsPuller()}}, - // system_elapsed_realtime - {{.atomTag = android::util::SYSTEM_ELAPSED_REALTIME}, - {.coolDownNs = NS_PER_SEC, - .puller = new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME), - .pullTimeoutNs = NS_PER_SEC / 2, - }}, - // remaining_battery_capacity {{.atomTag = android::util::REMAINING_BATTERY_CAPACITY}, {.puller = new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}}, @@ -95,35 +86,6 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { {{.atomTag = android::util::BATTERY_CYCLE_COUNT}, {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}}, - // looper_stats - {{.atomTag = android::util::LOOPER_STATS}, - {.additiveFields = {5, 6, 7, 8, 9}, - .puller = new StatsCompanionServicePuller(android::util::LOOPER_STATS)}}, - - // Disk Stats - {{.atomTag = android::util::DISK_STATS}, - {.puller = new StatsCompanionServicePuller(android::util::DISK_STATS)}}, - - // Directory usage - {{.atomTag = android::util::DIRECTORY_USAGE}, - {.puller = new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}}, - - // Size of app's code, data, and cache - {{.atomTag = android::util::APP_SIZE}, - {.puller = new StatsCompanionServicePuller(android::util::APP_SIZE)}}, - - // Size of specific categories of files. Eg. Music. - {{.atomTag = android::util::CATEGORY_SIZE}, - {.puller = new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}}, - - // Number of fingerprints enrolled for each user. - {{.atomTag = android::util::NUM_FINGERPRINTS_ENROLLED}, - {.puller = new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS_ENROLLED)}}, - - // Number of faces enrolled for each user. - {{.atomTag = android::util::NUM_FACES_ENROLLED}, - {.puller = new StatsCompanionServicePuller(android::util::NUM_FACES_ENROLLED)}}, - // ProcStats. {{.atomTag = android::util::PROC_STATS}, {.puller = new StatsCompanionServicePuller(android::util::PROC_STATS)}}, @@ -132,20 +94,6 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { {{.atomTag = android::util::PROC_STATS_PKG_PROC}, {.puller = new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}}, - // Disk I/O stats per uid. - {{.atomTag = android::util::DISK_IO}, - {.additiveFields = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, - .coolDownNs = 3 * NS_PER_SEC, - .puller = new StatsCompanionServicePuller(android::util::DISK_IO)}}, - - // Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses. - {{.atomTag = android::util::PROCESS_CPU_TIME}, - {.coolDownNs = 5 * NS_PER_SEC /* min cool-down in seconds*/, - .puller = new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}}, - {{.atomTag = android::util::CPU_TIME_PER_THREAD_FREQ}, - {.additiveFields = {7, 9, 11, 13, 15, 17, 19, 21}, - .puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}}, - // DebugElapsedClock. {{.atomTag = android::util::DEBUG_ELAPSED_CLOCK}, {.additiveFields = {1, 2, 3, 4}, @@ -156,25 +104,9 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { {.additiveFields = {1, 2, 3, 4}, .puller = new StatsCompanionServicePuller(android::util::DEBUG_FAILING_ELAPSED_CLOCK)}}, - // RoleHolder. - {{.atomTag = android::util::ROLE_HOLDER}, - {.puller = new StatsCompanionServicePuller(android::util::ROLE_HOLDER)}}, - - // PermissionState. - {{.atomTag = android::util::DANGEROUS_PERMISSION_STATE}, - {.puller = new StatsCompanionServicePuller(android::util::DANGEROUS_PERMISSION_STATE)}}, - // TrainInfo. {{.atomTag = android::util::TRAIN_INFO}, {.puller = new TrainInfoPuller()}}, - // TimeZoneDataInfo. - {{.atomTag = android::util::TIME_ZONE_DATA_INFO}, - {.puller = new StatsCompanionServicePuller(android::util::TIME_ZONE_DATA_INFO)}}, - - // ExternalStorageInfo - {{.atomTag = android::util::EXTERNAL_STORAGE_INFO}, - {.puller = new StatsCompanionServicePuller(android::util::EXTERNAL_STORAGE_INFO)}}, - // GpuStatsGlobalInfo {{.atomTag = android::util::GPU_STATS_GLOBAL_INFO}, {.puller = new GpuStatsPuller(android::util::GPU_STATS_GLOBAL_INFO)}}, @@ -183,31 +115,14 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { {{.atomTag = android::util::GPU_STATS_APP_INFO}, {.puller = new GpuStatsPuller(android::util::GPU_STATS_APP_INFO)}}, - // AppsOnExternalStorageInfo - {{.atomTag = android::util::APPS_ON_EXTERNAL_STORAGE_INFO}, - {.puller = new StatsCompanionServicePuller(android::util::APPS_ON_EXTERNAL_STORAGE_INFO)}}, - // Face Settings {{.atomTag = android::util::FACE_SETTINGS}, {.puller = new StatsCompanionServicePuller(android::util::FACE_SETTINGS)}}, - // App ops - {{.atomTag = android::util::APP_OPS}, - {.puller = new StatsCompanionServicePuller(android::util::APP_OPS)}}, - // VmsClientStats {{.atomTag = android::util::VMS_CLIENT_STATS}, {.additiveFields = {5, 6, 7, 8, 9, 10}, .puller = new CarStatsPuller(android::util::VMS_CLIENT_STATS)}}, - - // NotiifcationRemoteViews. - {{.atomTag = android::util::NOTIFICATION_REMOTE_VIEWS}, - {.puller = new StatsCompanionServicePuller(android::util::NOTIFICATION_REMOTE_VIEWS)}}, - - // PermissionStateSampled. - {{.atomTag = android::util::DANGEROUS_PERMISSION_STATE_SAMPLED}, - {.puller = - new StatsCompanionServicePuller(android::util::DANGEROUS_PERMISSION_STATE_SAMPLED)}}, }; StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) { @@ -406,21 +321,6 @@ int StatsPullerManager::ClearPullerCacheIfNecessary(int64_t timestampNs) { return totalCleared; } -// Deprecated, remove after puller API is complete. -void StatsPullerManager::RegisterPullerCallback(int32_t atomTag, - const sp<IStatsPullerCallback>& callback) { - AutoMutex _l(mLock); - // Platform pullers cannot be changed. - if (!isVendorPulledAtom(atomTag)) { - VLOG("RegisterPullerCallback: atom tag %d is not vendor pulled", atomTag); - return; - } - VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag); - StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true); - kAllPullAtomInfo[{.atomTag = atomTag}] = { - .puller = new StatsCallbackPullerDeprecated(atomTag, callback)}; -} - void StatsPullerManager::RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs, const int64_t timeoutNs, const vector<int32_t>& additiveFields, @@ -437,16 +337,6 @@ void StatsPullerManager::RegisterPullAtomCallback(const int uid, const int32_t a }; } -void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) { - AutoMutex _l(mLock); - // Platform pullers cannot be changed. - if (!isVendorPulledAtom(atomTag)) { - return; - } - StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false); - kAllPullAtomInfo.erase({.atomTag = atomTag}); -} - void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag) { AutoMutex _l(mLock); StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false); diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h index 349fd47b6c9d..4b6ab57b3bbe 100644 --- a/cmds/statsd/src/external/StatsPullerManager.h +++ b/cmds/statsd/src/external/StatsPullerManager.h @@ -18,7 +18,6 @@ #include <android/os/IPullAtomCallback.h> #include <android/os/IStatsCompanionService.h> -#include <android/os/IStatsPullerCallback.h> #include <binder/IServiceManager.h> #include <utils/RefBase.h> #include <utils/threads.h> @@ -116,15 +115,10 @@ public: void SetStatsCompanionService(sp<IStatsCompanionService> statsCompanionService); - // Deprecated, remove after puller API is complete. - void RegisterPullerCallback(int32_t atomTag, const sp<IStatsPullerCallback>& callback); - void RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs, const int64_t timeoutNs, const vector<int32_t>& additiveFields, const sp<IPullAtomCallback>& callback); - void UnregisterPullerCallback(int32_t atomTag); - void UnregisterPullAtomCallback(const int uid, const int32_t atomTag); static std::map<PullerKey, PullAtomInfo> kAllPullAtomInfo; diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h index 692d91e1a82f..32827852ecad 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.h +++ b/cmds/statsd/src/guardrail/StatsdStats.h @@ -164,9 +164,6 @@ public: // Maximum number of pushed atoms statsd stats will track above kMaxPushedAtomId. static const int kMaxNonPlatformPushedAtoms = 100; - // Max platform atom tag number. - static const int32_t kMaxPlatformAtomTag = 100000; - // Vendor pulled atom start id. static const int32_t kVendorPulledAtomStartTag = 150000; diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 2010cc98ef2d..67a59f1975d5 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -22,6 +22,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import android.Manifest; import android.annotation.DrawableRes; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -65,6 +66,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.UserManager; import android.os.WorkSource; import android.util.ArrayMap; import android.util.DisplayMetrics; @@ -3479,6 +3481,50 @@ public class ActivityManager { } /** + * Return a list of {@link ApplicationExitInfo} records containing the reasons for the most + * recent app deaths. + * + * <p class="note"> Note: System stores this historical information in a ring buffer and only + * the most recent records will be returned. </p> + * + * <p class="note"> Note: In the case that this application was bound to an external service + * with flag {@link android.content.Context#BIND_EXTERNAL_SERVICE}, the process of that external + * service will be included in this package's exit info. </p> + * + * @param packageName Optional, a null value means match all packages belonging to the + * caller's UID. If this package belongs to another UID, you must hold + * {@link android.Manifest.permission#DUMP} in order to retrieve it. + * @param pid A process ID that used to belong to this package but died later; a value + * of 0 means to ignore this parameter and return all matching records. + * @param maxNum The maximum number of results to be returned; a value of 0 + * means to ignore this parameter and return all matching records + * + * @return a list of {@link ApplicationExitInfo} records matching the criteria, sorted in + * the order from most recent to least recent. + */ + @Nullable + public List<ApplicationExitInfo> getHistoricalProcessExitReasons(@Nullable String packageName, + @IntRange(from = 0) int pid, @IntRange(from = 0) int maxNum) { + try { + ParceledListSlice<ApplicationExitInfo> r = getService().getHistoricalProcessExitReasons( + packageName, pid, maxNum, mContext.getUserId()); + return r == null ? null : r.getList(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /* + * @return Whether or not the low memory kill will be reported in + * {@link #getHistoricalProcessExitReasons}. + * + * @see {@link ApplicationExitInfo#REASON_LOW_MEMORY} + */ + public static boolean isLowMemoryKillReportSupported() { + return SystemProperties.getBoolean("persist.sys.lmk.reportkills", false); + } + + /** * Return the importance of a given package name, based on the processes that are * currently running. The return value is one of the importance constants defined * in {@link RunningAppProcessInfo}, giving you the highest importance of all the @@ -4463,6 +4509,53 @@ public class ActivityManager { } /** + * Return if a given profile is in the foreground. + * @param userHandle UserHandle to check + * @return Returns the boolean result. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.CREATE_USERS + }) + public boolean isProfileForeground(@NonNull UserHandle userHandle) { + UserManager userManager = mContext.getSystemService(UserManager.class); + if (userManager != null) { + for (UserInfo userInfo : userManager.getProfiles(getCurrentUser())) { + if (userInfo.id == userHandle.getIdentifier()) { + return true; + } + } + } + return false; + } + + /** + * Kill the given PIDs, but the killing will be delayed until the device is idle + * and the given process is imperceptible. + * + * <p>You must hold the permission + * {@link android.Manifest.permission#FORCE_STOP_PACKAGES} to be able to + * call this method. + * </p> + * + * @param pids The list of the pids to be killed + * @pram reason The reason of the kill + * + * @hide + */ + @SystemApi @TestApi + @RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES) + public void killProcessesWhenImperceptible(@NonNull int[] pids, @NonNull String reason) { + try { + getService().killProcessesWhenImperceptible(pids, reason); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * The AppTask allows you to manage your own application's tasks. * See {@link android.app.ActivityManager#getAppTasks()} */ diff --git a/apex/permission/service/java/com/android/server/permission/RuntimePermissionPersistence.java b/core/java/android/app/ApplicationExitInfo.aidl index a534e22c04cb..fb7d8f605c96 100644 --- a/apex/permission/service/java/com/android/server/permission/RuntimePermissionPersistence.java +++ b/core/java/android/app/ApplicationExitInfo.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * 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. @@ -14,9 +14,6 @@ * limitations under the License. */ -package com.android.server.permission; +package android.app; -/** - * Persistence for runtime permissions. - */ -public class RuntimePermissionPersistence {} +parcelable ApplicationExitInfo; diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java new file mode 100644 index 000000000000..4bf5f07e86be --- /dev/null +++ b/core/java/android/app/ApplicationExitInfo.java @@ -0,0 +1,901 @@ +/* + * 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.app; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.app.ActivityManager.RunningAppProcessInfo.Importance; +import android.icu.text.SimpleDateFormat; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; +import android.text.TextUtils; +import android.util.DebugUtils; +import android.util.proto.ProtoInputStream; +import android.util.proto.ProtoOutputStream; +import android.util.proto.WireTypeMismatchException; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Date; +import java.util.Objects; + +/** + * Describes the information of an application process's death. + * + * <p> + * Application process could die for many reasons, for example {@link #REASON_LOW_MEMORY} + * when it was killed by the ystem because it was running low on memory. Reason + * of the death can be retrieved via {@link #getReason}. Besides the reason, there are a few other + * auxiliary APIs like {@link #getStatus} and {@link #getImportance} to help the caller with + * additional diagnostic information. + * </p> + * + */ +public final class ApplicationExitInfo implements Parcelable { + + /** + * Application process died due to unknown reason. + */ + public static final int REASON_UNKNOWN = 0; + + /** + * Application process exit normally by itself, for example, + * via {@link java.lang.System#exit}; {@link #getStatus} will specify the exit code. + * + * <p>Applications should normally not do this, as the system has a better knowledge + * in terms of process management.</p> + */ + public static final int REASON_EXIT_SELF = 1; + + /** + * Application process died due to the result of an OS signal; for example, + * {@link android.system.OsConstants#SIGKILL}; {@link #getStatus} will specify the signal + * number. + */ + public static final int REASON_SIGNALED = 2; + + /** + * Application process was killed by the system low memory killer, meaning the system was + * under memory pressure at the time of kill. + * + * <p class="note"> + * Not all devices support reporting {@link #REASON_LOW_MEMORY}; on a device with no such + * support, when a process is killed due to memory pressure, the {@link #getReason} will return + * {@link #REASON_SIGNALED} and {@link #getStatus} will return + * the value {@link android.system.OsConstants#SIGKILL}. + * + * Application should use {@link ActivityManager#isLowMemoryKillReportSupported} to check + * if the device supports reporting {@link #REASON_LOW_MEMORY} or not. + * </p> + */ + public static final int REASON_LOW_MEMORY = 3; + + /** + * Application process died because of an unhandled exception in Java code. + */ + public static final int REASON_CRASH = 4; + + /** + * Application process died because of a native code crash. + */ + public static final int REASON_CRASH_NATIVE = 5; + + /** + * Application process was killed due to being unresponsive (ANR). + */ + public static final int REASON_ANR = 6; + + /** + * Application process was killed because of initialization failure, + * for example, it took too long to attach to the system during the start, + * or there was an error during initialization. + */ + public static final int REASON_INITIALIZATION_FAILURE = 7; + + /** + * Application process was killed due to a runtime permission change. + */ + public static final int REASON_PERMISSION_CHANGE = 8; + + /** + * Application process was killed by the system due to excessive resource usage. + */ + public static final int REASON_EXCESSIVE_RESOURCE_USAGE = 9; + + /** + * Application process was killed by the system for various other reasons, + * for example, the application package got disabled by the user; + * {@link #getDescription} will specify the cause given by the system. + */ + public static final int REASON_OTHER = 10; + + /** + * Application process kills subreason is unknown. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_UNKNOWN = 0; + + /** + * Application process was killed because user quit it on the "wait for debugger" dialog; + * this would be set when the reason is {@link #REASON_OTHER}. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_WAIT_FOR_DEBUGGER = 1; + + /** + * Application process was killed by the activity manager because there were too many cached + * processes; this would be set only when the reason is {@link #REASON_OTHER}. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_TOO_MANY_CACHED = 2; + + /** + * Application process was killed by the activity manager because there were too many empty + * processes; this would be set only when the reason is {@link #REASON_OTHER}. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_TOO_MANY_EMPTY = 3; + + /** + * Application process was killed by the activity manager because there were too many cached + * processes and this process had been in empty state for a long time; + * this would be set only when the reason is {@link #REASON_OTHER}. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_TRIM_EMPTY = 4; + + /** + * Application process was killed by the activity manager because system was on memory pressure + * and this process took large amount of cached memory; + * this would be set only when the reason is {@link #REASON_OTHER}. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_LARGE_CACHED = 5; + + /** + * Application process was killed by the activity manager because the system was on low memory + * pressure for a significant amount of time since last idle; + * this would be set only when the reason is {@link #REASON_OTHER}. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_MEMORY_PRESSURE = 6; + + /** + * Application process was killed by the activity manager due to excessive CPU usage; + * this would be set only when the reason is {@link #REASON_EXCESSIVE_RESOURCE_USAGE}. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_EXCESSIVE_CPU = 7; + + /** + * @see {@link #getPid} + */ + private int mPid; + + /** + * @see {@link #getRealUid} + */ + private int mRealUid; + + /** + * @see {@link #getPackageUid} + */ + private int mPackageUid; + + /** + * @see {@link #getDefiningUid} + */ + private int mDefiningUid; + + /** + * @see {@link #getProcessName} + */ + private String mProcessName; + + /** + * @see {@link #getReason} + */ + private @Reason int mReason; + + /** + * @see {@link #getStatus} + */ + private int mStatus; + + /** + * @see {@link #getImportance} + */ + private @Importance int mImportance; + + /** + * @see {@link #getPss} + */ + private int mPss; + + /** + * @see {@link #getRss} + */ + private int mRss; + + /** + * @see {@link #getTimestamp} + */ + private long mTimestamp; + + /** + * @see {@link #getDescription} + */ + private @Nullable String mDescription; + + /** + * @see {@link #getSubReason} + */ + private @SubReason int mSubReason; + + /** + * @see {@link #getConnectionGroup} + */ + private int mConnectionGroup; + + /** + * @see {@link #getPackageName} + */ + private String mPackageName; + + /** + * @see {@link #getPackageList} + */ + private String[] mPackageList; + + /** @hide */ + @IntDef(prefix = { "REASON_" }, value = { + REASON_UNKNOWN, + REASON_EXIT_SELF, + REASON_SIGNALED, + REASON_LOW_MEMORY, + REASON_CRASH, + REASON_CRASH_NATIVE, + REASON_ANR, + REASON_INITIALIZATION_FAILURE, + REASON_PERMISSION_CHANGE, + REASON_EXCESSIVE_RESOURCE_USAGE, + REASON_OTHER, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Reason {} + + /** @hide */ + @IntDef(prefix = { "SUBREASON_" }, value = { + SUBREASON_UNKNOWN, + SUBREASON_WAIT_FOR_DEBUGGER, + SUBREASON_TOO_MANY_CACHED, + SUBREASON_TOO_MANY_EMPTY, + SUBREASON_TRIM_EMPTY, + SUBREASON_LARGE_CACHED, + SUBREASON_MEMORY_PRESSURE, + SUBREASON_EXCESSIVE_CPU, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SubReason {} + + /** + * The process id of the process that died. + */ + public int getPid() { + return mPid; + } + + /** + * The kernel user identifier of the process, most of the time the system uses this + * to do access control checks. It's typically the uid of the package where the component is + * running from, except the case of isolated process, where this field identifies the kernel + * user identifier that this process is actually running with, while the {@link #getPackageUid} + * identifies the kernel user identifier that is assigned at the package installation time. + */ + public int getRealUid() { + return mRealUid; + } + + /** + * Similar to {@link #getRealUid}, it's the kernel user identifier that is assigned at the + * package installation time. + */ + public int getPackageUid() { + return mPackageUid; + } + + /** + * Return the defining kernel user identifier, maybe different from {@link #getRealUid} and + * {@link #getPackageUid}, if an external service was bound with the flag + * {@link android.content.Context#BIND_EXTERNAL_SERVICE} - in this case, this field here + * will be the kernel user identifier of the external service provider. + */ + public int getDefiningUid() { + return mDefiningUid; + } + + /** + * The actual process name it was running with. + */ + public @NonNull String getProcessName() { + return mProcessName; + } + + /** + * The reason code of the process's death. + */ + public @Reason int getReason() { + return mReason; + } + + /* + * The exit status argument of exit() if the application calls it, or the signal + * number if the application is signaled. + */ + public int getStatus() { + return mStatus; + } + + /** + * The importance of the process that it used to have before the death. + */ + public @Importance int getImportance() { + return mImportance; + } + + /* + * Last proportional set size of the memory that the process had used in kB. + * + * <p class="note">Note: This is the value from last sampling on the process, + * it's NOT the exact memory information prior to its death; and it'll be zero + * if the process died before system had a chance to take the sample. </p> + */ + public int getPss() { + return mPss; + } + + /** + * Last resident set size of the memory that the process had used in kB. + * + * <p class="note">Note: This is the value from last sampling on the process, + * it's NOT the exact memory information prior to its death; and it'll be zero + * if the process died before system had a chance to take the sample. </p> + */ + public int getRss() { + return mRss; + } + + /** + * The timestamp of the process's death, in milliseconds since the epoch. + */ + public long getTimestamp() { + return mTimestamp; + } + + /** + * The human readable description of the process's death, given by the system; could be null. + */ + public @Nullable String getDescription() { + return mDescription; + } + + /** + * Return the user id of the record on a multi-user system. + * + * @hide + */ + @SystemApi + public @NonNull UserHandle getUserHandle() { + return UserHandle.of(UserHandle.getUserId(mRealUid)); + } + + /** + * A subtype reason in conjunction with {@link #mReason}. + * + * For internal use only. + * + * @hide + */ + public @SubReason int getSubReason() { + return mSubReason; + } + + /** + * The connection group this process belongs to, if there is any. + * @see {@link android.content.Context#updateServiceGroup}. + * + * For internal use only. + * + * @hide + */ + public int getConnectionGroup() { + return mConnectionGroup; + } + + /** + * Name of first package running in this process; + * + * For system internal use only, will not retain across processes. + * + * @hide + */ + public String getPackageName() { + return mPackageName; + } + + /** + * List of packages running in this process; + * + * For system internal use only, will not retain across processes. + * + * @hide + */ + public String[] getPackageList() { + return mPackageList; + } + + /** + * @see {@link #getPid} + * + * @hide + */ + public void setPid(final int pid) { + mPid = pid; + } + + /** + * @see {@link #getRealUid} + * + * @hide + */ + public void setRealUid(final int uid) { + mRealUid = uid; + } + + /** + * @see {@link #getPackageUid} + * + * @hide + */ + public void setPackageUid(final int uid) { + mPackageUid = uid; + } + + /** + * @see {@link #getDefiningUid} + * + * @hide + */ + public void setDefiningUid(final int uid) { + mDefiningUid = uid; + } + + /** + * @see {@link #getProcessName} + * + * @hide + */ + public void setProcessName(final String processName) { + mProcessName = processName; + } + + /** + * @see {@link #getReason} + * + * @hide + */ + public void setReason(final @Reason int reason) { + mReason = reason; + } + + /** + * @see {@link #getStatus} + * + * @hide + */ + public void setStatus(final int status) { + mStatus = status; + } + + /** + * @see {@link #getImportance} + * + * @hide + */ + public void setImportance(final @Importance int importance) { + mImportance = importance; + } + + /** + * @see {@link #getPss} + * + * @hide + */ + public void setPss(final int pss) { + mPss = pss; + } + + /** + * @see {@link #getRss} + * + * @hide + */ + public void setRss(final int rss) { + mRss = rss; + } + + /** + * @see {@link #getTimestamp} + * + * @hide + */ + public void setTimestamp(final long timestamp) { + mTimestamp = timestamp; + } + + /** + * @see {@link #getDescription} + * + * @hide + */ + public void setDescription(final String description) { + mDescription = description; + } + + /** + * @see {@link #getSubReason} + * + * @hide + */ + public void setSubReason(final @SubReason int subReason) { + mSubReason = subReason; + } + + /** + * @see {@link #getConnectionGroup} + * + * @hide + */ + public void setConnectionGroup(final int connectionGroup) { + mConnectionGroup = connectionGroup; + } + + /** + * @see {@link #getPackageName} + * + * @hide + */ + public void setPackageName(final String packageName) { + mPackageName = packageName; + } + + /** + * @see {@link #getPackageList} + * + * @hide + */ + public void setPackageList(final String[] packageList) { + mPackageList = packageList; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mPid); + dest.writeInt(mRealUid); + dest.writeInt(mPackageUid); + dest.writeInt(mDefiningUid); + dest.writeString(mProcessName); + dest.writeInt(mConnectionGroup); + dest.writeInt(mReason); + dest.writeInt(mSubReason); + dest.writeInt(mStatus); + dest.writeInt(mImportance); + dest.writeInt(mPss); + dest.writeInt(mRss); + dest.writeLong(mTimestamp); + dest.writeString(mDescription); + } + + /** @hide */ + public ApplicationExitInfo() { + } + + /** @hide */ + public ApplicationExitInfo(ApplicationExitInfo other) { + mPid = other.mPid; + mRealUid = other.mRealUid; + mPackageUid = other.mPackageUid; + mDefiningUid = other.mDefiningUid; + mProcessName = other.mProcessName; + mConnectionGroup = other.mConnectionGroup; + mReason = other.mReason; + mStatus = other.mStatus; + mSubReason = other.mSubReason; + mImportance = other.mImportance; + mPss = other.mPss; + mRss = other.mRss; + mTimestamp = other.mTimestamp; + mDescription = other.mDescription; + } + + private ApplicationExitInfo(@NonNull Parcel in) { + mPid = in.readInt(); + mRealUid = in.readInt(); + mPackageUid = in.readInt(); + mDefiningUid = in.readInt(); + mProcessName = in.readString(); + mConnectionGroup = in.readInt(); + mReason = in.readInt(); + mSubReason = in.readInt(); + mStatus = in.readInt(); + mImportance = in.readInt(); + mPss = in.readInt(); + mRss = in.readInt(); + mTimestamp = in.readLong(); + mDescription = in.readString(); + } + + public @NonNull static final Creator<ApplicationExitInfo> CREATOR = + new Creator<ApplicationExitInfo>() { + @Override + public ApplicationExitInfo createFromParcel(Parcel in) { + return new ApplicationExitInfo(in); + } + + @Override + public ApplicationExitInfo[] newArray(int size) { + return new ApplicationExitInfo[size]; + } + }; + + /** @hide */ + public void dump(@NonNull PrintWriter pw, @Nullable String prefix, @Nullable String seqSuffix, + @NonNull SimpleDateFormat sdf) { + pw.println(prefix + "ApplicationExitInfo " + seqSuffix + ":"); + pw.println(prefix + " timestamp=" + sdf.format(new Date(mTimestamp))); + pw.println(prefix + " pid=" + mPid); + pw.println(prefix + " realUid=" + mRealUid); + pw.println(prefix + " packageUid=" + mPackageUid); + pw.println(prefix + " definingUid=" + mDefiningUid); + pw.println(prefix + " user=" + UserHandle.getUserId(mPackageUid)); + pw.println(prefix + " process=" + mProcessName); + pw.println(prefix + " reason=" + mReason + " (" + reasonCodeToString(mReason) + ")"); + pw.println(prefix + " status=" + mStatus); + pw.println(prefix + " importance=" + mImportance); + pw.print(prefix + " pss="); DebugUtils.printSizeValue(pw, mPss << 10); pw.println(); + pw.print(prefix + " rss="); DebugUtils.printSizeValue(pw, mRss << 10); pw.println(); + pw.println(prefix + " description=" + mDescription); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("ApplicationExitInfo(timestamp="); + sb.append(new SimpleDateFormat().format(new Date(mTimestamp))); + sb.append(" pid=").append(mPid); + sb.append(" realUid=").append(mRealUid); + sb.append(" packageUid=").append(mPackageUid); + sb.append(" definingUid=").append(mDefiningUid); + sb.append(" user=").append(UserHandle.getUserId(mPackageUid)); + sb.append(" process=").append(mProcessName); + sb.append(" reason=").append(mReason).append(" (") + .append(reasonCodeToString(mReason)).append(")"); + sb.append(" status=").append(mStatus); + sb.append(" importance=").append(mImportance); + sb.append(" pss="); DebugUtils.sizeValueToString(mPss << 10, sb); + sb.append(" rss="); DebugUtils.sizeValueToString(mRss << 10, sb); + sb.append(" description=").append(mDescription); + return sb.toString(); + } + + private static String reasonCodeToString(@Reason int reason) { + switch (reason) { + case REASON_EXIT_SELF: + return "EXIT_SELF"; + case REASON_SIGNALED: + return "SIGNALED"; + case REASON_LOW_MEMORY: + return "LOW_MEMORY"; + case REASON_CRASH: + return "APP CRASH(EXCEPTION)"; + case REASON_CRASH_NATIVE: + return "APP CRASH(NATIVE)"; + case REASON_ANR: + return "ANR"; + case REASON_INITIALIZATION_FAILURE: + return "INITIALIZATION FAILURE"; + case REASON_PERMISSION_CHANGE: + return "PERMISSION CHANGE"; + case REASON_EXCESSIVE_RESOURCE_USAGE: + return "EXCESSIVE RESOURCE USAGE"; + case REASON_OTHER: + return "OTHER KILLS BY SYSTEM"; + default: + return "UNKNOWN"; + } + } + + /** @hide */ + public static String subreasonToString(@SubReason int subreason) { + switch (subreason) { + case SUBREASON_WAIT_FOR_DEBUGGER: + return "WAIT FOR DEBUGGER"; + case SUBREASON_TOO_MANY_CACHED: + return "TOO MANY CACHED PROCS"; + case SUBREASON_TOO_MANY_EMPTY: + return "TOO MANY EMPTY PROCS"; + case SUBREASON_TRIM_EMPTY: + return "TRIM EMPTY"; + case SUBREASON_LARGE_CACHED: + return "LARGE CACHED"; + case SUBREASON_MEMORY_PRESSURE: + return "MEMORY PRESSURE"; + case SUBREASON_EXCESSIVE_CPU: + return "EXCESSIVE CPU USAGE"; + default: + return "UNKNOWN"; + } + } + + /** + * Write to a protocol buffer output stream. + * Protocol buffer message definition at {@link android.app.ApplicationExitInfoProto} + * + * @param proto Stream to write the ApplicationExitInfo object to. + * @param fieldId Field Id of the ApplicationExitInfo as defined in the parent message + * @hide + */ + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(ApplicationExitInfoProto.PID, mPid); + proto.write(ApplicationExitInfoProto.REAL_UID, mRealUid); + proto.write(ApplicationExitInfoProto.PACKAGE_UID, mPackageUid); + proto.write(ApplicationExitInfoProto.DEFINING_UID, mDefiningUid); + proto.write(ApplicationExitInfoProto.PROCESS_NAME, mProcessName); + proto.write(ApplicationExitInfoProto.CONNECTION_GROUP, mConnectionGroup); + proto.write(ApplicationExitInfoProto.REASON, mReason); + proto.write(ApplicationExitInfoProto.SUB_REASON, mSubReason); + proto.write(ApplicationExitInfoProto.STATUS, mStatus); + proto.write(ApplicationExitInfoProto.IMPORTANCE, mImportance); + proto.write(ApplicationExitInfoProto.PSS, mPss); + proto.write(ApplicationExitInfoProto.RSS, mRss); + proto.write(ApplicationExitInfoProto.TIMESTAMP, mTimestamp); + proto.write(ApplicationExitInfoProto.DESCRIPTION, mDescription); + proto.end(token); + } + + /** + * Read from a protocol buffer input stream. + * Protocol buffer message definition at {@link android.app.ApplicationExitInfoProto} + * + * @param proto Stream to read the ApplicationExitInfo object from. + * @param fieldId Field Id of the ApplicationExitInfo as defined in the parent message + * @hide + */ + public void readFromProto(ProtoInputStream proto, long fieldId) + throws IOException, WireTypeMismatchException { + final long token = proto.start(fieldId); + while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + switch (proto.getFieldNumber()) { + case (int) ApplicationExitInfoProto.PID: + mPid = proto.readInt(ApplicationExitInfoProto.PID); + break; + case (int) ApplicationExitInfoProto.REAL_UID: + mRealUid = proto.readInt(ApplicationExitInfoProto.REAL_UID); + break; + case (int) ApplicationExitInfoProto.PACKAGE_UID: + mPackageUid = proto.readInt(ApplicationExitInfoProto.PACKAGE_UID); + break; + case (int) ApplicationExitInfoProto.DEFINING_UID: + mDefiningUid = proto.readInt(ApplicationExitInfoProto.DEFINING_UID); + break; + case (int) ApplicationExitInfoProto.PROCESS_NAME: + mProcessName = proto.readString(ApplicationExitInfoProto.PROCESS_NAME); + break; + case (int) ApplicationExitInfoProto.CONNECTION_GROUP: + mConnectionGroup = proto.readInt(ApplicationExitInfoProto.CONNECTION_GROUP); + break; + case (int) ApplicationExitInfoProto.REASON: + mReason = proto.readInt(ApplicationExitInfoProto.REASON); + break; + case (int) ApplicationExitInfoProto.SUB_REASON: + mSubReason = proto.readInt(ApplicationExitInfoProto.SUB_REASON); + break; + case (int) ApplicationExitInfoProto.STATUS: + mStatus = proto.readInt(ApplicationExitInfoProto.STATUS); + break; + case (int) ApplicationExitInfoProto.IMPORTANCE: + mImportance = proto.readInt(ApplicationExitInfoProto.IMPORTANCE); + break; + case (int) ApplicationExitInfoProto.PSS: + mPss = proto.readInt(ApplicationExitInfoProto.PSS); + break; + case (int) ApplicationExitInfoProto.RSS: + mRss = proto.readInt(ApplicationExitInfoProto.RSS); + break; + case (int) ApplicationExitInfoProto.TIMESTAMP: + mTimestamp = proto.readLong(ApplicationExitInfoProto.TIMESTAMP); + break; + case (int) ApplicationExitInfoProto.DESCRIPTION: + mDescription = proto.readString(ApplicationExitInfoProto.DESCRIPTION); + break; + } + } + proto.end(token); + } + + @Override + public boolean equals(Object other) { + if (other == null || !(other instanceof ApplicationExitInfo)) { + return false; + } + ApplicationExitInfo o = (ApplicationExitInfo) other; + return mPid == o.mPid && mRealUid == o.mRealUid && mPackageUid == o.mPackageUid + && mDefiningUid == o.mDefiningUid + && mConnectionGroup == o.mConnectionGroup && mReason == o.mReason + && mSubReason == o.mSubReason && mImportance == o.mImportance + && mStatus == o.mStatus && mTimestamp == o.mTimestamp + && mPss == o.mPss && mRss == o.mRss + && TextUtils.equals(mProcessName, o.mProcessName) + && TextUtils.equals(mDescription, o.mDescription); + } + + @Override + public int hashCode() { + int result = mPid; + result = 31 * result + mRealUid; + result = 31 * result + mPackageUid; + result = 31 * result + mDefiningUid; + result = 31 * result + mConnectionGroup; + result = 31 * result + mReason; + result = 31 * result + mSubReason; + result = 31 * result + mImportance; + result = 31 * result + mStatus; + result = 31 * result + mPss; + result = 31 * result + mRss; + result = 31 * result + Long.hashCode(mTimestamp); + result = 31 * result + Objects.hashCode(mProcessName); + result = 31 * result + Objects.hashCode(mDescription); + return result; + } +} diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 580382e0a4aa..7d04ca0afe7e 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -18,6 +18,7 @@ package android.app; import android.app.ActivityManager; import android.app.ApplicationErrorReport; +import android.app.ApplicationExitInfo; import android.app.ContentProviderHolder; import android.app.GrantedUriPermission; import android.app.IApplicationThread; @@ -604,4 +605,36 @@ interface IActivityManager { * Method for the app to tell system that it's wedged and would like to trigger an ANR. */ void appNotResponding(String reason); + + /** + * Return a list of {@link ApplicationExitInfo} records. + * + * <p class="note"> Note: System stores these historical information in a ring buffer, older + * records would be overwritten by newer records. </p> + * + * <p class="note"> Note: In the case that this application bound to an external service with + * flag {@link android.content.Context#BIND_EXTERNAL_SERVICE}, the process of that external + * service will be included in this package's exit info. </p> + * + * @param packageName Optional, an empty value means match all packages belonging to the + * caller's UID. If this package belongs to another UID, you must hold + * {@link android.Manifest.permission#DUMP} in order to retrieve it. + * @param pid Optional, it could be a process ID that used to belong to this package but + * died later; A value of 0 means to ignore this parameter and return all + * matching records. + * @param maxNum Optional, the maximum number of results should be returned; A value of 0 + * means to ignore this parameter and return all matching records + * @param userId The userId in the multi-user environment. + * + * @return a list of {@link ApplicationExitInfo} records with the matching criteria, sorted in + * the order from most recent to least recent. + */ + ParceledListSlice<ApplicationExitInfo> getHistoricalProcessExitReasons(String packageName, + int pid, int maxNum, int userId); + + /* + * Kill the given PIDs, but the killing will be delayed until the device is idle + * and the given process is imperceptible. + */ + void killProcessesWhenImperceptible(in int[] pids, String reason); } diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java index abb0cfc73f35..3df164822f32 100644 --- a/core/java/android/app/SharedPreferencesImpl.java +++ b/core/java/android/app/SharedPreferencesImpl.java @@ -66,8 +66,9 @@ final class SharedPreferencesImpl implements SharedPreferences { /** * There will now be a callback to {@link - * OnSharedPreferenceChangeListener#onSharedPreferenceChanged(SharedPreferences, String)} with - * a {@code null} key on {@link Editor#clear()}. + * android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged + * OnSharedPreferenceChangeListener.onSharedPreferenceChanged} with a {@code null} key on + * {@link android.content.SharedPreferences.Editor#clear Editor.clear}. */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java index 0beceb0a1f08..0ea05d8f683c 100644 --- a/core/java/android/app/StatsManager.java +++ b/core/java/android/app/StatsManager.java @@ -25,11 +25,9 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.Context; import android.os.Binder; -import android.os.IBinder; import android.os.IPullAtomCallback; import android.os.IPullAtomResultReceiver; import android.os.IStatsManagerService; -import android.os.IStatsPullerCallback; import android.os.IStatsd; import android.os.RemoteException; import android.os.ServiceManager; @@ -476,42 +474,6 @@ public final class StatsManager { } /** - * Registers a callback for an atom when that atom is to be pulled. The stats service will - * invoke pullData in the callback when the stats service determines that this atom needs to be - * pulled. Currently, this only works for atoms with tags above 100,000 that do not have a uid. - * - * @param atomTag The tag of the atom for this puller callback. Must be at least 100000. - * @param callback The callback to be invoked when the stats service pulls the atom. - * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service - * - * @hide - * @deprecated Please use registerPullAtomCallback - */ - @Deprecated - @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS }) - public void setPullerCallback(int atomTag, IStatsPullerCallback callback) - throws StatsUnavailableException { - synchronized (sLock) { - try { - IStatsd service = getIStatsdLocked(); - if (callback == null) { - service.unregisterPullerCallback(atomTag, mContext.getOpPackageName()); - } else { - service.registerPullerCallback(atomTag, callback, - mContext.getOpPackageName()); - } - - } catch (RemoteException e) { - Slog.e(TAG, "Failed to connect to statsd when registering data listener."); - throw new StatsUnavailableException("could not connect", e); - } catch (SecurityException e) { - throw new StatsUnavailableException(e.getMessage(), e); - } - } - } - - - /** * Temp registration for while the migration is in progress. * * @hide @@ -734,32 +696,6 @@ public final class StatsManager { int onPullAtom(int atomTag, @NonNull List<StatsEvent> data); } - private class StatsdDeathRecipient implements IBinder.DeathRecipient { - @Override - public void binderDied() { - synchronized (sLock) { - mService = null; - } - } - } - - @GuardedBy("sLock") - private IStatsd getIStatsdLocked() throws StatsUnavailableException { - if (mService != null) { - return mService; - } - mService = IStatsd.Stub.asInterface(ServiceManager.getService("stats")); - if (mService == null) { - throw new StatsUnavailableException("could not be found"); - } - try { - mService.asBinder().linkToDeath(new StatsdDeathRecipient(), 0); - } catch (RemoteException e) { - throw new StatsUnavailableException("could not connect when linkToDeath", e); - } - return mService; - } - @GuardedBy("sLock") private IStatsManagerService getIStatsManagerServiceLocked() { if (mStatsManagerService != null) { diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 9ad3d38a3084..a88500920e97 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1564,6 +1564,8 @@ public class WallpaperManager { * @return The desired minimum width for the wallpaper. This value should * be honored by applications that set the wallpaper but it is not * mandatory. + * + * @see #getDesiredMinimumHeight() */ public int getDesiredMinimumWidth() { if (sGlobals.mService == null) { @@ -1590,6 +1592,8 @@ public class WallpaperManager { * @return The desired minimum height for the wallpaper. This value should * be honored by applications that set the wallpaper but it is not * mandatory. + * + * @see #getDesiredMinimumWidth() */ public int getDesiredMinimumHeight() { if (sGlobals.mService == null) { @@ -1609,12 +1613,11 @@ public class WallpaperManager { * a virtual wallpaper that is larger than the physical screen, matching * the size of their workspace. * - * <p>Note developers, who don't seem to be reading this. This is - * for <em>home apps</em> to tell what size wallpaper they would like. - * Nobody else should be calling this! Certainly not other non-home - * apps that change the wallpaper. Those apps are supposed to - * <b>retrieve</b> the suggested size so they can construct a wallpaper - * that matches it. + * <p class="note">Calling this method from apps other than the active + * home app is not guaranteed to work properly. Other apps that supply + * wallpaper imagery should use {@link #getDesiredMinimumWidth()} and + * {@link #getDesiredMinimumHeight()} and construct a wallpaper that + * matches those dimensions. * * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#SET_WALLPAPER_HINTS}. diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index ee758024fb9f..c8c31028b9d2 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -4021,6 +4021,7 @@ public class Intent implements Parcelable, Cloneable { * <p> * @see #EXTRA_SIM_STATE * @see #EXTRA_SIM_LOCKED_REASON + * @see #EXTRA_REBROADCAST_ON_UNLOCK * * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or * {@link #ACTION_SIM_APPLICATION_STATE_CHANGED} @@ -4197,6 +4198,18 @@ public class Intent implements Parcelable, Cloneable { public static final String SIM_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED"; /** + * The extra used with {@link #ACTION_SIM_STATE_CHANGED} for indicating whether this broadcast + * is a rebroadcast on unlock. Defaults to {@code false} if not specified. + * + * @hide + * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or + * {@link #ACTION_SIM_APPLICATION_STATE_CHANGED} + */ + @Deprecated + @SystemApi + public static final String EXTRA_REBROADCAST_ON_UNLOCK = "rebroadcastOnUnlock"; + + /** * Broadcast Action: indicate that the phone service state has changed. * The intent will have the following extra values:</p> * <p> diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl index e9546353d5f3..e86bb250c033 100644 --- a/core/java/android/content/pm/IPackageInstallerSession.aidl +++ b/core/java/android/content/pm/IPackageInstallerSession.aidl @@ -36,7 +36,7 @@ interface IPackageInstallerSession { void close(); void commit(in IntentSender statusReceiver, boolean forTransferred); - void transfer(in String packageName, in IntentSender statusReceiver); + void transfer(in String packageName); void abandon(); void addFile(String name, long lengthBytes, in byte[] metadata); diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 7a280221eb08..3c6f602e93e1 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -29,8 +29,6 @@ import android.annotation.TestApi; import android.app.ActivityManager; import android.app.AppGlobals; import android.compat.annotation.UnsupportedAppUsage; -import android.content.IIntentReceiver; -import android.content.IIntentSender; import android.content.Intent; import android.content.IntentSender; import android.content.pm.PackageManager.DeleteFlags; @@ -38,11 +36,9 @@ import android.content.pm.PackageManager.InstallReason; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; -import android.os.Bundle; import android.os.FileBridge; import android.os.Handler; import android.os.HandlerExecutor; -import android.os.IBinder; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; @@ -71,8 +67,6 @@ import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.stream.Collectors; @@ -182,9 +176,8 @@ public class PackageInstaller { * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS}, * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED}, * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT}, - * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, - * {@link #STATUS_FAILURE_STORAGE}, {@link #STATUS_FAILURE_NAME_NOT_FOUND}, - * {@link #STATUS_FAILURE_ILLEGAL_STATE} or {@link #STATUS_FAILURE_SECURITY}. + * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or + * {@link #STATUS_FAILURE_STORAGE}. * <p> * More information about a status may be available through additional * extras; see the individual status documentation for details. @@ -332,34 +325,6 @@ public class PackageInstaller { */ public static final int STATUS_FAILURE_INCOMPATIBLE = 7; - /** - * The transfer failed because a target package can't be found. For example - * transferring a session to a non-existing package. - * <p> - * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the - * missing package. - * - * @see #EXTRA_STATUS_MESSAGE - * @see #EXTRA_OTHER_PACKAGE_NAME - */ - public static final int STATUS_FAILURE_NAME_NOT_FOUND = 8; - - /** - * The transfer failed because a session is in invalid state. For example - * transferring an already committed session. - * - * @see #EXTRA_STATUS_MESSAGE - */ - public static final int STATUS_FAILURE_ILLEGAL_STATE = 9; - - /** - * The transfer failed for security reasons. For example transferring - * to a package which does not have INSTALL_PACKAGES permission. - * - * @see #EXTRA_STATUS_MESSAGE - */ - public static final int STATUS_FAILURE_SECURITY = 10; - private final IPackageInstaller mInstaller; private final int mUserId; private final String mInstallerPackageName; @@ -1143,8 +1108,7 @@ public class PackageInstaller { } /** - * Attempt to commit a session that has been {@link #transfer(String, IntentSender) - * transferred}. + * Attempt to commit a session that has been {@link #transfer(String) transferred}. * * <p>If the device reboots before the session has been finalized, you may commit the * session again. @@ -1185,14 +1149,6 @@ public class PackageInstaller { * * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES * permission. - * @param statusReceiver Called when the state of the session changes. Intents sent to - * this receiver contain {@link #EXTRA_STATUS}. Possible statuses: - * {@link #STATUS_FAILURE_NAME_NOT_FOUND}, - * {@link #STATUS_FAILURE_ILLEGAL_STATE}, - * {@link #STATUS_FAILURE_SECURITY}, - * {@link #STATUS_FAILURE}. - * Refer to the individual transfer status codes on how to handle - * them. * * @throws PackageManager.NameNotFoundException if the new owner could not be found. * @throws SecurityException if called after the session has been committed or abandoned. @@ -1200,13 +1156,12 @@ public class PackageInstaller { * @throws SecurityException if streams opened through * {@link #openWrite(String, long, long) are still open. */ - public void transfer(@NonNull String packageName, @NonNull IntentSender statusReceiver) + public void transfer(@NonNull String packageName) throws PackageManager.NameNotFoundException { - Objects.requireNonNull(statusReceiver); Objects.requireNonNull(packageName); try { - mSession.transfer(packageName, statusReceiver); + mSession.transfer(packageName); } catch (ParcelableException e) { e.maybeRethrow(PackageManager.NameNotFoundException.class); throw new RuntimeException(e); @@ -1216,64 +1171,6 @@ public class PackageInstaller { } /** - * Transfer the session to a new owner. - * This is a convenience blocking wrapper around {@link #transfer(String, IntentSender)}. - * Converts all statuses into exceptions. - * - * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES - * permission. - * - * @throws PackageManager.NameNotFoundException if the new owner could not be found. - * @throws SecurityException if called after the session has been committed or abandoned. - * @throws SecurityException if the session does not update the original installer - * @throws SecurityException if streams opened through - * {@link #openWrite(String, long, long) are still open. - */ - public void transfer(@NonNull String packageName) - throws PackageManager.NameNotFoundException { - Objects.requireNonNull(packageName); - - CompletableFuture<Intent> intentFuture = new CompletableFuture<Intent>(); - try { - IIntentSender localSender = new IIntentSender.Stub() { - @Override - public void send(int code, Intent intent, String resolvedType, - IBinder whitelistToken, - IIntentReceiver finishedReceiver, String requiredPermission, - Bundle options) { - intentFuture.complete(intent); - } - }; - transfer(packageName, new IntentSender(localSender)); - } catch (ParcelableException e) { - e.maybeRethrow(PackageManager.NameNotFoundException.class); - throw new RuntimeException(e); - } - - try { - Intent intent = intentFuture.get(); - final int status = intent.getIntExtra(EXTRA_STATUS, Integer.MIN_VALUE); - final String statusMessage = intent.getStringExtra(EXTRA_STATUS_MESSAGE); - switch (status) { - case STATUS_SUCCESS: - break; - case STATUS_FAILURE_NAME_NOT_FOUND: - throw new PackageManager.NameNotFoundException(statusMessage); - case STATUS_FAILURE_ILLEGAL_STATE: - throw new IllegalStateException(statusMessage); - case STATUS_FAILURE_SECURITY: - throw new SecurityException(statusMessage); - default: - throw new RuntimeException(statusMessage); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** * Release this session object. You can open the session again if it * hasn't been finalized. */ diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java index f7222750b89b..796cfdce2c0d 100644 --- a/core/java/android/database/sqlite/SQLiteConnection.java +++ b/core/java/android/database/sqlite/SQLiteConnection.java @@ -39,6 +39,8 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Map; +import java.util.function.BinaryOperator; +import java.util.function.UnaryOperator; /** * Represents a SQLite database connection. @@ -123,8 +125,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen boolean enableTrace, boolean enableProfile, int lookasideSlotSize, int lookasideSlotCount); private static native void nativeClose(long connectionPtr); - private static native void nativeRegisterCustomFunction(long connectionPtr, - SQLiteCustomFunction function); + private static native void nativeRegisterCustomScalarFunction(long connectionPtr, + String name, UnaryOperator<String> function); + private static native void nativeRegisterCustomAggregateFunction(long connectionPtr, + String name, BinaryOperator<String> function); private static native void nativeRegisterLocalizedCollators(long connectionPtr, String locale); private static native long nativePrepareStatement(long connectionPtr, String sql); private static native void nativeFinalizeStatement(long connectionPtr, long statementPtr); @@ -225,13 +229,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen setJournalSizeLimit(); setAutoCheckpointInterval(); setLocaleFromConfiguration(); - - // Register custom functions. - final int functionCount = mConfiguration.customFunctions.size(); - for (int i = 0; i < functionCount; i++) { - SQLiteCustomFunction function = mConfiguration.customFunctions.get(i); - nativeRegisterCustomFunction(mConnectionPtr, function); - } + setCustomFunctionsFromConfiguration(); } private void dispose(boolean finalized) { @@ -457,6 +455,19 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen } } + private void setCustomFunctionsFromConfiguration() { + for (int i = 0; i < mConfiguration.customScalarFunctions.size(); i++) { + nativeRegisterCustomScalarFunction(mConnectionPtr, + mConfiguration.customScalarFunctions.keyAt(i), + mConfiguration.customScalarFunctions.valueAt(i)); + } + for (int i = 0; i < mConfiguration.customAggregateFunctions.size(); i++) { + nativeRegisterCustomAggregateFunction(mConnectionPtr, + mConfiguration.customAggregateFunctions.keyAt(i), + mConfiguration.customAggregateFunctions.valueAt(i)); + } + } + private void checkDatabaseWiped() { if (!SQLiteGlobal.checkDbWipe()) { return; @@ -491,15 +502,6 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen void reconfigure(SQLiteDatabaseConfiguration configuration) { mOnlyAllowReadOnlyOperations = false; - // Register custom functions. - final int functionCount = configuration.customFunctions.size(); - for (int i = 0; i < functionCount; i++) { - SQLiteCustomFunction function = configuration.customFunctions.get(i); - if (!mConfiguration.customFunctions.contains(function)) { - nativeRegisterCustomFunction(mConnectionPtr, function); - } - } - // Remember what changed. boolean foreignKeyModeChanged = configuration.foreignKeyConstraintsEnabled != mConfiguration.foreignKeyConstraintsEnabled; @@ -507,6 +509,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen & (SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING | SQLiteDatabase.ENABLE_LEGACY_COMPATIBILITY_WAL)) != 0; boolean localeChanged = !configuration.locale.equals(mConfiguration.locale); + boolean customScalarFunctionsChanged = !configuration.customScalarFunctions + .equals(mConfiguration.customScalarFunctions); + boolean customAggregateFunctionsChanged = !configuration.customAggregateFunctions + .equals(mConfiguration.customAggregateFunctions); // Update configuration parameters. mConfiguration.updateParametersFrom(configuration); @@ -514,20 +520,18 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen // Update prepared statement cache size. mPreparedStatementCache.resize(configuration.maxSqlCacheSize); - // Update foreign key mode. if (foreignKeyModeChanged) { setForeignKeyModeFromConfiguration(); } - - // Update WAL. if (walModeChanged) { setWalModeFromConfiguration(); } - - // Update locale. if (localeChanged) { setLocaleFromConfiguration(); } + if (customScalarFunctionsChanged || customAggregateFunctionsChanged) { + setCustomFunctionsFromConfiguration(); + } } // Called by SQLiteConnectionPool only. diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 44c78aa783a7..458914efcbbd 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -62,6 +62,8 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.WeakHashMap; +import java.util.function.BinaryOperator; +import java.util.function.UnaryOperator; /** * Exposes methods to manage a SQLite database. @@ -958,26 +960,87 @@ public final class SQLiteDatabase extends SQLiteClosable { } /** - * Registers a CustomFunction callback as a function that can be called from - * SQLite database triggers. - * - * @param name the name of the sqlite3 function - * @param numArgs the number of arguments for the function - * @param function callback to call when the function is executed - * @hide - */ - public void addCustomFunction(String name, int numArgs, CustomFunction function) { - // Create wrapper (also validates arguments). - SQLiteCustomFunction wrapper = new SQLiteCustomFunction(name, numArgs, function); + * Register a custom scalar function that can be called from SQL + * expressions. + * <p> + * For example, registering a custom scalar function named {@code REVERSE} + * could be used in a query like + * {@code SELECT REVERSE(name) FROM employees}. + * <p> + * When attempting to register multiple functions with the same function + * name, SQLite will replace any previously defined functions with the + * latest definition, regardless of what function type they are. SQLite does + * not support unregistering functions. + * + * @param functionName Case-insensitive name to register this function + * under, limited to 255 UTF-8 bytes in length. + * @param scalarFunction Functional interface that will be invoked when the + * function name is used by a SQL statement. The argument values + * from the SQL statement are passed to the functional interface, + * and the return values from the functional interface are + * returned back into the SQL statement. + * @throws SQLiteException if the custom function could not be registered. + * @see #setCustomAggregateFunction(String, BinaryOperator) + */ + public void setCustomScalarFunction(@NonNull String functionName, + @NonNull UnaryOperator<String> scalarFunction) throws SQLiteException { + Objects.requireNonNull(functionName); + Objects.requireNonNull(scalarFunction); + + synchronized (mLock) { + throwIfNotOpenLocked(); + + mConfigurationLocked.customScalarFunctions.put(functionName, scalarFunction); + try { + mConnectionPoolLocked.reconfigure(mConfigurationLocked); + } catch (RuntimeException ex) { + mConfigurationLocked.customScalarFunctions.remove(functionName); + throw ex; + } + } + } + + /** + * Register a custom aggregate function that can be called from SQL + * expressions. + * <p> + * For example, registering a custom aggregation function named + * {@code LONGEST} could be used in a query like + * {@code SELECT LONGEST(name) FROM employees}. + * <p> + * The implementation of this method follows the reduction flow outlined in + * {@link java.util.stream.Stream#reduce(BinaryOperator)}, and the custom + * aggregation function is expected to be an associative accumulation + * function, as defined by that class. + * <p> + * When attempting to register multiple functions with the same function + * name, SQLite will replace any previously defined functions with the + * latest definition, regardless of what function type they are. SQLite does + * not support unregistering functions. + * + * @param functionName Case-insensitive name to register this function + * under, limited to 255 UTF-8 bytes in length. + * @param aggregateFunction Functional interface that will be invoked when + * the function name is used by a SQL statement. The argument + * values from the SQL statement are passed to the functional + * interface, and the return values from the functional interface + * are returned back into the SQL statement. + * @throws SQLiteException if the custom function could not be registered. + * @see #setCustomScalarFunction(String, UnaryOperator) + */ + public void setCustomAggregateFunction(@NonNull String functionName, + @NonNull BinaryOperator<String> aggregateFunction) throws SQLiteException { + Objects.requireNonNull(functionName); + Objects.requireNonNull(aggregateFunction); synchronized (mLock) { throwIfNotOpenLocked(); - mConfigurationLocked.customFunctions.add(wrapper); + mConfigurationLocked.customAggregateFunctions.put(functionName, aggregateFunction); try { mConnectionPoolLocked.reconfigure(mConfigurationLocked); } catch (RuntimeException ex) { - mConfigurationLocked.customFunctions.remove(wrapper); + mConfigurationLocked.customAggregateFunctions.remove(functionName); throw ex; } } diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java index 6a52b72a9e1c..b11942abe0c7 100644 --- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java +++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java @@ -17,9 +17,12 @@ package android.database.sqlite; import android.compat.annotation.UnsupportedAppUsage; +import android.util.ArrayMap; -import java.util.ArrayList; import java.util.Locale; +import java.util.Map; +import java.util.function.BinaryOperator; +import java.util.function.UnaryOperator; import java.util.regex.Pattern; /** @@ -87,10 +90,16 @@ public final class SQLiteDatabaseConfiguration { public boolean foreignKeyConstraintsEnabled; /** - * The custom functions to register. + * The custom scalar functions to register. */ - public final ArrayList<SQLiteCustomFunction> customFunctions = - new ArrayList<SQLiteCustomFunction>(); + public final ArrayMap<String, UnaryOperator<String>> customScalarFunctions + = new ArrayMap<>(); + + /** + * The custom aggregate functions to register. + */ + public final ArrayMap<String, BinaryOperator<String>> customAggregateFunctions + = new ArrayMap<>(); /** * The size in bytes of each lookaside slot @@ -181,8 +190,10 @@ public final class SQLiteDatabaseConfiguration { maxSqlCacheSize = other.maxSqlCacheSize; locale = other.locale; foreignKeyConstraintsEnabled = other.foreignKeyConstraintsEnabled; - customFunctions.clear(); - customFunctions.addAll(other.customFunctions); + customScalarFunctions.clear(); + customScalarFunctions.putAll(other.customScalarFunctions); + customAggregateFunctions.clear(); + customAggregateFunctions.putAll(other.customAggregateFunctions); lookasideSlotSize = other.lookasideSlotSize; lookasideSlotCount = other.lookasideSlotCount; idleConnectionTimeoutMs = other.idleConnectionTimeoutMs; diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index fb5f136f2fca..d67de09dd2a4 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -749,6 +749,17 @@ public final class DisplayManager { return mGlobal.getDefaultBrightnessConfiguration(); } + + /** + * Gets the last requested minimal post processing setting for the display with displayId. + * + * @hide + */ + @TestApi + public boolean isMinimalPostProcessingRequested(int displayId) { + return mGlobal.isMinimalPostProcessingRequested(displayId); + } + /** * Temporarily sets the brightness of the display. * <p> diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index 2a584951887f..fd539e8f1c91 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -594,6 +594,19 @@ public final class DisplayManagerGlobal { } /** + * Gets the last requested minimal post processing setting for the display with displayId. + * + * @hide + */ + public boolean isMinimalPostProcessingRequested(int displayId) { + try { + return mDm.isMinimalPostProcessingRequested(displayId); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /** * Temporarily sets the brightness of the display. * <p> * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission. diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index 0143c9129b50..ccf221b693bc 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -111,6 +111,9 @@ interface IDisplayManager { // Gets the default brightness configuration if configured. BrightnessConfiguration getDefaultBrightnessConfiguration(); + // Gets the last requested minimal post processing settings for display with displayId. + boolean isMinimalPostProcessingRequested(int displayId); + // Temporarily sets the display brightness. void setTemporaryBrightness(int brightness); diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index aae9fd4725b4..7cc78f7389c2 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -33,6 +33,7 @@ import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import java.util.ArrayList; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -50,20 +51,29 @@ public abstract class NetworkAgent { /** * The {@link Network} corresponding to this object. */ - @NonNull - public final Network network; + @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; private static final boolean DBG = true; private static final boolean VDBG = false; - private final Context mContext; private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>(); private volatile long mLastBwRefreshTime = 0; 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; /** * The ID of the {@link NetworkProvider} that created this object, or @@ -262,46 +272,96 @@ public abstract class NetworkAgent { */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; - // TODO : remove these two constructors. They are a stopgap measure to help sheperding a number - // of dependent changes that would conflict throughout the automerger graph. Having these - // temporarily helps with the process of going through with all these dependent changes across - // the entire tree. - /** @hide TODO: decide which of these to expose. */ + /** @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: decide which of these to expose. */ + /** @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: decide which of these to expose. */ + /** @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: decide which of these to expose. */ + /** @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 the type and an empty description. + return new NetworkInfo(config.legacyType, config.legacyType, config.legacyTypeName, ""); + } + + /** + * Create a new network agent. + * @param context a {@link Context} to get system services from. + * @param looper the {@link Looper} on which to invoke the callbacks. + * @param logTag the tag for logs + * @param nc the initial {@link NetworkCapabilities} of this network. Update with + * sendNetworkCapabilities. + * @param lp the initial {@link LinkProperties} of this network. Update with sendLinkProperties. + * @param score the initial score of this network. Update with sendNetworkScore. + * @param config an immutable {@link NetworkAgentConfig} for this agent. + * @param provider the {@link NetworkProvider} managing this agent. + */ + public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @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 */); + } + + private static class InitialConfiguration { + public final Context context; + public final NetworkCapabilities capabilities; + public final LinkProperties properties; + public final int score; + public final NetworkAgentConfig config; + public final NetworkInfo info; + InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, + @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config, + @NonNull NetworkInfo info) { + this.context = context; + this.capabilities = capabilities; + this.properties = properties; + this.score = score; + this.config = config; + this.info = info; + } + } + private volatile InitialConfiguration mInitialConfiguration; + + 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) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; - mContext = context; + mIsLegacy = legacy; + mNetworkInfo = new NetworkInfo(ni); this.providerId = providerId; if (ni == null || nc == null || lp == null) { throw new IllegalArgumentException(); } - if (VDBG) log("Registering NetworkAgent"); - ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( - Context.CONNECTIVITY_SERVICE); - network = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni), - new LinkProperties(lp), new NetworkCapabilities(nc), score, config, - providerId); + mInitialConfiguration = new InitialConfiguration(context, new NetworkCapabilities(nc), + new LinkProperties(lp), score, config, ni); } private class NetworkAgentHandler extends Handler { @@ -423,6 +483,32 @@ public abstract class NetworkAgent { } } + /** + * Register this network agent with ConnectivityService. + * @return the Network associated with this network agent (which can also be obtained later + * by calling getNetwork() on this agent). + */ + @NonNull + public Network register() { + if (VDBG) log("Registering NetworkAgent"); + final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context + .getSystemService(Context.CONNECTIVITY_SERVICE); + mNetwork = cm.registerNetworkAgent(new Messenger(mHandler), + new NetworkInfo(mInitialConfiguration.info), + mInitialConfiguration.properties, mInitialConfiguration.capabilities, + mInitialConfiguration.score, mInitialConfiguration.config, providerId); + mInitialConfiguration = null; // All this memory can now be GC'd + return mNetwork; + } + + /** + * @return The Network associated with this agent, or null if it's not registered yet. + */ + @Nullable + public Network getNetwork() { + return mNetwork; + } + private void queueOrSendMessage(int what, Object obj) { queueOrSendMessage(what, 0, 0, obj); } @@ -455,15 +541,89 @@ public abstract class NetworkAgent { * @param linkProperties the new LinkProperties. */ public void sendLinkProperties(@NonNull LinkProperties linkProperties) { + Objects.requireNonNull(linkProperties); queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties)); } /** + * Inform ConnectivityService that this agent has now connected. + */ + public void setConnected() { + if (mIsLegacy) { + throw new UnsupportedOperationException( + "Legacy agents can't call setConnected."); + } + mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); + queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); + } + + /** + * Unregister this network agent. + * + * This signals the network has disconnected and ends its lifecycle. After this is called, + * 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."); + } + mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); + queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); + } + + /** + * Change the legacy subtype of this network agent. + * + * This is only for backward compatibility and should not be used by non-legacy network agents, + * or agents that did not use to set a subtype. As such, only TYPE_MOBILE type agents can use + * this and others will be thrown an exception if they try. + * + * @deprecated this is for backward compatibility only. + * @param legacySubtype the legacy subtype. + */ + @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); + } + + /** + * Set the ExtraInfo of this network agent. + * + * This sets the ExtraInfo field inside the NetworkInfo returned by legacy public API and the + * broadcasts about the corresponding Network. + * This is only for backward compatibility and should not be used by non-legacy network agents, + * who will be thrown an exception if they try. The extra info should only be : + * <ul> + * <li>For cellular agents, the APN name.</li> + * <li>For ethernet agents, the interface name.</li> + * </ul> + * + * @deprecated this is for backward compatibility only. + * @param extraInfo the ExtraInfo. + */ + @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); + } + + /** * Must be called by the agent when it has a new NetworkInfo object. * @hide TODO: expose something better. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public void sendNetworkInfo(NetworkInfo networkInfo) { + if (!mIsLegacy) { + throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo."); + } queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo)); } @@ -472,6 +632,7 @@ public abstract class NetworkAgent { * @param networkCapabilities the new NetworkCapabilities. */ public void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { + Objects.requireNonNull(networkCapabilities); mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED, diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java index abc6b67efb11..2c5a113a93da 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -21,12 +21,10 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import android.text.TextUtils; /** * Allows a network transport to provide the system with policy and configuration information about - * a particular network when registering a {@link NetworkAgent}. This information cannot change once - * the agent is registered. + * a particular network when registering a {@link NetworkAgent}. This information cannot change once the agent is registered. * * @hide */ @@ -120,6 +118,19 @@ public final class NetworkAgentConfig implements Parcelable { } /** + * The legacy type of this network agent, or TYPE_NONE if unset. + * @hide + */ + public int legacyType = ConnectivityManager.TYPE_NONE; + + /** + * @return the legacy type + */ + public int getLegacyType() { + return legacyType; + } + + /** * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network. * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode. * @@ -127,6 +138,21 @@ public final class NetworkAgentConfig implements Parcelable { */ public boolean hasShownBroken; + /** + * The name of the legacy network type. It's a free-form string used in logging. + * @hide + */ + @NonNull + public String legacyTypeName = ""; + + /** + * @return the name of the legacy network type. It's a free-form string used in logging. + */ + @NonNull + public String getLegacyTypeName() { + return legacyTypeName; + } + /** @hide */ public NetworkAgentConfig() { } @@ -140,6 +166,8 @@ public final class NetworkAgentConfig implements Parcelable { subscriberId = nac.subscriberId; provisioningNotificationDisabled = nac.provisioningNotificationDisabled; skip464xlat = nac.skip464xlat; + legacyType = nac.legacyType; + legacyTypeName = nac.legacyTypeName; } } @@ -185,6 +213,29 @@ public final class NetworkAgentConfig implements Parcelable { } /** + * Sets the legacy type for this network. + * + * @param legacyType the type + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setLegacyType(int legacyType) { + mConfig.legacyType = legacyType; + return this; + } + + /** + * Sets the name of the legacy type of the agent. It's a free-form string used in logging. + * @param legacyTypeName the name + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setLegacyTypeName(@NonNull String legacyTypeName) { + mConfig.legacyTypeName = legacyTypeName; + return this; + } + + /** * Returns the constructed {@link NetworkAgentConfig} object. */ @NonNull diff --git a/core/java/android/net/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java index 530c84a8f3f0..83dbc637fb65 100644 --- a/core/java/android/net/StringNetworkSpecifier.java +++ b/core/java/android/net/StringNetworkSpecifier.java @@ -26,16 +26,7 @@ import com.android.internal.util.Preconditions; import java.util.Objects; -/** - * @deprecated use other subclass of {@link android.net.NetworkSpecifier}, - * eg. {@link android.net.TelephonyNetworkSpecifier}, - * {@link android.net.wifi.WifiNetworkSpecifier} instead. - * @see {@link android.net.NetworkRequest#setNetworkSpecifier(String)} for details. - * @removed this class was tentatively made SystemApi in December 2019 in the scramble for - * publishing mainline APIs, it should be removed before R release is published. - * @hide - */ -@Deprecated +/** @hide */ @SystemApi public final class StringNetworkSpecifier extends NetworkSpecifier implements Parcelable { /** diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl index 92fecaddff22..bbc936d76e1c 100644 --- a/core/java/android/os/storage/IStorageManager.aidl +++ b/core/java/android/os/storage/IStorageManager.aidl @@ -193,4 +193,5 @@ interface IStorageManager { void startCheckpoint(int numTries) = 85; boolean needsCheckpoint() = 86; void abortChanges(in String message, boolean retry) = 87; + void clearUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 88; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 0e3dd3a8292a..b97482a30cc0 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7598,6 +7598,12 @@ public final class Settings { public static final String DOZE_WAKE_DISPLAY_GESTURE = "doze_wake_display_gesture"; /** + * Whether the device should suppress the current doze configuration and disable dozing. + * @hide + */ + public static final String SUPPRESS_DOZE = "suppress_doze"; + + /** * Gesture that skips media. * @hide */ diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index f3690648f35b..453728137d9a 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -5374,5 +5374,11 @@ public final class Telephony { /** Whether uicc applications is set to be enabled or disabled. By default it's enabled. */ public static final String UICC_APPLICATIONS_ENABLED = "uicc_applications_enabled"; + + /** + * TelephonyProvider column name for allowed network types. Indicate which network types + * are allowed. Default is -1. + */ + public static final String ALLOWED_NETWORK_TYPES = "allowed_network_types"; } } diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java index 00060ab8ef4a..a5c5c613e1f2 100644 --- a/core/java/android/se/omapi/SEService.java +++ b/core/java/android/se/omapi/SEService.java @@ -98,6 +98,8 @@ public final class SEService { private static final String TAG = "OMAPI.SEService"; + private static final String UICC_TERMINAL = "SIM"; + private final Object mLock = new Object(); /** The client context (e.g. activity). */ @@ -190,32 +192,33 @@ public final class SEService { * is of length 0. */ public @NonNull Reader[] getReaders() { - if (mSecureElementService == null) { - throw new IllegalStateException("service not connected to system"); - } - String[] readerNames; - try { - readerNames = mSecureElementService.getReaders(); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + loadReaders(); - Reader[] readers = new Reader[readerNames.length]; - int i = 0; - for (String readerName : readerNames) { - if (mReaders.get(readerName) == null) { - try { - mReaders.put(readerName, new Reader(this, readerName, - getReader(readerName))); - readers[i++] = mReaders.get(readerName); - } catch (Exception e) { - Log.e(TAG, "Error adding Reader: " + readerName, e); - } - } else { - readers[i++] = mReaders.get(readerName); - } - } - return readers; + return mReaders.values().toArray(new Reader[0]); + } + + /** + * Obtain a UICC Reader instance with specific slot number from the SecureElementService + * + * @param slotNumber The index of the uicc slot. The index starts from 1. + * @throws IllegalArgumentException if the reader object corresponding to the uiccSlotNumber + * is not exist. + * @return A Reader object for this uicc slot. + */ + public @NonNull Reader getUiccReader(int slotNumber) { + if (slotNumber < 1) { + throw new IllegalArgumentException("slotNumber should be larger than 0"); + } + loadReaders(); + + String readerName = UICC_TERMINAL + slotNumber; + Reader reader = mReaders.get(readerName); + + if (reader == null) { + throw new IllegalArgumentException("Reader:" + readerName + " doesn't exist"); + } + + return reader; } /** @@ -270,4 +273,30 @@ public final class SEService { throw new IllegalStateException(e.getMessage()); } } + + /** + * Load available Secure Element Readers + */ + private void loadReaders() { + if (mSecureElementService == null) { + throw new IllegalStateException("service not connected to system"); + } + String[] readerNames; + try { + readerNames = mSecureElementService.getReaders(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + + for (String readerName : readerNames) { + if (mReaders.get(readerName) == null) { + try { + mReaders.put(readerName, new Reader(this, readerName, + getReader(readerName))); + } catch (Exception e) { + Log.e(TAG, "Error adding Reader: " + readerName, e); + } + } + } + } } diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 615dab0f04e4..d433591f2b3c 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -86,7 +86,7 @@ public final class DisplayCutout { * @hide */ public static final DisplayCutout NO_CUTOUT = new DisplayCutout( - ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT, + ZERO_RECT, Insets.NONE, ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT, false /* copyArguments */); @@ -103,8 +103,12 @@ public final class DisplayCutout { private static float sCachedDensity; @GuardedBy("CACHE_LOCK") private static Pair<Path, DisplayCutout> sCachedCutout = NULL_PAIR; + @GuardedBy("CACHE_LOCK") + private static Insets sCachedWaterfallInsets; private final Rect mSafeInsets; + @NonNull + private final Insets mWaterfallInsets; /** @@ -251,7 +255,32 @@ public final class DisplayCutout { // TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE) public DisplayCutout(@NonNull Insets safeInsets, @Nullable Rect boundLeft, @Nullable Rect boundTop, @Nullable Rect boundRight, @Nullable Rect boundBottom) { - this(safeInsets.toRect(), boundLeft, boundTop, boundRight, boundBottom, true); + this(safeInsets.toRect(), Insets.NONE, boundLeft, boundTop, boundRight, boundBottom, true); + } + + /** + * Creates a DisplayCutout instance. + * + * <p>Note that this is only useful for tests. For production code, developers should always + * use a {@link DisplayCutout} obtained from the system.</p> + * + * @param safeInsets the insets from each edge which avoid the display cutout as returned by + * {@link #getSafeInsetTop()} etc. + * @param boundLeft the left bounding rect of the display cutout in pixels. If null is passed, + * it's treated as an empty rectangle (0,0)-(0,0). + * @param boundTop the top bounding rect of the display cutout in pixels. If null is passed, + * it's treated as an empty rectangle (0,0)-(0,0). + * @param boundRight the right bounding rect of the display cutout in pixels. If null is + * passed, it's treated as an empty rectangle (0,0)-(0,0). + * @param boundBottom the bottom bounding rect of the display cutout in pixels. If null is + * passed, it's treated as an empty rectangle (0,0)-(0,0). + * @param waterfallInsets the insets for the curved areas in waterfall display. + */ + public DisplayCutout(@NonNull Insets safeInsets, @Nullable Rect boundLeft, + @Nullable Rect boundTop, @Nullable Rect boundRight, @Nullable Rect boundBottom, + @NonNull Insets waterfallInsets) { + this(safeInsets.toRect(), waterfallInsets, boundLeft, boundTop, boundRight, boundBottom, + true); } /** @@ -269,7 +298,7 @@ public final class DisplayCutout { // TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE) @Deprecated public DisplayCutout(@Nullable Rect safeInsets, @Nullable List<Rect> boundingRects) { - this(safeInsets, extractBoundsFromList(safeInsets, boundingRects), + this(safeInsets, Insets.NONE, extractBoundsFromList(safeInsets, boundingRects), true /* copyArguments */); } @@ -281,19 +310,23 @@ public final class DisplayCutout { * @param copyArguments if true, create a copy of the arguments. If false, the passed arguments * are not copied and MUST remain unchanged forever. */ - private DisplayCutout(Rect safeInsets, Rect boundLeft, Rect boundTop, Rect boundRight, - Rect boundBottom, boolean copyArguments) { + private DisplayCutout(Rect safeInsets, Insets waterfallInsets, Rect boundLeft, + Rect boundTop, Rect boundRight, Rect boundBottom, boolean copyArguments) { mSafeInsets = getCopyOrRef(safeInsets, copyArguments); + mWaterfallInsets = waterfallInsets == null ? Insets.NONE : waterfallInsets; mBounds = new Bounds(boundLeft, boundTop, boundRight, boundBottom, copyArguments); } - private DisplayCutout(Rect safeInsets, Rect[] bounds, boolean copyArguments) { + private DisplayCutout(Rect safeInsets, Insets waterfallInsets, Rect[] bounds, + boolean copyArguments) { mSafeInsets = getCopyOrRef(safeInsets, copyArguments); + mWaterfallInsets = waterfallInsets == null ? Insets.NONE : waterfallInsets; mBounds = new Bounds(bounds, copyArguments); } - private DisplayCutout(Rect safeInsets, Bounds bounds) { + private DisplayCutout(Rect safeInsets, Insets waterfallInsets, Bounds bounds) { mSafeInsets = safeInsets; + mWaterfallInsets = waterfallInsets == null ? Insets.NONE : waterfallInsets; mBounds = bounds; } @@ -309,6 +342,14 @@ public final class DisplayCutout { } /** + * Return the waterfall insets. + */ + public @NonNull Insets getWaterfallInsets() { + return mWaterfallInsets; + } + + + /** * Find the position of the bounding rect, and create an array of Rect whose index represents * the position (= BoundsPosition). * @@ -476,7 +517,8 @@ public final class DisplayCutout { @Override public int hashCode() { - return mSafeInsets.hashCode() * 48271 + mBounds.hashCode(); + return (mSafeInsets.hashCode() * 48271 + mBounds.hashCode()) * 48271 + + mWaterfallInsets.hashCode(); } @Override @@ -486,7 +528,8 @@ public final class DisplayCutout { } if (o instanceof DisplayCutout) { DisplayCutout c = (DisplayCutout) o; - return mSafeInsets.equals(c.mSafeInsets) && mBounds.equals(c.mBounds); + return mSafeInsets.equals(c.mSafeInsets) && mBounds.equals(c.mBounds) + && mWaterfallInsets.equals(c.mWaterfallInsets); } return false; } @@ -494,6 +537,7 @@ public final class DisplayCutout { @Override public String toString() { return "DisplayCutout{insets=" + mSafeInsets + + " waterfall=" + mWaterfallInsets + " boundingRect={" + mBounds + "}" + "}"; } @@ -508,6 +552,7 @@ public final class DisplayCutout { mBounds.getRect(BOUNDS_POSITION_TOP).dumpDebug(proto, BOUND_TOP); mBounds.getRect(BOUNDS_POSITION_RIGHT).dumpDebug(proto, BOUND_RIGHT); mBounds.getRect(BOUNDS_POSITION_BOTTOM).dumpDebug(proto, BOUND_BOTTOM); + mWaterfallInsets.toRect().dumpDebug(proto, INSETS); proto.end(token); } @@ -553,7 +598,7 @@ public final class DisplayCutout { } } - return new DisplayCutout(safeInsets, bounds, false /* copyArguments */); + return new DisplayCutout(safeInsets, mWaterfallInsets, bounds, false /* copyArguments */); } /** @@ -565,7 +610,7 @@ public final class DisplayCutout { * @hide */ public DisplayCutout replaceSafeInsets(Rect safeInsets) { - return new DisplayCutout(new Rect(safeInsets), mBounds); + return new DisplayCutout(new Rect(safeInsets), mWaterfallInsets, mBounds); } private static int atLeastZero(int value) { @@ -585,7 +630,16 @@ public final class DisplayCutout { for (int i = 0; i < BOUNDS_POSITION_LENGTH; ++i) { bounds[i] = (pos == i) ? new Rect(left, top, right, bottom) : new Rect(); } - return new DisplayCutout(ZERO_RECT, bounds, false /* copyArguments */); + return new DisplayCutout(ZERO_RECT, Insets.NONE, bounds, false /* copyArguments */); + } + + /** + * Creates an instance from a bounding and waterfall insets. + * + * @hide + */ + public static DisplayCutout fromBoundsAndWaterfall(Rect[] bounds, Insets waterfallInsets) { + return new DisplayCutout(ZERO_RECT, waterfallInsets, bounds, false /* copyArguments */); } /** @@ -594,7 +648,7 @@ public final class DisplayCutout { * @hide */ public static DisplayCutout fromBounds(Rect[] bounds) { - return new DisplayCutout(ZERO_RECT, bounds, false /* copyArguments */); + return new DisplayCutout(ZERO_RECT, Insets.NONE, bounds, false /* copyArguments */); } /** @@ -606,7 +660,8 @@ public final class DisplayCutout { */ public static DisplayCutout fromResourcesRectApproximation(Resources res, int displayWidth, int displayHeight) { return fromSpec(res.getString(R.string.config_mainBuiltInDisplayCutoutRectApproximation), - displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT); + displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT, + loadWaterfallInset(res)); } /** @@ -617,7 +672,8 @@ public final class DisplayCutout { public static Path pathFromResources(Resources res, int displayWidth, int displayHeight) { return pathAndDisplayCutoutFromSpec( res.getString(R.string.config_mainBuiltInDisplayCutout), - displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT).first; + displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT, + loadWaterfallInset(res)).first; } /** @@ -627,91 +683,109 @@ public final class DisplayCutout { */ @VisibleForTesting(visibility = PRIVATE) public static DisplayCutout fromSpec(String spec, int displayWidth, int displayHeight, - float density) { - return pathAndDisplayCutoutFromSpec(spec, displayWidth, displayHeight, density).second; + float density, Insets waterfallInsets) { + return pathAndDisplayCutoutFromSpec( + spec, displayWidth, displayHeight, density, waterfallInsets).second; } private static Pair<Path, DisplayCutout> pathAndDisplayCutoutFromSpec(String spec, - int displayWidth, int displayHeight, float density) { - if (TextUtils.isEmpty(spec)) { + int displayWidth, int displayHeight, float density, Insets waterfallInsets) { + if (TextUtils.isEmpty(spec) && waterfallInsets.equals(Insets.NONE)) { return NULL_PAIR; } + synchronized (CACHE_LOCK) { if (spec.equals(sCachedSpec) && sCachedDisplayWidth == displayWidth && sCachedDisplayHeight == displayHeight - && sCachedDensity == density) { + && sCachedDensity == density + && waterfallInsets.equals(sCachedWaterfallInsets)) { return sCachedCutout; } } - spec = spec.trim(); - final float offsetX; - if (spec.endsWith(RIGHT_MARKER)) { - offsetX = displayWidth; - spec = spec.substring(0, spec.length() - RIGHT_MARKER.length()).trim(); - } else if (spec.endsWith(LEFT_MARKER)) { - offsetX = 0; - spec = spec.substring(0, spec.length() - LEFT_MARKER.length()).trim(); - } else { - offsetX = displayWidth / 2f; - } - final boolean inDp = spec.endsWith(DP_MARKER); - if (inDp) { - spec = spec.substring(0, spec.length() - DP_MARKER.length()); - } + Path p = null; + Rect boundTop = null; + Rect boundBottom = null; + Rect safeInset = new Rect(); String bottomSpec = null; - if (spec.contains(BOTTOM_MARKER)) { - String[] splits = spec.split(BOTTOM_MARKER, 2); - spec = splits[0].trim(); - bottomSpec = splits[1].trim(); - } - - final Path p; - final Region r = Region.obtain(); - try { - p = PathParser.createPathFromPathData(spec); - } catch (Throwable e) { - Log.wtf(TAG, "Could not inflate cutout: ", e); - return NULL_PAIR; - } + if (!TextUtils.isEmpty(spec)) { + spec = spec.trim(); + final float offsetX; + if (spec.endsWith(RIGHT_MARKER)) { + offsetX = displayWidth; + spec = spec.substring(0, spec.length() - RIGHT_MARKER.length()).trim(); + } else if (spec.endsWith(LEFT_MARKER)) { + offsetX = 0; + spec = spec.substring(0, spec.length() - LEFT_MARKER.length()).trim(); + } else { + offsetX = displayWidth / 2f; + } + final boolean inDp = spec.endsWith(DP_MARKER); + if (inDp) { + spec = spec.substring(0, spec.length() - DP_MARKER.length()); + } - final Matrix m = new Matrix(); - if (inDp) { - m.postScale(density, density); - } - m.postTranslate(offsetX, 0); - p.transform(m); + if (spec.contains(BOTTOM_MARKER)) { + String[] splits = spec.split(BOTTOM_MARKER, 2); + spec = splits[0].trim(); + bottomSpec = splits[1].trim(); + } - Rect boundTop = new Rect(); - toRectAndAddToRegion(p, r, boundTop); - final int topInset = boundTop.bottom; + final Matrix m = new Matrix(); + final Region r = Region.obtain(); + if (!spec.isEmpty()) { + try { + p = PathParser.createPathFromPathData(spec); + } catch (Throwable e) { + Log.wtf(TAG, "Could not inflate cutout: ", e); + } - Rect boundBottom = null; - final int bottomInset; - if (bottomSpec != null) { - final Path bottomPath; - try { - bottomPath = PathParser.createPathFromPathData(bottomSpec); - } catch (Throwable e) { - Log.wtf(TAG, "Could not inflate bottom cutout: ", e); - return NULL_PAIR; + if (p != null) { + if (inDp) { + m.postScale(density, density); + } + m.postTranslate(offsetX, 0); + p.transform(m); + + boundTop = new Rect(); + toRectAndAddToRegion(p, r, boundTop); + safeInset.top = boundTop.bottom; + } + } + + if (bottomSpec != null) { + int bottomInset = 0; + Path bottomPath = null; + try { + bottomPath = PathParser.createPathFromPathData(bottomSpec); + } catch (Throwable e) { + Log.wtf(TAG, "Could not inflate bottom cutout: ", e); + } + + if (bottomPath != null) { + // Keep top transform + m.postTranslate(0, displayHeight); + bottomPath.transform(m); + p.addPath(bottomPath); + boundBottom = new Rect(); + toRectAndAddToRegion(bottomPath, r, boundBottom); + bottomInset = displayHeight - boundBottom.top; + } + safeInset.bottom = bottomInset; } - // Keep top transform - m.postTranslate(0, displayHeight); - bottomPath.transform(m); - p.addPath(bottomPath); - boundBottom = new Rect(); - toRectAndAddToRegion(bottomPath, r, boundBottom); - bottomInset = displayHeight - boundBottom.top; - } else { - bottomInset = 0; } - Rect safeInset = new Rect(0, topInset, 0, bottomInset); - final DisplayCutout cutout = new DisplayCutout( - safeInset, null /* boundLeft */, boundTop, null /* boundRight */, boundBottom, - false /* copyArguments */); + if (!waterfallInsets.equals(Insets.NONE)) { + safeInset.set( + Math.max(waterfallInsets.left, safeInset.left), + Math.max(waterfallInsets.top, safeInset.top), + Math.max(waterfallInsets.right, safeInset.right), + Math.max(waterfallInsets.bottom, safeInset.bottom)); + } + final DisplayCutout cutout = new DisplayCutout( + safeInset, waterfallInsets, null /* boundLeft */, boundTop, + null /* boundRight */, boundBottom, false /* copyArguments */); final Pair<Path, DisplayCutout> result = new Pair<>(p, cutout); synchronized (CACHE_LOCK) { sCachedSpec = spec; @@ -719,6 +793,7 @@ public final class DisplayCutout { sCachedDisplayHeight = displayHeight; sCachedDensity = density; sCachedCutout = result; + sCachedWaterfallInsets = waterfallInsets; } return result; } @@ -730,6 +805,15 @@ public final class DisplayCutout { inoutRegion.op(inoutRect, Op.UNION); } + + private static Insets loadWaterfallInset(Resources res) { + return Insets.of( + res.getDimensionPixelSize(R.dimen.waterfall_display_left_edge_size), + res.getDimensionPixelSize(R.dimen.waterfall_display_top_edge_size), + res.getDimensionPixelSize(R.dimen.waterfall_display_right_edge_size), + res.getDimensionPixelSize(R.dimen.waterfall_display_bottom_edge_size)); + } + /** * Helper class for passing {@link DisplayCutout} through binder. * @@ -773,6 +857,7 @@ public final class DisplayCutout { out.writeInt(1); out.writeTypedObject(cutout.mSafeInsets, flags); out.writeTypedArray(cutout.mBounds.getRects(), flags); + out.writeTypedObject(cutout.mWaterfallInsets, flags); } } @@ -815,8 +900,10 @@ public final class DisplayCutout { Rect safeInsets = in.readTypedObject(Rect.CREATOR); Rect[] bounds = new Rect[BOUNDS_POSITION_LENGTH]; in.readTypedArray(bounds, Rect.CREATOR); + Insets waterfallInsets = in.readTypedObject(Insets.CREATOR); - return new DisplayCutout(safeInsets, bounds, false /* copyArguments */); + return new DisplayCutout( + safeInsets, waterfallInsets, bounds, false /* copyArguments */); } public DisplayCutout get() { diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 7d455c93729c..b9868a7e1444 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -624,6 +624,8 @@ public final class DisplayInfo implements Parcelable { sb.append(Arrays.toString(supportedColorModes)); sb.append(", hdrCapabilities "); sb.append(hdrCapabilities); + sb.append(", minimalPostProcessingSupported "); + sb.append(minimalPostProcessingSupported); sb.append(", rotation "); sb.append(rotation); sb.append(", density "); diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index 69d01050801f..f5afd106a4a7 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -239,7 +239,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll return state.calculateInsets(frame, false /* isScreenRound */, false /* alwaysConsumeSystemBars */, null /* displayCutout */, null /* legacyContentInsets */, null /* legacyStableInsets */, - LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/, typeSideMap) + LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/, + 0 /* legacySystemUiFlags */, typeSideMap) .getInsets(mTypes); } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index e2739c469e5f..9bc8dce71856 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -246,6 +246,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private int mPendingTypesToShow; private int mLastLegacySoftInputMode; + private int mLastLegacySystemUiFlags; private boolean mStartingAnimation; private SyncRtSurfaceTransactionApplier mApplier; @@ -274,7 +275,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation WindowInsets insets = state.calculateInsets(mFrame, mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(), mLastInsets.getDisplayCutout(), mLastLegacyContentInsets, mLastLegacyStableInsets, mLastLegacySoftInputMode, - null /* typeSideMap */); + mLastLegacySystemUiFlags, null /* typeSideMap */); mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets); for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) { @@ -317,12 +318,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public WindowInsets calculateInsets(boolean isScreenRound, boolean alwaysConsumeSystemBars, DisplayCutout cutout, Rect legacyContentInsets, - Rect legacyStableInsets, int legacySoftInputMode) { + Rect legacyStableInsets, int legacySoftInputMode, int legacySystemUiFlags) { mLastLegacyContentInsets.set(legacyContentInsets); mLastLegacyStableInsets.set(legacyStableInsets); mLastLegacySoftInputMode = legacySoftInputMode; + mLastLegacySystemUiFlags = legacySystemUiFlags; mLastInsets = mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeSystemBars, cutout, - legacyContentInsets, legacyStableInsets, legacySoftInputMode, + legacyContentInsets, legacyStableInsets, legacySoftInputMode, legacySystemUiFlags, null /* typeSideMap */); return mLastInsets; } diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index e33ca70c222e..bd19799bb664 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -16,6 +16,7 @@ package android.view; +import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; @@ -143,7 +144,8 @@ public class InsetsState implements Parcelable { public WindowInsets calculateInsets(Rect frame, boolean isScreenRound, boolean alwaysConsumeSystemBars, DisplayCutout cutout, @Nullable Rect legacyContentInsets, @Nullable Rect legacyStableInsets, - int legacySoftInputMode, @Nullable @InternalInsetsSide SparseIntArray typeSideMap) { + int legacySoftInputMode, int legacySystemUiFlags, + @Nullable @InternalInsetsSide SparseIntArray typeSideMap) { Insets[] typeInsetsMap = new Insets[Type.SIZE]; Insets[] typeMaxInsetsMap = new Insets[Type.SIZE]; boolean[] typeVisibilityMap = new boolean[SIZE]; @@ -186,7 +188,9 @@ public class InsetsState implements Parcelable { return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound, alwaysConsumeSystemBars, cutout, softInputAdjustMode == SOFT_INPUT_ADJUST_RESIZE ? systemBars() | ime() - : systemBars()); + : systemBars(), + sNewInsetsMode == NEW_INSETS_MODE_FULL + && (legacySystemUiFlags & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0); } public Rect calculateVisibleInsets(Rect frame, Rect legacyVisibleInsets, diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 17b945b71773..2d1d78f158e7 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2082,7 +2082,9 @@ public final class ViewRootImpl implements ViewParent, mLastWindowInsets = mInsetsController.calculateInsets( mContext.getResources().getConfiguration().isScreenRound(), mAttachInfo.mAlwaysConsumeSystemBars, displayCutout, - contentInsets, stableInsets, mWindowAttributes.softInputMode); + contentInsets, stableInsets, mWindowAttributes.softInputMode, + (mWindowAttributes.systemUiVisibility + | mWindowAttributes.subtreeSystemUiVisibility)); } return mLastWindowInsets; } diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 9291b5652425..06c24b0fa3f3 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -27,6 +27,7 @@ import static android.view.WindowInsets.Type.STATUS_BARS; import static android.view.WindowInsets.Type.SYSTEM_GESTURES; import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT; import static android.view.WindowInsets.Type.all; +import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.indexOf; import static android.view.WindowInsets.Type.systemBars; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; @@ -46,6 +47,7 @@ import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethod; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; @@ -91,6 +93,7 @@ public final class WindowInsets { private final boolean mDisplayCutoutConsumed; private final int mCompatInsetTypes; + private final boolean mCompatIgnoreVisibility; /** * Since new insets may be added in the future that existing apps couldn't @@ -117,7 +120,8 @@ public final class WindowInsets { boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) { this(createCompatTypeMap(systemWindowInsetsRect), createCompatTypeMap(stableInsetsRect), createCompatVisibilityMap(createCompatTypeMap(systemWindowInsetsRect)), - isRound, alwaysConsumeSystemBars, displayCutout, systemBars()); + isRound, alwaysConsumeSystemBars, displayCutout, systemBars(), + false /* compatIgnoreVisibility */); } /** @@ -136,7 +140,8 @@ public final class WindowInsets { @Nullable Insets[] typeMaxInsetsMap, boolean[] typeVisibilityMap, boolean isRound, - boolean alwaysConsumeSystemBars, DisplayCutout displayCutout, int compatInsetTypes) { + boolean alwaysConsumeSystemBars, DisplayCutout displayCutout, int compatInsetTypes, + boolean compatIgnoreVisibility) { mSystemWindowInsetsConsumed = typeInsetsMap == null; mTypeInsetsMap = mSystemWindowInsetsConsumed ? new Insets[SIZE] @@ -151,6 +156,7 @@ public final class WindowInsets { mIsRound = isRound; mAlwaysConsumeSystemBars = alwaysConsumeSystemBars; mCompatInsetTypes = compatInsetTypes; + mCompatIgnoreVisibility = compatIgnoreVisibility; mDisplayCutoutConsumed = displayCutout == null; mDisplayCutout = (mDisplayCutoutConsumed || displayCutout.isEmpty()) @@ -167,7 +173,8 @@ public final class WindowInsets { src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap, src.mTypeVisibilityMap, src.mIsRound, src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src), - src.mCompatInsetTypes); + src.mCompatInsetTypes, + src.mCompatIgnoreVisibility); } private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) { @@ -219,7 +226,7 @@ public final class WindowInsets { @UnsupportedAppUsage public WindowInsets(Rect systemWindowInsets) { this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, false, null, - systemBars()); + systemBars(), false /* compatIgnoreVisibility */); } /** @@ -239,7 +246,8 @@ public final class WindowInsets { /** * @hide */ - static void assignCompatInsets(Insets[] typeInsetsMap, Rect insets) { + @VisibleForTesting + public static void assignCompatInsets(Insets[] typeInsetsMap, Rect insets) { typeInsetsMap[indexOf(STATUS_BARS)] = Insets.of(0, insets.top, 0, 0); typeInsetsMap[indexOf(NAVIGATION_BARS)] = Insets.of(insets.left, 0, insets.right, insets.bottom); @@ -288,7 +296,15 @@ public final class WindowInsets { */ @NonNull public Insets getSystemWindowInsets() { - return getInsets(mTypeInsetsMap, mCompatInsetTypes); + Insets result = mCompatIgnoreVisibility + ? getMaxInsets(mCompatInsetTypes & ~ime()) + : getInsets(mCompatInsetTypes); + + // We can't query max insets for IME, so we need to add it manually after. + if ((mCompatInsetTypes & ime()) != 0 && mCompatIgnoreVisibility) { + result = Insets.max(result, getInsets(ime())); + } + return result; } /** @@ -448,7 +464,7 @@ public final class WindowInsets { mTypeVisibilityMap, mIsRound, mAlwaysConsumeSystemBars, null /* displayCutout */, - mCompatInsetTypes); + mCompatInsetTypes, mCompatIgnoreVisibility); } @@ -491,11 +507,11 @@ public final class WindowInsets { */ @NonNull public WindowInsets consumeSystemWindowInsets() { - return new WindowInsets(null, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, + return new WindowInsets(null, null, mTypeVisibilityMap, mIsRound, mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(this), - mCompatInsetTypes); + mCompatInsetTypes, mCompatIgnoreVisibility); } // TODO(b/119190588): replace @code with @link below @@ -741,10 +757,7 @@ public final class WindowInsets { */ @NonNull public WindowInsets consumeStableInsets() { - return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, null, - mTypeVisibilityMap, mIsRound, mAlwaysConsumeSystemBars, - displayCutoutCopyConstructorArgument(this), - mCompatInsetTypes); + return consumeSystemWindowInsets(); } /** @@ -829,7 +842,7 @@ public final class WindowInsets { : mDisplayCutout == null ? DisplayCutout.NO_CUTOUT : mDisplayCutout.inset(left, top, right, bottom), - mCompatInsetTypes); + mCompatInsetTypes, mCompatIgnoreVisibility); } @Override @@ -1147,7 +1160,7 @@ public final class WindowInsets { return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, mIsRound, mAlwaysConsumeSystemBars, mDisplayCutout, - systemBars()); + systemBars(), false /* compatIgnoreVisibility */); } } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index f7d9706a9fce..290a13d3feb1 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1131,6 +1131,15 @@ public interface WindowManager extends ViewManager { public static final int TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39; /** + * Window type: the notification shade and keyguard. There can be only one status bar + * window; it is placed at the top of the screen, and all other + * windows are shifted down so they are below it. + * In multiuser systems shows on all users' windows. + * @hide + */ + public static final int TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40; + + /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999; @@ -1732,14 +1741,6 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_SYSTEM_ERROR = 0x00000100; /** - * Flag whether the current window is a keyguard window, meaning that it will hide all other - * windows behind it except for windows with flag {@link #FLAG_SHOW_WHEN_LOCKED} set. - * Further, this can only be set by {@link LayoutParams#TYPE_STATUS_BAR}. - * {@hide} - */ - public static final int PRIVATE_FLAG_KEYGUARD = 0x00000400; - - /** * Flag that prevents the wallpaper behind the current window from receiving touch events. * * {@hide} @@ -1748,12 +1749,12 @@ public interface WindowManager extends ViewManager { /** * Flag to force the status bar window to be visible all the time. If the bar is hidden when - * this flag is set it will be shown again and the bar will have a transparent background. + * this flag is set it will be shown again. * This can only be set by {@link LayoutParams#TYPE_STATUS_BAR}. * * {@hide} */ - public static final int PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT = 0x00001000; + public static final int PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR = 0x00001000; /** * Flag indicating that the x, y, width, and height members should be @@ -1917,17 +1918,13 @@ public interface WindowManager extends ViewManager { equals = PRIVATE_FLAG_SYSTEM_ERROR, name = "SYSTEM_ERROR"), @ViewDebug.FlagToString( - mask = PRIVATE_FLAG_KEYGUARD, - equals = PRIVATE_FLAG_KEYGUARD, - name = "KEYGUARD"), - @ViewDebug.FlagToString( mask = PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS, equals = PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS, name = "DISABLE_WALLPAPER_TOUCH_EVENTS"), @ViewDebug.FlagToString( - mask = PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT, - equals = PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT, - name = "FORCE_STATUS_BAR_VISIBLE_TRANSPARENT"), + mask = PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR, + equals = PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR, + name = "FORCE_STATUS_BAR_VISIBLE"), @ViewDebug.FlagToString( mask = PRIVATE_FLAG_PRESERVE_GEOMETRY, equals = PRIVATE_FLAG_PRESERVE_GEOMETRY, @@ -2402,7 +2399,8 @@ public interface WindowManager extends ViewManager { flag = true, value = {LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT, LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, - LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER}) + LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER, + LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS}) @interface LayoutInDisplayCutoutMode {} /** @@ -2414,6 +2412,7 @@ public interface WindowManager extends ViewManager { * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER + * @see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS * @see DisplayCutout * @see android.R.attr#windowLayoutInDisplayCutoutMode * android:windowLayoutInDisplayCutoutMode @@ -2447,13 +2446,6 @@ public interface WindowManager extends ViewManager { public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0; /** - * @deprecated use {@link #LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES} - * @hide - */ - @Deprecated - public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 1; - - /** * The window is always allowed to extend into the {@link DisplayCutout} areas on the short * edges of the screen. * @@ -2516,6 +2508,25 @@ public interface WindowManager extends ViewManager { */ public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2; + /** + * The window is always allowed to extend into the {@link DisplayCutout} areas on the all + * edges of the screen. + * + * <p> + * The window must make sure that no important content overlaps with the + * {@link DisplayCutout}. + * + * <p> + * In this mode, the window extends under cutouts on the all edges of the display in both + * portrait and landscape, regardless of whether the window is hiding the system bars. + * + * @see DisplayCutout + * @see WindowInsets#getDisplayCutout() + * @see #layoutInDisplayCutoutMode + * @see android.R.attr#windowLayoutInDisplayCutoutMode + * android:windowLayoutInDisplayCutoutMode + */ + public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 3; /** * When this window has focus, disable touch pad pointer gesture processing. diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index f0a346ab25fd..e298556617df 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -35,6 +35,7 @@ import android.system.ErrnoException; import android.system.Os; import android.util.Log; +import dalvik.annotation.optimization.FastNative; import dalvik.system.ZygoteHooks; import libcore.io.IoUtils; @@ -1018,4 +1019,19 @@ public final class Zygote { command.append(" '").append(arg.replace("'", "'\\''")).append("'"); } } + + /** + * Parse the given unsolicited zygote message as type SIGCHLD, + * extract the payload information into the given output buffer. + * + * @param in The unsolicited zygote message to be parsed + * @param length The number of bytes in the message + * @param out The output buffer where the payload information will be placed + * @return Number of elements being place into output buffer, or -1 if + * either the message is malformed or not the type as expected here. + * + * @hide + */ + @FastNative + public static native int nativeParseSigChld(byte[] in, int length, int[] out); } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 01709782fb91..a6637a2fb601 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -1240,9 +1240,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } updateBackgroundDrawable(); - if (insets != null) { - insets = insets.consumeStableInsets(); - } return insets; } diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 88a9cb0aefef..4abd39797ba0 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -27,8 +27,8 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; -import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import android.annotation.NonNull; @@ -2466,7 +2466,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (a.hasValue(R.styleable.Window_windowLayoutInDisplayCutoutMode)) { int mode = a.getInt(R.styleable.Window_windowLayoutInDisplayCutoutMode, -1); if (mode < LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT - || mode > LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER) { + || mode > LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) { throw new UnsupportedOperationException("Unknown windowLayoutInDisplayCutoutMode: " + a.getString(R.styleable.Window_windowLayoutInDisplayCutoutMode)); } diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp index d9ed07ebcfbb..c80f1dc28595 100644 --- a/core/jni/android_database_SQLiteConnection.cpp +++ b/core/jni/android_database_SQLiteConnection.cpp @@ -59,14 +59,12 @@ namespace android { static const int BUSY_TIMEOUT_MS = 2500; static struct { - jfieldID name; - jfieldID numArgs; - jmethodID dispatchCallback; -} gSQLiteCustomFunctionClassInfo; + jmethodID apply; +} gUnaryOperator; static struct { - jclass clazz; -} gStringClassInfo; + jmethodID apply; +} gBinaryOperator; struct SQLiteConnection { // Open flags. @@ -203,74 +201,146 @@ static void nativeClose(JNIEnv* env, jclass clazz, jlong connectionPtr) { } } -// Called each time a custom function is evaluated. -static void sqliteCustomFunctionCallback(sqlite3_context *context, +static void sqliteCustomScalarFunctionCallback(sqlite3_context *context, int argc, sqlite3_value **argv) { JNIEnv* env = AndroidRuntime::getJNIEnv(); - - // Get the callback function object. - // Create a new local reference to it in case the callback tries to do something - // dumb like unregister the function (thereby destroying the global ref) while it is running. jobject functionObjGlobal = reinterpret_cast<jobject>(sqlite3_user_data(context)); - jobject functionObj = env->NewLocalRef(functionObjGlobal); - - jobjectArray argsArray = env->NewObjectArray(argc, gStringClassInfo.clazz, NULL); - if (argsArray) { - for (int i = 0; i < argc; i++) { - const jchar* arg = static_cast<const jchar*>(sqlite3_value_text16(argv[i])); - if (!arg) { - ALOGW("NULL argument in custom_function_callback. This should not happen."); - } else { - size_t argLen = sqlite3_value_bytes16(argv[i]) / sizeof(jchar); - jstring argStr = env->NewString(arg, argLen); - if (!argStr) { - goto error; // out of memory error - } - env->SetObjectArrayElement(argsArray, i, argStr); - env->DeleteLocalRef(argStr); - } - } + ScopedLocalRef<jobject> functionObj(env, env->NewLocalRef(functionObjGlobal)); + ScopedLocalRef<jstring> argString(env, + env->NewStringUTF(reinterpret_cast<const char*>(sqlite3_value_text(argv[0])))); + ScopedLocalRef<jstring> resString(env, + (jstring) env->CallObjectMethod(functionObj.get(), gUnaryOperator.apply, argString.get())); - // TODO: Support functions that return values. - env->CallVoidMethod(functionObj, - gSQLiteCustomFunctionClassInfo.dispatchCallback, argsArray); + if (env->ExceptionCheck()) { + ALOGE("Exception thrown by custom scalar function"); + sqlite3_result_error(context, "Exception thrown by custom scalar function", -1); + env->ExceptionDescribe(); + env->ExceptionClear(); + return; + } -error: - env->DeleteLocalRef(argsArray); + if (resString.get() == nullptr) { + sqlite3_result_null(context); + } else { + ScopedUtfChars res(env, resString.get()); + sqlite3_result_text(context, res.c_str(), -1, SQLITE_TRANSIENT); } +} + +static void sqliteCustomScalarFunctionDestructor(void* data) { + jobject functionObjGlobal = reinterpret_cast<jobject>(data); + + JNIEnv* env = AndroidRuntime::getJNIEnv(); + env->DeleteGlobalRef(functionObjGlobal); +} - env->DeleteLocalRef(functionObj); +static void nativeRegisterCustomScalarFunction(JNIEnv* env, jclass clazz, jlong connectionPtr, + jstring functionName, jobject functionObj) { + SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); + + jobject functionObjGlobal = env->NewGlobalRef(functionObj); + ScopedUtfChars functionNameChars(env, functionName); + int err = sqlite3_create_function_v2(connection->db, + functionNameChars.c_str(), 1, SQLITE_UTF8, + reinterpret_cast<void*>(functionObjGlobal), + &sqliteCustomScalarFunctionCallback, + nullptr, + nullptr, + &sqliteCustomScalarFunctionDestructor); + + if (err != SQLITE_OK) { + ALOGE("sqlite3_create_function returned %d", err); + env->DeleteGlobalRef(functionObjGlobal); + throw_sqlite3_exception(env, connection->db); + return; + } +} + +static void sqliteCustomAggregateFunctionStep(sqlite3_context *context, + int argc, sqlite3_value **argv) { + char** agg = reinterpret_cast<char**>( + sqlite3_aggregate_context(context, sizeof(const char**))); + if (agg == nullptr) { + return; + } else if (*agg == nullptr) { + // During our first call the best we can do is allocate our result + // holder and populate it with our first value; we'll reduce it + // against any additional values in future calls + const char* res = reinterpret_cast<const char*>(sqlite3_value_text(argv[0])); + if (res == nullptr) { + *agg = nullptr; + } else { + *agg = strdup(res); + } + return; + } + + JNIEnv* env = AndroidRuntime::getJNIEnv(); + jobject functionObjGlobal = reinterpret_cast<jobject>(sqlite3_user_data(context)); + ScopedLocalRef<jobject> functionObj(env, env->NewLocalRef(functionObjGlobal)); + ScopedLocalRef<jstring> arg0String(env, + env->NewStringUTF(reinterpret_cast<const char*>(*agg))); + ScopedLocalRef<jstring> arg1String(env, + env->NewStringUTF(reinterpret_cast<const char*>(sqlite3_value_text(argv[0])))); + ScopedLocalRef<jstring> resString(env, + (jstring) env->CallObjectMethod(functionObj.get(), gBinaryOperator.apply, + arg0String.get(), arg1String.get())); if (env->ExceptionCheck()) { - ALOGE("An exception was thrown by custom SQLite function."); - LOGE_EX(env); + ALOGE("Exception thrown by custom aggregate function"); + sqlite3_result_error(context, "Exception thrown by custom aggregate function", -1); + env->ExceptionDescribe(); env->ExceptionClear(); + return; + } + + // One way or another, we have a new value to collect, and we need to + // free our previous value + if (*agg != nullptr) { + free(*agg); + } + if (resString.get() == nullptr) { + *agg = nullptr; + } else { + ScopedUtfChars res(env, resString.get()); + *agg = strdup(res.c_str()); + } +} + +static void sqliteCustomAggregateFunctionFinal(sqlite3_context *context) { + // We pass zero size here to avoid allocating for empty sets + char** agg = reinterpret_cast<char**>( + sqlite3_aggregate_context(context, 0)); + if (agg == nullptr) { + return; + } else if (*agg == nullptr) { + sqlite3_result_null(context); + } else { + sqlite3_result_text(context, *agg, -1, SQLITE_TRANSIENT); + free(*agg); } } -// Called when a custom function is destroyed. -static void sqliteCustomFunctionDestructor(void* data) { +static void sqliteCustomAggregateFunctionDestructor(void* data) { jobject functionObjGlobal = reinterpret_cast<jobject>(data); JNIEnv* env = AndroidRuntime::getJNIEnv(); env->DeleteGlobalRef(functionObjGlobal); } -static void nativeRegisterCustomFunction(JNIEnv* env, jclass clazz, jlong connectionPtr, - jobject functionObj) { +static void nativeRegisterCustomAggregateFunction(JNIEnv* env, jclass clazz, jlong connectionPtr, + jstring functionName, jobject functionObj) { SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); - jstring nameStr = jstring(env->GetObjectField( - functionObj, gSQLiteCustomFunctionClassInfo.name)); - jint numArgs = env->GetIntField(functionObj, gSQLiteCustomFunctionClassInfo.numArgs); - jobject functionObjGlobal = env->NewGlobalRef(functionObj); - - const char* name = env->GetStringUTFChars(nameStr, NULL); - int err = sqlite3_create_function_v2(connection->db, name, numArgs, SQLITE_UTF16, + ScopedUtfChars functionNameChars(env, functionName); + int err = sqlite3_create_function_v2(connection->db, + functionNameChars.c_str(), 1, SQLITE_UTF8, reinterpret_cast<void*>(functionObjGlobal), - &sqliteCustomFunctionCallback, NULL, NULL, &sqliteCustomFunctionDestructor); - env->ReleaseStringUTFChars(nameStr, name); + nullptr, + &sqliteCustomAggregateFunctionStep, + &sqliteCustomAggregateFunctionFinal, + &sqliteCustomAggregateFunctionDestructor); if (err != SQLITE_OK) { ALOGE("sqlite3_create_function returned %d", err); @@ -812,8 +882,10 @@ static const JNINativeMethod sMethods[] = (void*)nativeOpen }, { "nativeClose", "(J)V", (void*)nativeClose }, - { "nativeRegisterCustomFunction", "(JLandroid/database/sqlite/SQLiteCustomFunction;)V", - (void*)nativeRegisterCustomFunction }, + { "nativeRegisterCustomScalarFunction", "(JLjava/lang/String;Ljava/util/function/UnaryOperator;)V", + (void*)nativeRegisterCustomScalarFunction }, + { "nativeRegisterCustomAggregateFunction", "(JLjava/lang/String;Ljava/util/function/BinaryOperator;)V", + (void*)nativeRegisterCustomAggregateFunction }, { "nativeRegisterLocalizedCollators", "(JLjava/lang/String;)V", (void*)nativeRegisterLocalizedCollators }, { "nativePrepareStatement", "(JLjava/lang/String;)J", @@ -864,15 +936,13 @@ static const JNINativeMethod sMethods[] = int register_android_database_SQLiteConnection(JNIEnv *env) { - jclass clazz = FindClassOrDie(env, "android/database/sqlite/SQLiteCustomFunction"); - - gSQLiteCustomFunctionClassInfo.name = GetFieldIDOrDie(env, clazz, "name", "Ljava/lang/String;"); - gSQLiteCustomFunctionClassInfo.numArgs = GetFieldIDOrDie(env, clazz, "numArgs", "I"); - gSQLiteCustomFunctionClassInfo.dispatchCallback = GetMethodIDOrDie(env, clazz, - "dispatchCallback", "([Ljava/lang/String;)V"); + jclass unaryClazz = FindClassOrDie(env, "java/util/function/UnaryOperator"); + gUnaryOperator.apply = GetMethodIDOrDie(env, unaryClazz, + "apply", "(Ljava/lang/Object;)Ljava/lang/Object;"); - clazz = FindClassOrDie(env, "java/lang/String"); - gStringClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); + jclass binaryClazz = FindClassOrDie(env, "java/util/function/BinaryOperator"); + gBinaryOperator.apply = GetMethodIDOrDie(env, binaryClazz, + "apply", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); return RegisterMethodsOrDie(env, "android/database/sqlite/SQLiteConnection", sMethods, NELEM(sMethods)); diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 05b573ab90b4..9d02d105e11e 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -67,6 +67,7 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> +#include <sys/un.h> #include <sys/utsname.h> #include <sys/wait.h> #include <unistd.h> @@ -163,6 +164,12 @@ static std::atomic_uint32_t gUsapPoolCount = 0; */ static int gUsapPoolEventFD = -1; +/** + * The socket file descriptor used to send notifications to the + * system_server. + */ +static int gSystemServerSocketFd = -1; + static constexpr int DEFAULT_DATA_DIR_PERMISSION = 0751; /** @@ -344,6 +351,26 @@ enum RuntimeFlags : uint32_t { PROFILE_FROM_SHELL = 1 << 15, }; +enum UnsolicitedZygoteMessageTypes : uint32_t { + UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED = 0, + UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD = 1, +}; + +struct UnsolicitedZygoteMessageSigChld { + struct { + UnsolicitedZygoteMessageTypes type; + } header; + struct { + pid_t pid; + uid_t uid; + int status; + } payload; +}; + +// Keep sync with services/core/java/com/android/server/am/ProcessList.java +static constexpr struct sockaddr_un kSystemServerSockAddr = + {.sun_family = AF_LOCAL, .sun_path = "/data/system/unsolzygotesocket"}; + // Forward declaration so we don't have to move the signal handler. static bool RemoveUsapTableEntry(pid_t usap_pid); @@ -353,74 +380,107 @@ static void RuntimeAbort(JNIEnv* env, int line, const char* msg) { env->FatalError(oss.str().c_str()); } -// This signal handler is for zygote mode, since the zygote must reap its children -static void SigChldHandler(int /*signal_number*/) { - pid_t pid; - int status; - int64_t usaps_removed = 0; - - // It's necessary to save and restore the errno during this function. - // Since errno is stored per thread, changing it here modifies the errno - // on the thread on which this signal handler executes. If a signal occurs - // between a call and an errno check, it's possible to get the errno set - // here. - // See b/23572286 for extra information. - int saved_errno = errno; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { - // Log process-death status that we care about. - if (WIFEXITED(status)) { - async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, - "Process %d exited cleanly (%d)", pid, WEXITSTATUS(status)); - - // Check to see if the PID is in the USAP pool and remove it if it is. - if (RemoveUsapTableEntry(pid)) { - ++usaps_removed; - } - } else if (WIFSIGNALED(status)) { - async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, - "Process %d exited due to signal %d (%s)%s", pid, - WTERMSIG(status), strsignal(WTERMSIG(status)), - WCOREDUMP(status) ? "; core dumped" : ""); - - // If the process exited due to a signal other than SIGTERM, check to see - // if the PID is in the USAP pool and remove it if it is. If the process - // was closed by the Zygote using SIGTERM then the USAP pool entry will - // have already been removed (see nativeEmptyUsapPool()). - if (WTERMSIG(status) != SIGTERM && RemoveUsapTableEntry(pid)) { - ++usaps_removed; - } +// Create the socket which is going to be used to send unsolicited message +// to system_server, the socket will be closed post forking a child process. +// It's expected to be called at each zygote's initialization. +static void initUnsolSocketToSystemServer() { + gSystemServerSocketFd = socket(AF_LOCAL, SOCK_DGRAM | SOCK_NONBLOCK, 0); + if (gSystemServerSocketFd >= 0) { + ALOGV("Zygote:systemServerSocketFD = %d", gSystemServerSocketFd); + } else { + ALOGE("Unable to create socket file descriptor to connect to system_server"); + } +} + +static void sendSigChildStatus(const pid_t pid, const uid_t uid, const int status) { + int socketFd = gSystemServerSocketFd; + if (socketFd >= 0) { + // fill the message buffer + struct UnsolicitedZygoteMessageSigChld data = + {.header = {.type = UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD}, + .payload = {.pid = pid, .uid = uid, .status = status}}; + if (TEMP_FAILURE_RETRY( + sendto(socketFd, &data, sizeof(data), 0, + reinterpret_cast<const struct sockaddr*>(&kSystemServerSockAddr), + sizeof(kSystemServerSockAddr))) == -1) { + async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, + "Zygote failed to write to system_server FD: %s", + strerror(errno)); + } } +} - // If the just-crashed process is the system_server, bring down zygote - // so that it is restarted by init and system server will be restarted - // from there. - if (pid == gSystemServerPid) { - async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, - "Exit zygote because system server (pid %d) has terminated", pid); - kill(getpid(), SIGKILL); +// This signal handler is for zygote mode, since the zygote must reap its children +static void SigChldHandler(int /*signal_number*/, siginfo_t* info, void* /*ucontext*/) { + pid_t pid; + int status; + int64_t usaps_removed = 0; + + // It's necessary to save and restore the errno during this function. + // Since errno is stored per thread, changing it here modifies the errno + // on the thread on which this signal handler executes. If a signal occurs + // between a call and an errno check, it's possible to get the errno set + // here. + // See b/23572286 for extra information. + int saved_errno = errno; + + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + // Notify system_server that we received a SIGCHLD + sendSigChildStatus(pid, info->si_uid, status); + // Log process-death status that we care about. + if (WIFEXITED(status)) { + async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, "Process %d exited cleanly (%d)", pid, + WEXITSTATUS(status)); + + // Check to see if the PID is in the USAP pool and remove it if it is. + if (RemoveUsapTableEntry(pid)) { + ++usaps_removed; + } + } else if (WIFSIGNALED(status)) { + async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, + "Process %d exited due to signal %d (%s)%s", pid, + WTERMSIG(status), strsignal(WTERMSIG(status)), + WCOREDUMP(status) ? "; core dumped" : ""); + + // If the process exited due to a signal other than SIGTERM, check to see + // if the PID is in the USAP pool and remove it if it is. If the process + // was closed by the Zygote using SIGTERM then the USAP pool entry will + // have already been removed (see nativeEmptyUsapPool()). + if (WTERMSIG(status) != SIGTERM && RemoveUsapTableEntry(pid)) { + ++usaps_removed; + } + } + + // If the just-crashed process is the system_server, bring down zygote + // so that it is restarted by init and system server will be restarted + // from there. + if (pid == gSystemServerPid) { + async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, + "Exit zygote because system server (pid %d) has terminated", pid); + kill(getpid(), SIGKILL); + } } - } - // Note that we shouldn't consider ECHILD an error because - // the secondary zygote might have no children left to wait for. - if (pid < 0 && errno != ECHILD) { - async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, - "Zygote SIGCHLD error in waitpid: %s", strerror(errno)); - } + // Note that we shouldn't consider ECHILD an error because + // the secondary zygote might have no children left to wait for. + if (pid < 0 && errno != ECHILD) { + async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, "Zygote SIGCHLD error in waitpid: %s", + strerror(errno)); + } - if (usaps_removed > 0) { - if (TEMP_FAILURE_RETRY(write(gUsapPoolEventFD, &usaps_removed, sizeof(usaps_removed))) == -1) { - // If this write fails something went terribly wrong. We will now kill - // the zygote and let the system bring it back up. - async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, - "Zygote failed to write to USAP pool event FD: %s", - strerror(errno)); - kill(getpid(), SIGKILL); + if (usaps_removed > 0) { + if (TEMP_FAILURE_RETRY(write(gUsapPoolEventFD, &usaps_removed, sizeof(usaps_removed))) == + -1) { + // If this write fails something went terribly wrong. We will now kill + // the zygote and let the system bring it back up. + async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, + "Zygote failed to write to USAP pool event FD: %s", + strerror(errno)); + kill(getpid(), SIGKILL); + } } - } - errno = saved_errno; + errno = saved_errno; } // Configures the SIGCHLD/SIGHUP handlers for the zygote process. This is @@ -441,12 +501,11 @@ static void SigChldHandler(int /*signal_number*/) { // This ends up being called repeatedly before each fork(), but there's // no real harm in that. static void SetSignalHandlers() { - struct sigaction sig_chld = {}; - sig_chld.sa_handler = SigChldHandler; + struct sigaction sig_chld = {.sa_flags = SA_SIGINFO, .sa_sigaction = SigChldHandler}; - if (sigaction(SIGCHLD, &sig_chld, nullptr) < 0) { - ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); - } + if (sigaction(SIGCHLD, &sig_chld, nullptr) < 0) { + ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); + } struct sigaction sig_hup = {}; sig_hup.sa_handler = SIG_IGN; @@ -1049,6 +1108,9 @@ static pid_t ForkCommon(JNIEnv* env, bool is_system_server, // Turn fdsan back on. android_fdsan_set_error_level(fdsan_error_level); + + // Reset the fd to the unsolicited zygote socket + gSystemServerSocketFd = -1; } else { ALOGD("Forked child process %d", pid); } @@ -1094,19 +1156,19 @@ static std::string getAppDataDirName(std::string_view parent_path, std::string_v fail_fn(CREATE_ERROR("Unexpected error in getAppDataDirName: %s", strerror(errno))); return nullptr; } - // Directory doesn't exist, try to search the name from inode - DIR* dir = opendir(parent_path.data()); - if (dir == nullptr) { - fail_fn(CREATE_ERROR("Failed to opendir %s", parent_path.data())); - } - struct dirent* ent; - while ((ent = readdir(dir))) { - if (ent->d_ino == ce_data_inode) { - closedir(dir); - return ent->d_name; + { + // Directory doesn't exist, try to search the name from inode + std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(parent_path.data()), closedir); + if (dir == nullptr) { + fail_fn(CREATE_ERROR("Failed to opendir %s", parent_path.data())); + } + struct dirent* ent; + while ((ent = readdir(dir.get()))) { + if (ent->d_ino == ce_data_inode) { + return ent->d_name; + } } } - closedir(dir); // Fallback due to b/145989852, ce_data_inode stored in package manager may be corrupted // if ino_t is 32 bits. @@ -1117,19 +1179,18 @@ static std::string getAppDataDirName(std::string_view parent_path, std::string_v fixed_ce_data_inode = ((ce_data_inode >> 32) & LOWER_HALF_WORD_MASK); } if (fixed_ce_data_inode != 0) { - dir = opendir(parent_path.data()); + std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(parent_path.data()), closedir); if (dir == nullptr) { fail_fn(CREATE_ERROR("Failed to opendir %s", parent_path.data())); } - while ((ent = readdir(dir))) { + struct dirent* ent; + while ((ent = readdir(dir.get()))) { if (ent->d_ino == fixed_ce_data_inode) { long long d_ino = ent->d_ino; ALOGW("Fallback success inode %lld -> %lld", ce_data_inode, d_ino); - closedir(dir); return ent->d_name; } } - closedir(dir); } // Fallback done @@ -1608,6 +1669,10 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, } } + if (is_child_zygote) { + initUnsolSocketToSystemServer(); + } + env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, is_child_zygote, managed_instruction_set); @@ -1873,6 +1938,11 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( fds_to_ignore.push_back(gUsapPoolEventFD); } + if (gSystemServerSocketFd != -1) { + fds_to_close.push_back(gSystemServerSocketFd); + fds_to_ignore.push_back(gSystemServerSocketFd); + } + pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true); if (pid == 0) { @@ -1899,6 +1969,11 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( fds_to_ignore.push_back(gUsapPoolEventFD); } + if (gSystemServerSocketFd != -1) { + fds_to_close.push_back(gSystemServerSocketFd); + fds_to_ignore.push_back(gSystemServerSocketFd); + } + pid_t pid = ForkCommon(env, true, fds_to_close, fds_to_ignore, @@ -1969,6 +2044,9 @@ static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env, fds_to_close.push_back(gZygoteSocketFD); fds_to_close.push_back(gUsapPoolEventFD); fds_to_close.insert(fds_to_close.end(), session_socket_fds.begin(), session_socket_fds.end()); + if (gSystemServerSocketFd != -1) { + fds_to_close.push_back(gSystemServerSocketFd); + } fds_to_ignore.push_back(gZygoteSocketFD); fds_to_ignore.push_back(gUsapPoolSocketFD); @@ -1976,6 +2054,9 @@ static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env, fds_to_ignore.push_back(read_pipe_fd); fds_to_ignore.push_back(write_pipe_fd); fds_to_ignore.insert(fds_to_ignore.end(), session_socket_fds.begin(), session_socket_fds.end()); + if (gSystemServerSocketFd != -1) { + fds_to_ignore.push_back(gSystemServerSocketFd); + } pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore, is_priority_fork == JNI_TRUE); @@ -2074,6 +2155,8 @@ static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jc ALOGE("Unable to fetch USAP pool socket file descriptor"); } + initUnsolSocketToSystemServer(); + /* * Security Initialization */ @@ -2200,43 +2283,81 @@ static void com_android_internal_os_Zygote_nativeBoostUsapPriority(JNIEnv* env, setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX); } +static jint com_android_internal_os_Zygote_nativeParseSigChld(JNIEnv* env, jclass, jbyteArray in, + jint length, jintArray out) { + if (length != sizeof(struct UnsolicitedZygoteMessageSigChld)) { + // Apparently it's not the message we are expecting. + return -1; + } + if (in == nullptr || out == nullptr) { + // Invalid parameter + jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); + return -1; + } + ScopedByteArrayRO source(env, in); + if (source.size() < length) { + // Invalid parameter + jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); + return -1; + } + const struct UnsolicitedZygoteMessageSigChld* msg = + reinterpret_cast<const struct UnsolicitedZygoteMessageSigChld*>(source.get()); + + switch (msg->header.type) { + case UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD: { + ScopedIntArrayRW buf(env, out); + if (buf.size() != 3) { + jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); + return UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED; + } + buf[0] = msg->payload.pid; + buf[1] = msg->payload.uid; + buf[2] = msg->payload.status; + return 3; + } + default: + break; + } + return -1; +} + static const JNINativeMethod gMethods[] = { - { "nativeForkAndSpecialize", - "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;)I", - (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize }, - { "nativeForkSystemServer", "(II[II[[IJJ)I", - (void *) com_android_internal_os_Zygote_nativeForkSystemServer }, - { "nativeAllowFileAcrossFork", "(Ljava/lang/String;)V", - (void *) com_android_internal_os_Zygote_nativeAllowFileAcrossFork }, - { "nativePreApplicationInit", "()V", - (void *) com_android_internal_os_Zygote_nativePreApplicationInit }, - { "nativeInstallSeccompUidGidFilter", "(II)V", - (void *) com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter }, - { "nativeForkUsap", "(II[IZ)I", - (void *) com_android_internal_os_Zygote_nativeForkUsap }, - { "nativeSpecializeAppProcess", - "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;)V", - (void *) com_android_internal_os_Zygote_nativeSpecializeAppProcess }, - { "nativeInitNativeState", "(Z)V", - (void *) com_android_internal_os_Zygote_nativeInitNativeState }, - { "nativeGetUsapPipeFDs", "()[I", - (void *) com_android_internal_os_Zygote_nativeGetUsapPipeFDs }, - { "nativeRemoveUsapTableEntry", "(I)Z", - (void *) com_android_internal_os_Zygote_nativeRemoveUsapTableEntry }, - { "nativeGetUsapPoolEventFD", "()I", - (void *) com_android_internal_os_Zygote_nativeGetUsapPoolEventFD }, - { "nativeGetUsapPoolCount", "()I", - (void *) com_android_internal_os_Zygote_nativeGetUsapPoolCount }, - { "nativeEmptyUsapPool", "()V", - (void *) com_android_internal_os_Zygote_nativeEmptyUsapPool }, - { "nativeDisableExecuteOnly", "()Z", - (void *) com_android_internal_os_Zygote_nativeDisableExecuteOnly }, - { "nativeBlockSigTerm", "()V", - (void* ) com_android_internal_os_Zygote_nativeBlockSigTerm }, - { "nativeUnblockSigTerm", "()V", - (void* ) com_android_internal_os_Zygote_nativeUnblockSigTerm }, - { "nativeBoostUsapPriority", "()V", - (void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority } + {"nativeForkAndSpecialize", + "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/" + "String;Z[Ljava/lang/String;)I", + (void*)com_android_internal_os_Zygote_nativeForkAndSpecialize}, + {"nativeForkSystemServer", "(II[II[[IJJ)I", + (void*)com_android_internal_os_Zygote_nativeForkSystemServer}, + {"nativeAllowFileAcrossFork", "(Ljava/lang/String;)V", + (void*)com_android_internal_os_Zygote_nativeAllowFileAcrossFork}, + {"nativePreApplicationInit", "()V", + (void*)com_android_internal_os_Zygote_nativePreApplicationInit}, + {"nativeInstallSeccompUidGidFilter", "(II)V", + (void*)com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter}, + {"nativeForkUsap", "(II[IZ)I", (void*)com_android_internal_os_Zygote_nativeForkUsap}, + {"nativeSpecializeAppProcess", + "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/" + "String;Z[Ljava/lang/String;)V", + (void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess}, + {"nativeInitNativeState", "(Z)V", + (void*)com_android_internal_os_Zygote_nativeInitNativeState}, + {"nativeGetUsapPipeFDs", "()[I", + (void*)com_android_internal_os_Zygote_nativeGetUsapPipeFDs}, + {"nativeRemoveUsapTableEntry", "(I)Z", + (void*)com_android_internal_os_Zygote_nativeRemoveUsapTableEntry}, + {"nativeGetUsapPoolEventFD", "()I", + (void*)com_android_internal_os_Zygote_nativeGetUsapPoolEventFD}, + {"nativeGetUsapPoolCount", "()I", + (void*)com_android_internal_os_Zygote_nativeGetUsapPoolCount}, + {"nativeEmptyUsapPool", "()V", (void*)com_android_internal_os_Zygote_nativeEmptyUsapPool}, + {"nativeDisableExecuteOnly", "()Z", + (void*)com_android_internal_os_Zygote_nativeDisableExecuteOnly}, + {"nativeBlockSigTerm", "()V", (void*)com_android_internal_os_Zygote_nativeBlockSigTerm}, + {"nativeUnblockSigTerm", "()V", (void*)com_android_internal_os_Zygote_nativeUnblockSigTerm}, + {"nativeBoostUsapPriority", "()V", + (void*)com_android_internal_os_Zygote_nativeBoostUsapPriority}, + {"nativeParseSigChld", "([BI[I)I", + (void*)com_android_internal_os_Zygote_nativeParseSigChld}, }; int register_com_android_internal_os_Zygote(JNIEnv* env) { diff --git a/core/proto/android/app/appexitinfo.proto b/core/proto/android/app/appexitinfo.proto new file mode 100644 index 000000000000..e23f150fab25 --- /dev/null +++ b/core/proto/android/app/appexitinfo.proto @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +option java_multiple_files = true; + +package android.app; + +import "frameworks/base/core/proto/android/privacy.proto"; + +/** + * An android.app.ApplicationExitInfo object. + */ +message ApplicationExitInfoProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 pid = 1; + optional int32 real_uid = 2; + optional int32 package_uid = 3; + optional int32 defining_uid = 4; + optional string process_name = 5; + optional int32 connection_group = 6; + + enum ReasonCode { + /** + * Application process died due to unknown reason. + */ + REASON_UNKNOWN = 0; + + /** + * Application process exit normally by itself, for example, + * via {@link android.os.Process#exit}; {@link #status} will specify the exit code. + * + * <p>Applications should normally not do this, as the system has a better knowledge + * in terms of process management.</p> + */ + REASON_EXIT_SELF = 1; + + /** + * Application process died due to the result of an OS signal; for example, + * {@link android.os.Process#SIGNAL_KILL}; {@link #status} will specify the signum. + */ + REASON_SIGNALED = 2; + + /** + * Application process was killed by the system low memory killer, meaning the system was + * under memory pressure at the time of kill. + */ + REASON_LOW_MEMORY = 3; + + /** + * Application process died because of an unhandled exception in Java code. + */ + REASON_CRASH = 4; + + /** + * Application process died because it's crashed due to a native code crash. + */ + REASON_CRASH_NATIVE = 5; + + /** + * Application process was killed due to being unresponsive (ANR). + */ + REASON_ANR = 6; + + /** + * Application process was killed because it took too long to attach to the system + * during the start. + */ + REASON_INITIALIZATION_FAILURE = 7; + + /** + * Application process was killed because of initialization failure, + * for example, it took too long to attach to the system during the start, + * or there was an error during initialization. + */ + REASON_PERMISSION_CHANGE = 8; + + /** + * Application process was killed by the activity manager due to excessive resource usage. + */ + REASON_EXCESSIVE_RESOURCE_USAGE = 9; + + /** + * Application process was killed by the system for various other reasons, + * for example, the application package got disabled by the user; + * {@link #description} will specify the cause given by the system. + */ + REASON_OTHER = 10; + + } + optional ReasonCode reason = 7; + + enum SubReason { + /** + * Application process kills subReason is unknown. + */ + SUBREASON_UNKNOWN = 0; + + /** + * Application process was killed because user quit it on the "wait for debugger" dialog. + */ + SUBREASON_WAIT_FOR_DEBUGGER = 1; + + /** + * Application process was killed by the activity manager because there were too many cached + * processes. + */ + SUBREASON_TOO_MANY_CACHED = 2; + + /** + * Application process was killed by the activity manager because there were too many empty + * processes. + */ + SUBREASON_TOO_MANY_EMPTY = 3; + + /** + * Application process was killed by the activity manager because there were too many cached + * processes and this process had been in empty state for a long time. + */ + SUBREASON_TRIM_EMPTY = 4; + + /** + * Application process was killed by the activity manager because system was on + * memory pressure and this process took large amount of cached memory. + */ + SUBREASON_LARGE_CACHED = 5; + + /** + * Application process was killed by the activity manager because the system was on + * low memory pressure for a significant amount of time since last idle. + */ + SUBREASON_MEMORY_PRESSURE = 6; + + /** + * Application process was killed by the activity manager due to excessive CPU usage. + */ + SUBREASON_EXCESSIVE_CPU = 7; + } + + optional SubReason sub_reason = 8; + + optional int32 status = 9; + + enum Importance { + option allow_alias = true; + /** + * Keep sync with the definitions in + * {@link android.app.ActivityManager.RunningAppProcessInfo} + */ + IMPORTANCE_FOREGROUND = 100; + IMPORTANCE_FOREGROUND_SERVICE = 125; + IMPORTANCE_TOP_SLEEPING_PRE_28 = 150; + IMPORTANCE_VISIBLE = 200; + IMPORTANCE_PERCEPTIBLE_PRE_26 = 130; + IMPORTANCE_PERCEPTIBLE = 230; + IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170; + IMPORTANCE_SERVICE = 300; + IMPORTANCE_TOP_SLEEPING = 325; + IMPORTANCE_CANT_SAVE_STATE = 350; + IMPORTANCE_CACHED = 400; + IMPORTANCE_BACKGROUND = 400; + IMPORTANCE_EMPTY = 500; + IMPORTANCE_GONE = 1000; + } + + optional Importance importance = 10; + optional int32 pss = 11; + optional int32 rss = 12; + optional int64 timestamp = 13; + optional string description = 14; +} diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index cd3887e276ff..a85c8f4e798b 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2557,4 +2557,9 @@ enum PageId { // OS: R DND_PEOPLE = 1823; + // OPEN: Settings > Apps and notifications > App info > one of any app > Open by default + // > Open supported links + // CATEGORY: SETTINGS + // OS: R + OPEN_SUPPORTED_LINKS = 1824; } diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 7835016439e0..77d4e87cec56 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -188,6 +188,7 @@ message SecureSettingsProto { optional SettingProto pulse_on_long_press = 4 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto pulse_on_double_tap = 5 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto pulse_on_tap = 6 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto suppress = 7 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Doze doze = 21; diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index c79f314ffaf2..126d44529edc 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -19,6 +19,7 @@ syntax = "proto2"; package com.android.server.am; import "frameworks/base/core/proto/android/app/activitymanager.proto"; +import "frameworks/base/core/proto/android/app/appexitinfo.proto"; import "frameworks/base/core/proto/android/app/enums.proto"; import "frameworks/base/core/proto/android/app/notification.proto"; import "frameworks/base/core/proto/android/app/profilerinfo.proto"; @@ -1082,3 +1083,23 @@ message AppTimeTrackerProto { optional .android.util.Duration started_time = 4; optional string started_package = 5; } + +// sync with com.android.server.am.am.ProcessList.java +message AppsExitInfoProto { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int64 last_update_timestamp = 1; + message Package { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string package_name = 1; + message User { + option (.android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 uid = 1; + repeated .android.app.ApplicationExitInfoProto app_exit_info = 2; + } + repeated User users = 2; + } + repeated Package packages = 2; +} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 6b27348b6d87..718114244059 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -563,10 +563,12 @@ <protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" /> - <protected-broadcast android:name="com.android.phone.SIP_INCOMING_CALL" /> + <protected-broadcast android:name="android.net.sip.action.SIP_INCOMING_CALL" /> <protected-broadcast android:name="com.android.phone.SIP_ADD_PHONE" /> - <protected-broadcast android:name="com.android.phone.SIP_REMOVE_PHONE" /> - <protected-broadcast android:name="com.android.phone.SIP_CALL_OPTION_CHANGED" /> + <protected-broadcast android:name="android.net.sip.action.SIP_REMOVE_PROFILE" /> + <protected-broadcast android:name="android.net.sip.action.SIP_SERVICE_UP" /> + <protected-broadcast android:name="android.net.sip.action.SIP_CALL_OPTION_CHANGED" /> + <protected-broadcast android:name="android.net.sip.action.START_SIP" /> <protected-broadcast android:name="android.bluetooth.adapter.action.BLE_ACL_CONNECTED" /> <protected-broadcast android:name="android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED" /> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 3dd5651c6e96..be0e58824ad8 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"by jou kalender in te gaan"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS-boodskappe te stuur en te bekyk"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Berging"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"toegang te verkry tot foto\'s, media en lêers op jou toestel"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofoon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"oudio op te neem"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan tik, swiep, knyp en ander gebare uitvoer."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Vingerafdrukgebare"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebare vasvang wat op die toestel se vingerafdruksensor uitgevoer word."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"deaktiveer of verander statusbalk"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Laat die program toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"wees die statusbalk"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Verhoog volume bo aanbevole vlak?\n\nOm lang tydperke teen hoë volume te luister, kan jou gehoor beskadig."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gebruik toeganklikheidkortpad?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Wanneer die kortpad aan is, sal \'n toeganklikheidkenmerk begin word as albei volumeknoppies 3 sekondes lank gedruk word.\n\n Bestaande toeganklikheidkenmerk:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Jy kan die kenmerk in Instellings > Toeganklikheid verander."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Maak leeg"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Wysig kortpaaie"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Kanselleer"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Skakel kortpad af"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gebruik kortpad"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Kleuromkering"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Skakel werkprofiel aan?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Jou werkprogramme, kennisgewings, data en ander werkprofielkenmerke sal aangeskakel word"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Skakel aan"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Hierdie program is vir \'n ouer weergawe van Android gebou en sal dalk nie behoorlik werk nie. Probeer kyk vir opdaterings, of kontak die ontwikkelaar."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kyk vir opdatering"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Jy het nuwe boodskappe"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Battery kan afloop voordat dit normaalweg gelaai word"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterybespaarder is geaktiveer om batterylewe te verleng"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterybespaarder"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Batterybespaarder sal nie weer aanskakel voordat battery amper pap is nie"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Battery is tot \'n voldoende vlak gelaai. Batterybespaarder sal nie weer aanskakel voordat battery amper pap is nie"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Foon <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> gelaai"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> gelaai"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Toestel <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> gelaai"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Batterybespaarder is af. Kenmerke is nie meer beperk nie."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Batterybespaarder is afgeskakel. Kenmerke is nie meer beperk nie."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Vouer"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android-program"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Lêer"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 9b9dbb0c7d4c..c92d3b0b6947 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"የእርስዎን ቀን መቁጠሪያ ይድረሱበት"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"ኤስኤምኤስ"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"የኤስኤምኤስ መልዕክቶችን ይላኩና ይመልከቱ"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"ማከማቻ"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"ፋይሎች እና ሚዲያ"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"በመሳሪያዎ ላይ ያሉ ፎቶዎችን፣ ማህደረመረጃን እና ፋይሎችን ይድረሱ"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"ማይክሮፎን"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ኦዲዮ ይቅዱ"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"መታ ማድረግ፣ ማንሸራተት፣ መቆንጠጥ እና ሌሎች የጣት ምልክቶችን ማከናወን ይችላል።"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"የጣት አሻራ ምልክቶች"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"በመሣሪያው የጣት አሻራ ዳሳሽ ላይ የተከናወኑ የጣት ምልክቶችን መያዝ ይችላል።"</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ቅጽበታዊ ገጽ እይታን ያነሳል"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"የማሳያው ቅጽበታዊ ገጽ እይታን ማንሳት ይችላል።"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"የሁኔቴ አሞሌ አቦዝን ወይም ቀይር"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"የሁኔታ አሞሌ መሆን"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ድምጹ ከሚመከረው መጠን በላይ ከፍ ይበል?\n\nበከፍተኛ ድምጽ ለረጅም ጊዜ ማዳመጥ ጆሮዎን ሊጎዳው ይችላል።"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"የተደራሽነት አቋራጭ ጥቅም ላይ ይዋል?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"አቋራጩ ሲበራ ሁለቱንም የድምፅ አዝራሮች ለ3 ሰከንዶች ተጭኖ መቆየት የተደራሽነት ባህሪን ያስጀምረዋል።\n\n አሁን ያለ የተደራሽነት ባህሪ፦\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ባህሪውን በቅንብሮች > ተደራሽነት ውስጥ ሊለውጡት ይችላሉ።"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ባዶ"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"አቋራጮችን አርትዕ ያድርጉ"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ይቅር"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"አቋራጩን አጥፋ"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"አቋራጭ ይጠቀሙ"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"ተቃራኒ ቀለም"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"የስራ መገለጫ ይብራ?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"የእርስዎ የስራ መተግበሪያዎች፣ ማሳወቂያዎች፣ ውሂብ እና ሌሎች የስራ መገለጫ ባህሪያት ይበራሉ"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"አብራ"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"መተግበሪያ አይገኝም"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> አሁን አይገኝም።"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ይህ መተግበሪያ ለቆየ የAndroid ስሪት ነው የተገነባው፣ እና በአግባቡ ላይሰራ ይችላል። ዝማኔዎች ካሉ ለመመልከት ይሞክሩ፣ ወይም ደግሞ ገንቢውን ያነጋግሩ።"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ዝማኔ ካለ አረጋግጥ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"አዲስ መልዕክቶች አለዎት"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ባትሪ ከተለመደው ኃይል መሙላት በፊት ሊያልቅ ይችላል"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"የባትሪ ቆጣቢ የባትሪ ዕድሜን ለማራዘም ገብሯል።"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ባትሪ ቆጣቢ"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"ባትሪ ቆጣቢ ባትሪ እንደገና ዝቅ እስከሚል ድረስ ዳግም አይገብርም።"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ባትሪ በቂ ወደ ሆነ ደረጃ ኃይል ተሞልቷል። የባትሪ ቆጣቢ ባቲትው እንደገና ዝቅ እስከሚል ድረስ ዳግም አይገብርም።"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ስልክ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ኃይል ተሞልቷል"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ጡባዊ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ኃይል ተሞልቷል"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"መሣሪያ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ኃይል ተሞልቷል"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"የባትሪ ኃይል ቆጣቢ ጠፍቷል። ባህሪያት ከእንግዲህ የተገደቡ አይደሉም።"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"የባትሪ ቆጣቢ ጠፍቷል። ባህሪያት ከእንግዲህ የተገደቡ አይደሉም።"</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"የባትሪ ቆጣቢ ጠፍቷል"</string> + <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_apk" msgid="3168784749499623902">"የAndroid መተግበሪያ"</string> <string name="mime_type_generic" msgid="4606589110116560228">"ፋይል"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 68708d3557a0..1a6bbd8dc9a3 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -299,7 +299,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"الوصول تقويمك"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"إرسال رسائل قصيرة SMS وعرضها"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"التخزين"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"الوصول إلى الصور والوسائط والملفات على جهازك"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"الميكروفون"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"تسجيل الصوت"</string> @@ -322,9 +323,13 @@ <string name="capability_title_canControlMagnification" msgid="7701572187333415795">"التحكم في تكبير الشاشة"</string> <string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"يمكنك التحكّم في مستوى تكبير/تصغير الشاشة وتحديد الموضع."</string> <string name="capability_title_canPerformGestures" msgid="9106545062106728987">"تنفيذ إيماءات"</string> - <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"يمكن النقر والتمرير بسرعة والتصغير وتنفيذ إيماءات أخرى."</string> + <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"يمكن النقر والتمرير بسرعة والتصغير أو التكبير بإصبعين وتنفيذ إيماءات أخرى."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"إيماءات بصمات الإصبع"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"يمكن أن تلتقط الإيماءات التي تم تنفيذها على جهاز استشعار بصمات الإصبع في الجهاز."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"إيقاف شريط الحالة أو تعديله"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"للسماح للتطبيق بإيقاف شريط الحالة أو إضافة رموز نظام وإزالتها."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"العمل كشريط للحالة"</string> @@ -658,13 +663,13 @@ <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"للسماح للمالك ببدء استخدام الإذن لأحد التطبيقات. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string> <string name="policylab_limitPassword" msgid="4851829918814422199">"تعيين قواعد كلمة المرور"</string> <string name="policydesc_limitPassword" msgid="4105491021115793793">"للتحكم في الطول والأحرف المسموح بها في كلمات المرور وأرقام التعريف الشخصي في قفل الشاشة."</string> - <string name="policylab_watchLogin" msgid="7599669460083719504">"مراقبة محاولات إلغاء قفل الشاشة"</string> - <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"لمراقبة عدد مرات كتابة كلمات المرور غير الصحيحة عند إلغاء تأمين الشاشة وتأمين الجهاز اللوحي أو مسح جميع بياناته في حالة كتابة الكثير من كلمات المرور غير الصحيحة."</string> - <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند إلغاء قفل الشاشة، وقفل جهاز Android TV أو محو جميع بيانات جهاز Android TV إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> - <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند إلغاء تأمين الشاشة، وتأمين الهاتف ومحو جميع بياناته إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> - <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند إلغاء تأمين الشاشة، وتأمين الجهاز اللوحي ومحو جميع بيانات هذا المستخدم إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> - <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند إلغاء قفل الشاشة، وقفل جهاز Android TV أو محو جميع بيانات هذا المستخدم إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> - <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند إلغاء تأمين الشاشة، وتأمين الهاتف ومحو جميع بيانات هذا المستخدم إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> + <string name="policylab_watchLogin" msgid="7599669460083719504">"مراقبة محاولات فتح قفل الشاشة"</string> + <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"لمراقبة عدد مرات كتابة كلمات المرور غير الصحيحة عند فتح قفل الشاشة وتأمين الجهاز اللوحي أو مسح جميع بياناته في حالة كتابة الكثير من كلمات المرور غير الصحيحة."</string> + <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وقفل جهاز Android TV أو محو جميع بيانات جهاز Android TV إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> + <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وتأمين الهاتف ومحو جميع بياناته إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> + <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وتأمين الجهاز اللوحي ومحو جميع بيانات هذا المستخدم إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> + <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وقفل جهاز Android TV أو محو جميع بيانات هذا المستخدم إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> + <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وتأمين الهاتف ومحو جميع بيانات هذا المستخدم إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"تغيير قفل الشاشة"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"إمكانية تغيير قفل الشاشة"</string> <string name="policylab_forceLock" msgid="7360335502968476434">"قفل الشاشة"</string> @@ -821,7 +826,7 @@ <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"صحيح!"</string> <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"أعد المحاولة"</string> <string name="lockscreen_password_wrong" msgid="8605355913868947490">"أعد المحاولة"</string> - <string name="lockscreen_storage_locked" msgid="634993789186443380">"إلغاء قفل جميع الميزات والبيانات"</string> + <string name="lockscreen_storage_locked" msgid="634993789186443380">"فتح قفل جميع الميزات والبيانات"</string> <string name="faceunlock_multiple_failures" msgid="681991538434031708">"تم تجاوز الحد الأقصى لعدد محاولات تأمين الجهاز بالوجه"</string> <string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"ليست هناك شريحة SIM"</string> <string name="lockscreen_missing_sim_message" product="tablet" msgid="8596805728510570760">"ليس هناك شريحة SIM في الجهاز اللوحي."</string> @@ -843,22 +848,22 @@ <string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"شريحة SIM مؤمّنة بكود PUK."</string> <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"راجع دليل المستخدم أو اتصل بخدمة العملاء."</string> <string name="lockscreen_sim_locked_message" msgid="3160196135801185938">"شريحة SIM مؤمّنة."</string> - <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="2286497117428409709">"جارٍ إلغاء تأمين شريحة SIM…"</string> + <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="2286497117428409709">"جارٍ فتح قفل شريحة SIM…"</string> <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"لقد رسمت نقش فتح القفل بطريقة غير صحيحة <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة.\n\nيُرجى إعادة المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string> <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="3118353451602377380">"لقد كتبت كلمة المرور <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة بشكل غير صحيح. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string> <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="2874278239714821984">"لقد كتبت رمز PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة بشكل غير صحيح. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string> <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3069635524964070596">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الجهاز اللوحي باستخدام معلومات تسجيل الدخول إلى Google.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string> <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="6399092175942158529">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء<xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة أخرى غير ناجحة، ستُطالب بإلغاء قفل جهاز Android TV باستخدام معلومات تسجيل الدخول إلى Google.\n\n يُرجى إعادة المحاولة بعد <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string> <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="5691623136957148335">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام معلومات تسجيل الدخول إلى Google.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"لقد حاولت إلغاء تأمين الجهاز اللوحي <xliff:g id="NUMBER_0">%1$d</xliff:g> من المرات. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة، ستتم إعادة تعيين الجهاز اللوحي إلى الإعدادات الأساسية وسيتم فقد جميع بيانات المستخدم."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"لقد حاولت إلغاء قفل جهاز Android TV بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة أخرى غير ناجحة، ستتم إعادة ضبط جهاز Android TV على الإعداد التلقائي للمصنع وسيتم فقدان جميع بيانات المستخدمين."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"لقد حاولت إلغاء تأمين الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> من المرات. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة، ستتم إعادة تعيين الهاتف إلى الإعدادات الأساسية وسيتم فقد جميع بيانات المستخدم."</string> - <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"لقد حاولت إلغاء تأمين الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> من المرات بشكل غير صحيح. سيتم الآن إعادة تعيين الجهاز اللوحي إلى الإعدادات الأساسية."</string> - <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"لقد حاولت إلغاء قفل جهاز Android TV بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم الآن إعادة ضبط جهاز Android TV على الإعداد التلقائي للمصنع."</string> - <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"لقد حاولت إلغاء تأمين الهاتف <xliff:g id="NUMBER">%d</xliff:g> من المرات بشكل غير صحيح. سيتم الآن إعادة تعيين الهاتف إلى الإعدادات الأساسية."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="7914445759242151426">"لقد حاولت فتح قفل الجهاز اللوحي <xliff:g id="NUMBER_0">%1$d</xliff:g> من المرات. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة، ستتم إعادة تعيين الجهاز اللوحي إلى الإعدادات الأساسية وسيتم فقد جميع بيانات المستخدم."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="4275591249631864248">"لقد حاولت فتح قفل جهاز Android TV بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة أخرى غير ناجحة، ستتم إعادة ضبط جهاز Android TV على الإعداد التلقائي للمصنع وسيتم فقدان جميع بيانات المستخدمين."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="1166532464798446579">"لقد حاولت فتح قفل الهاتف <xliff:g id="NUMBER_0">%1$d</xliff:g> من المرات. بعد <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة، ستتم إعادة تعيين الهاتف إلى الإعدادات الأساسية وسيتم فقد جميع بيانات المستخدم."</string> + <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="8682445539263683414">"لقد حاولت فتح قفل الجهاز اللوحي <xliff:g id="NUMBER">%d</xliff:g> من المرات بشكل غير صحيح. سيتم الآن إعادة تعيين الجهاز اللوحي إلى الإعدادات الأساسية."</string> + <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2205435033340091883">"لقد حاولت فتح قفل جهاز Android TV بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم الآن إعادة ضبط جهاز Android TV على الإعداد التلقائي للمصنع."</string> + <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"لقد حاولت فتح قفل الهاتف <xliff:g id="NUMBER">%d</xliff:g> من المرات بشكل غير صحيح. سيتم الآن إعادة تعيين الهاتف إلى الإعدادات الأساسية."</string> <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"حاول مرة أخرى خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية."</string> <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"هل نسيت النمط؟"</string> - <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"إلغاء تأمين الحساب"</string> + <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"فتح قفل الحساب"</string> <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"محاولات النقش كثيرة جدًا"</string> <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"لإلغاء التأمين، سجّل الدخول بحسابك في Google."</string> <string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"اسم المستخدم (البريد إلكتروني)"</string> @@ -867,7 +872,7 @@ <string name="lockscreen_glogin_invalid_input" msgid="4369219936865697679">"اسم المستخدم غير صحيح أو كلمة المرور غير صحيحة."</string> <string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"هل نسيت اسم المستخدم أو كلمة المرور؟\nانتقل إلى "<b>"google.com/accounts/recovery"</b></string> <string name="lockscreen_glogin_checking_password" msgid="2607271802803381645">"جارٍ التحقق..."</string> - <string name="lockscreen_unlock_label" msgid="4648257878373307582">"إلغاء تأمين"</string> + <string name="lockscreen_unlock_label" msgid="4648257878373307582">"فتح قفل"</string> <string name="lockscreen_sound_on_label" msgid="1660281470535492430">"تشغيل الصوت"</string> <string name="lockscreen_sound_off_label" msgid="2331496559245450053">"الصوت متوقف"</string> <string name="lockscreen_access_pattern_start" msgid="3778502525702613399">"بدأ النمط"</string> @@ -879,8 +884,8 @@ <string name="keyguard_accessibility_widget_changed" msgid="7298011259508200234">"%1$s. الأداة %2$d من %3$d."</string> <string name="keyguard_accessibility_add_widget" msgid="8245795023551343672">"إضافة أداة."</string> <string name="keyguard_accessibility_widget_empty_slot" msgid="544239307077644480">"فارغة"</string> - <string name="keyguard_accessibility_unlock_area_expanded" msgid="7768634718706488951">"تم توسيع منطقة إلغاء القفل."</string> - <string name="keyguard_accessibility_unlock_area_collapsed" msgid="4729922043778400434">"تم تصغير منطقة إلغاء القفل."</string> + <string name="keyguard_accessibility_unlock_area_expanded" msgid="7768634718706488951">"تم توسيع منطقة فتح القفل."</string> + <string name="keyguard_accessibility_unlock_area_collapsed" msgid="4729922043778400434">"تم تصغير منطقة فتح القفل."</string> <string name="keyguard_accessibility_widget" msgid="6776892679715699875">"أداة <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string> <string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"محدد المستخدم"</string> <string name="keyguard_accessibility_status" msgid="6792745049712397237">"الحالة"</string> @@ -889,14 +894,14 @@ <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"بدأت إعادة ترتيب الأدوات."</string> <string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"انتهت إعادة ترتيب الأدوات."</string> <string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"تم حذف أداة <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string> - <string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"توسيع منطقة إلغاء القفل."</string> - <string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"إلغاء القفل باستخدام التمرير."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"إلغاء القفل باستخدام النقش."</string> + <string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"توسيع منطقة فتح القفل."</string> + <string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"فتح القفل باستخدام التمرير."</string> + <string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"فتح القفل باستخدام النقش."</string> <string name="keyguard_accessibility_face_unlock" msgid="632407612842329815">"تأمين الجهاز بالوجه."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"إلغاء القفل باستخدام رمز PIN."</string> - <string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"إلغاء قفل رقم التعريف الشخصي لشريحة SIM."</string> - <string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"إلغاء قفل مفتاح PUK لشريحة SIM."</string> - <string name="keyguard_accessibility_password_unlock" msgid="6130186108581153265">"إلغاء القفل باستخدام كلمة المرور."</string> + <string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"فتح القفل باستخدام رمز PIN."</string> + <string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"فتح قفل رقم التعريف الشخصي لشريحة SIM."</string> + <string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"فتح قفل مفتاح PUK لشريحة SIM."</string> + <string name="keyguard_accessibility_password_unlock" msgid="6130186108581153265">"فتح القفل باستخدام كلمة المرور."</string> <string name="keyguard_accessibility_pattern_area" msgid="1419570880512350689">"منطقة النقش."</string> <string name="keyguard_accessibility_slide_area" msgid="4331399051142520176">"منطقة التمرير."</string> <string name="password_keyboard_label_symbol_key" msgid="2716255580853511949">"?123"</string> @@ -1388,7 +1393,7 @@ <string name="adb_active_notification_message" msgid="5617264033476778211">"انقر لإيقاف تصحيح أخطاء الجهاز عبر USB."</string> <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"اختيار إيقاف تصحيح أخطاء USB."</string> <string name="test_harness_mode_notification_title" msgid="2282785860014142511">"تم تفعيل وضع \"مفعّل الاختبار\""</string> - <string name="test_harness_mode_notification_message" msgid="3039123743127958420">"يمكنك إجراء إعادة ضبط على إعدادات المصنع لإيقاف وضع \"مفعِّل اختبار\"."</string> + <string name="test_harness_mode_notification_message" msgid="3039123743127958420">"يمكنك إجراء إعادة ضبط على الإعدادات الأصلية لإيقاف وضع \"مفعِّل اختبار\"."</string> <string name="console_running_notification_title" msgid="6087888939261635904">"وحدة التحكّم التسلسلية مفعّلة"</string> <string name="console_running_notification_message" msgid="7892751888125174039">"الأداء متأثر. لإيقاف وحدة التحكّم، تحقّق من برنامج الإقلاع."</string> <string name="usb_contaminant_detected_title" msgid="4359048603069159678">"السوائل والشوائب في منفذ USB"</string> @@ -1398,7 +1403,7 @@ <string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"جارٍ الحصول على تقرير الخطأ…"</string> <string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"هل تريد مشاركة تقرير الخطأ؟"</string> <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"جارٍ مشاركة تقرير الخطأ…"</string> - <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"طلب المشرف الحصول على تقرير خطأ للمساعدة في تحرِّي مشكلة هذا الجهاز وإصلاحها؛ ويمكن أن تتم مشاركة التطبيقات والبيانات."</string> + <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"طلب المشرف الحصول على تقرير خطأ للمساعدة في تحديد مشكلة هذا الجهاز وحلّها؛ ويمكن أن تتم مشاركة التطبيقات والبيانات."</string> <string name="share_remote_bugreport_action" msgid="7630880678785123682">"مشاركة"</string> <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"رفض"</string> <string name="select_input_method" msgid="3971267998568587025">"اختيار أسلوب الإدخال"</string> @@ -1464,7 +1469,7 @@ <string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"للسماح لتطبيق ما بطلب حذف الحِزم."</string> <string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"طلب تجاهل تحسينات البطارية"</string> <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"للسماح للتطبيق بطلب الإذن لتجاهل تحسينات البطارية في هذا التطبيق."</string> - <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"اضغط مرتين للتحكم في التكبير/التصغير"</string> + <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"اضغط مرتين للتحكم في التكبير أو التصغير"</string> <string name="gadget_host_error_inflating" msgid="2449961590495198720">"تعذرت إضافة أداة."</string> <string name="ime_action_go" msgid="5536744546326495436">"تنفيذ"</string> <string name="ime_action_search" msgid="4501435960587287668">"بحث"</string> @@ -1667,7 +1672,7 @@ <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"شريحة SIM غير مفعّلة الآن. أدخل رمز PUK للمتابعة. اتصل بمشغل شبكة الجوال للاطلاع على التفاصيل."</string> <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"إدخال رمز رمز PIN المراد"</string> <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"تأكيد رمز رمز PIN المراد"</string> - <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"جارٍ إلغاء تأمين شريحة SIM…"</string> + <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"جارٍ فتح قفل شريحة SIM…"</string> <string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"رمز PIN غير صحيح."</string> <string name="kg_invalid_sim_pin_hint" msgid="4821601451222564077">"اكتب رقم التعريف الشخصي المكون من ٤ إلى ٨ أرقام."</string> <string name="kg_invalid_sim_puk_hint" msgid="2539364558870734339">"يجب أن يتكون رمز PUK من ۸ أرقام."</string> @@ -1684,12 +1689,12 @@ <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"لقد كتبت رمز PIN بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string> <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"لقد كتبت كلمة المرور بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"لقد رسمت نقش فتح القفل بطريقة غير صحيحة <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string> - <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"لقد حاولت إلغاء تأمين الجهاز اللوحي بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستتم إعادة تعيين الجهاز اللوحي على الإعدادات الأساسية وسيتم فقد جميع بيانات المستخدم."</string> - <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"لقد حاولت إلغاء قفل جهاز Android TV بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة أخرى غير ناجحة، ستتم إعادة ضبط جهاز Android TV على الإعداد التلقائي للمصنع وسيتم فقدان جميع بيانات المستخدمين."</string> - <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"لقد حاولت إلغاء تأمين الهاتف بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستتم إعادة تعيين الهاتف على الإعدادات الأساسية وسيتم فقد جميع بيانات المستخدم."</string> - <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"لقد حاولت إلغاء تأمين الجهاز اللوحي بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. سيتم الآن إعادة تعيين الجهاز اللوحي على الإعدادات الأساسية."</string> - <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"لقد حاولت إلغاء قفل جهاز Android TV بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم الآن إعادة ضبط جهاز Android TV على الإعداد التلقائي للمصنع."</string> - <string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"لقد حاولت إلغاء تأمين الهاتف بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. سيتم الآن إعادة تعيين الهاتف على الإعدادات الأساسية."</string> + <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="3479940221343361587">"لقد حاولت فتح قفل الجهاز اللوحي بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستتم إعادة تعيين الجهاز اللوحي على الإعدادات الأساسية وسيتم فقد جميع بيانات المستخدم."</string> + <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="9064457748587850217">"لقد حاولت فتح قفل جهاز Android TV بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة أخرى غير ناجحة، ستتم إعادة ضبط جهاز Android TV على الإعداد التلقائي للمصنع وسيتم فقدان جميع بيانات المستخدمين."</string> + <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="5955398963754432548">"لقد حاولت فتح قفل الهاتف بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستتم إعادة تعيين الهاتف على الإعدادات الأساسية وسيتم فقد جميع بيانات المستخدم."</string> + <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"لقد حاولت فتح قفل الجهاز اللوحي بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. سيتم الآن إعادة تعيين الجهاز اللوحي على الإعدادات الأساسية."</string> + <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"لقد حاولت فتح قفل جهاز Android TV بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم الآن إعادة ضبط جهاز Android TV على الإعداد التلقائي للمصنع."</string> + <string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"لقد حاولت فتح قفل الهاتف بشكل غير صحيح <xliff:g id="NUMBER">%d</xliff:g> مرة. سيتم الآن إعادة تعيين الهاتف على الإعدادات الأساسية."</string> <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستطالَب بإلغاء تأمين الجهاز اللوحي باستخدام معلومات حساب بريد إلكتروني.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string> <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة أخرى غير ناجحة، ستُطالب بإلغاء قفل جهاز Android TV باستخدام حساب بريد إلكتروني.\n\n يُرجى إعادة المحاولة بعد <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string> <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام حساب بريد إلكتروني لإلغاء تأمين الهاتف.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string> @@ -1698,6 +1703,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"هل تريد رفع مستوى الصوت فوق المستوى الموصى به؟\n\nقد يضر سماع صوت عالٍ لفترات طويلة بسمعك."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"هل تريد استخدام اختصار \"سهولة الاستخدام\"؟"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"عند تشغيل الاختصار، يؤدي الضغط على زرّي مستوى الصوت لمدة 3 ثوانٍ إلى تفعيل ميزة \"سهولة الاستخدام\".\n\n ميزة \"سهولة الاستخدام\" الحالية:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n يمكنك تغيير الميزة من \"الإعدادات\" > \"سهولة الاستخدام\"."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"فارغ"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"تعديل الاختصارات"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"إلغاء"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"إيقاف الاختصار"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استخدام الاختصار"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"عكس الألوان"</string> @@ -1973,6 +1981,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"تفعيل الملف الشخصي للعمل؟"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"سيتم تفعيل تطبيقات العمل التي تستخدمها والإشعارات والبيانات وغيرها من ميزات الملف الشخصي للعمل"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"تشغيل"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"تمّ إنشاء هذا التطبيق لإصدار قديم من Android وقد لا يعمل بشكل صحيح. جرِّب البحث عن تحديثات أو الاتصال بمطوّر البرامج."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"البحث عن تحديث"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"لديك رسائل جديدة"</string> @@ -2035,7 +2047,7 @@ <string name="autofill_save_notnow" msgid="2853932672029024195">"ليس الآن"</string> <string name="autofill_save_never" msgid="6821841919831402526">"أبدًا"</string> <string name="autofill_update_yes" msgid="4608662968996874445">"تعديل"</string> - <string name="autofill_continue_yes" msgid="7914985605534510385">"متابعة"</string> + <string name="autofill_continue_yes" msgid="7914985605534510385">"مواصلة"</string> <string name="autofill_save_type_password" msgid="5624528786144539944">"كلمة مرور"</string> <string name="autofill_save_type_address" msgid="3111006395818252885">"عنوان"</string> <string name="autofill_save_type_credit_card" msgid="3583795235862046693">"بطاقة ائتمان"</string> @@ -2087,13 +2099,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"قد تنفد طاقة البطارية قبل الشحن المعتاد"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"تم تفعيل \"توفير شحن البطارية\" لإطالة عمرها."</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"توفير شحن البطارية"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"لن يتم تفعيل ميزة \"توفير شحن البطارية\" مرة أخرى حتى تنخفض طاقة البطارية مرة أخرى."</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"وصل شحن البطارية إلى مستوى كافٍ. لن يتم تفعيل ميزة \"توفير شحن البطارية\" حتى تنخفض طاقة البطارية مرة أخرى."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"وصل مستوى شحن الهاتف إلى <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"وصل مستوى شحن الجهاز اللوحي إلى <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"وصل مستوى شحن الجهاز إلى <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"توفير شحن البطارية لا يعمل. لم تعُد الميزات مقيّدة."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"تم تفعيل \"توفير شحن البطارية\". لم تعُد الميزات مقيّدة."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 149ac6b1bd96..faa99a2aa7cd 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"আপোনাৰ কেলেণ্ডাৰ ব্যৱহাৰ কৰিব পাৰে"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"এছএমএছ"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"এছএমএছ বার্তা পঠিয়াব আৰু চাব পাৰে"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"সঞ্চয়াগাৰ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"আপোনাৰ ডিভাইচৰ ফট\', মিডিয়া আৰু ফাইলসমূহ ব্যৱহাৰ কৰিব পাৰে"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"মাইক্ৰ\'ফ\'ন"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"অডিঅ\' ৰেকর্ড কৰিব পাৰে"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"টেপ কৰা, ছোৱাইপ কৰা, পিঞ্চ কৰা আৰু আঙুলিৰ স্পৰ্শেৰে নিৰ্দেশ কৰা অন্যান্য কাৰ্যসমূহ কৰিব পাৰে।"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ফিংগাৰপ্ৰিণ্ট নিৰ্দেশ"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইচটোৰ ফিংগাৰপ্ৰিণ্ট ছেন্সৰত দিয়া নিৰ্দেশ বুজিব পাৰে।"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"স্থিতি দণ্ড অক্ষম কৰক বা সলনি কৰক"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"স্থিতি দণ্ড অক্ষম কৰিবলৈ বা ছিষ্টেম আইকন আঁতৰাবলৈ এপটোক অনুমতি দিয়ে।"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দণ্ড হ\'ব পাৰে"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"অনুমোদিত স্তৰতকৈ ওপৰলৈ ভলিউম বঢ়াব নেকি?\n\nদীৰ্ঘ সময়ৰ বাবে উচ্চ ভলিউমত শুনাৰ ফলত শ্ৰৱণ ক্ষমতাৰ ক্ষতি হ\'ব পাৰে।"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাট ব্যৱহাৰ কৰেনে?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"শ্বৰ্টকাট অন হৈ থকাৰ সময়ত দুয়োটা ভলিউম বুটামত ৩ ছেকেণ্ডৰ বাবে ছাপ দি থাকিলে দিব্যাংগসকলৰ বাবে থকা সুবিধা এটা আৰম্ভ হ\'ব। \n\n চলিত দিব্যাংগসকলৰ সুবিধা:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n আপুনি এই সুবিধাটো ছেটিংসমূহ > দিব্যাংগসকলৰ বাবে সুবিধা-লৈ গৈ সলনি কৰিব পাৰে।"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"খালী কৰক"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"শ্বৰ্টকাটসমূহ সম্পাদনা কৰক"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"বাতিল কৰক"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"শ্বৰ্টকাট অফ কৰক"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শ্বৰ্টকাট ব্যৱহাৰ কৰক"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"ৰং বিপৰীতকৰণ"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"কৰ্মস্থানৰ প্ৰ\'ফাইল অন কৰিবনে?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"আপোনাৰ কৰ্মস্থানৰ এপসমূহ, জাননীসমূহ, ডেটা আৰু কৰ্মস্থানৰ প্ৰ\'ফাইলৰ অইন সুবিধাসমূহ অন কৰা হ\'ব"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"অন কৰক"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"এই এপটো Androidৰ এটা পুৰণা সংস্কৰণৰ বাবে প্ৰস্তুত কৰা হৈছিল, আৰু ই বিচৰাধৰণে কাম নকৰিবও পাৰে। ইয়াৰ আপডে’ট আছে নেকি চাওক, বা বিকাশকৰ্তাৰ সৈতে যোগাযোগ কৰক।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"আপডে’ট আছে নেকি চাওক"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"আপুনি নতুন বার্তা লাভ কৰিছে"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"চ্চাৰ্জ কৰাৰ সচৰাচৰ সময়ৰ আগতেই বেটাৰি শেষ হ’ব পাৰে"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"বেটাৰিৰ খৰচ কমাবলৈ বেটাৰি সঞ্চয়কাৰী অন কৰা হৈছে"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"বেটাৰি সঞ্চয়কাৰী"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"বেটাৰিৰ চাৰ্জ নকমালৈকে বেটাৰি সঞ্চয়কাৰী পুনৰ সক্ৰিয় নহয়"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"বেটাৰি পৰ্যাপ্ত পৰিমাণে চাৰ্জ হৈছে। বেটাৰিৰ চাৰ্জ নকমালৈকে বেটাৰি সঞ্চয়কাৰী পুনৰ সক্ৰিয় নহয়।"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ফ’ন <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> চাৰ্জ হ’ল"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"টেবলেট <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> চাৰ্জ হ’ল"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"ডিভাইচটো <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> চাৰ্জ হ’ল"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"বেটাৰি সঞ্চয়কাৰী অফ আছে। সুবিধাবোৰ ব্যৱহাৰ কৰাত এতিয়া বাধা নাই।"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"বেটাৰি সঞ্চয়কাৰী অফ কৰা হ’ল। সুবিধাবোৰ ব্যৱহাৰ কৰাত এতিয়া বাধা নাই।"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 829b8a099c81..d97b73f79a67 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"təqvimə daxil olun"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"göndərin və SMS mesajlarına baxın"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Yaddaş"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"cihazınızda foto, media və fayllara daxil olun"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"səsi qeydə alın"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Digər jestlərə tıklaya, sürüşdürə və əməliyyat apara bilərsiniz."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Barmaq izi işarələri"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazların barmaq izi sensorunda olan işarələri əldə edə bilər."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"status panelini deaktivləşdir və ya dəyişdir"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"status paneli edin"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Səsin həcmi tövsiyə olunan səviyyədən artıq olsun?\n\nYüksək səsi uzun zaman dinləmək eşitmə qabiliyyətinizə zərər vura bilər."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Əlçatımlılıq Qısayolu istifadə edilsin?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Qısayol aktiv olduqda hər iki səs düyməsinə 3 saniyə basıb saxlamaqla əlçatımlılıq funksiyası işə başlayacaq.\n\n Cari əlçatımlılıq funksiyası:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funksiyanı Ayarlar və Əçatımlılıq bölməsində dəyişə bilərsiniz."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Boşaldın"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Qısayolları redaktə edin"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Ləğv edin"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Qısayolu Deaktiv edin"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Qısayol İstifadə edin"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Rəng İnversiyası"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"İş profili aktiv edilsin?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"İş tətbiqləri, bildirişləri, data və digər iş profili funksiyaları aktiv ediləcək"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivləşdirin"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Bu tətbiq köhnə Android versiyası üçün hazırlanıb və düzgün işləməyə bilər. Güncəlləməni yoxlayın və ya developer ilə əlaqə saxlayın."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Güncəlləməni yoxlayın"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Yeni mesajlarınız var"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batareya həmişəki vaxtdan əvvəl bitə bilər"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Enerjiyə Qənaət rejimi batareya istifadəsinin müddətini artırmaq üçün aktiv edilir"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Enerjiyə qənaət"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Enerjiyə qənaət batareya az olana qədər aktiv edilməyəcək"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Batareya kifayət qədər dolub. Enerjiyə qənaət batareya az olana qədər aktiv edilməyəcək."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Batareya <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> dolub"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Batareya <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> dolub"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Batareya <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> dolub"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Enerjiyə qənaət deaktivdir. Funksiyalar artıq məhdud deyil."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Enerjiyə qənaət deaktivdir. Funksiyalar artıq məhdud deyil."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Qovluq"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android tətbiqi"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fayl"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 790987258e36..c37e2b436393 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -290,7 +290,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"pristupi kalendaru"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"šalje i pregleda SMS poruke"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Memorijski prostor"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Datoteke i mediji"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"pristupa slikama, medijima i datotekama na uređaju"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"snima zvuk"</string> @@ -316,6 +316,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Može da dodiruje, lista, skuplja prikaz i obavlja druge pokrete."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Pokreti za otisak prsta"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Može da registruje pokrete na senzoru za otisak prsta na uređaju."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Napravi snimak ekrana"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može da napravi snimak ekrana."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmena statusne trake"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji da onemogući statusnu traku ili da dodaje i uklanja sistemske ikone."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"funkcionisanje kao statusna traka"</string> @@ -1632,6 +1634,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite da pojačate zvuk iznad preporučenog nivoa?\n\nSlušanje glasne muzike duže vreme može da vam ošteti sluh."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li da koristite prečicu za pristupačnost?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kada je prečica uključena, pritisnite oba dugmeta za jačinu zvuka da biste pokrenuli funkciju pristupačnosti.\n\n Aktuelna funkcija pristupačnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Možete da promenite funkciju u odeljku Podešavanja > Pristupačnost."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prazno"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Izmenite prečice"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Otkaži"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Isključi prečicu"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Koristi prečicu"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string> @@ -1877,6 +1882,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Da uključimo profil za Work?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Uključiće se poslovne aplikacije, obaveštenja, podaci i druge funkcije profila za Work"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string> + <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ova aplikacija je napravljena za stariju verziju Android-a, pa možda neće raditi ispravno. Potražite ažuriranja ili kontaktirajte programera."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Potraži ažuriranje"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string> @@ -1988,13 +1995,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Baterija će se možda isprazniti pre uobičajenog punjenja"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Ušteda baterije je aktivirana da bi se produžilo trajanje baterije"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Ušteda baterije"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Ušteda baterije se neće ponovo aktivirati dok baterija ne bude skoro prazna"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Baterija je napunjena do zadovoljavajućeg nivoa. Ušteda baterije se neće ponovo aktivirati dok baterija ne bude skoro prazna."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefon je napunjen <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet je napunjen <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Uređaj je napunjen <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Ušteda baterije je isključena. Funkcije više nisu ograničene."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Ušteda baterije je isključena. Funkcije više nisu ograničene."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Ušteda baterije je isključena"</string> + <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_apk" msgid="3168784749499623902">"Android aplikacija"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Datoteka"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 306934bdf6b1..855ce25ad3d1 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -293,7 +293,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"атрымліваць доступ да вашага календара"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"адпраўляць і праглядаць SMS-паведамленні"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Сховішча"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"атрымліваць доступ да фатаграфій, медыяфайлаў і файлаў на вашай прыладзе"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Мікрафон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"запісваць аўдыя"</string> @@ -319,6 +320,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Можна кранаць, праводзіць пальцам, маштабаваць шчыпком, а таксама выконваць іншыя жэсты."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Жэсты на сканеры адбіткаў пальцаў"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"адключаць ці змяняць радок стану"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"быць панэллю стану"</string> @@ -1654,6 +1659,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Павялiчыць гук вышэй рэкамендаванага ўзроўню?\n\nДоўгае праслухоўванне музыкi на вялiкай гучнасцi можа пашкодзiць ваш слых."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Выкарыстоўваць камбінацыю хуткага доступу для спецыяльных магчымасцей?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Калі камбінацыя хуткага доступу ўключана, вы можаце націснуць абедзве кнопкі гучнасці і ўтрымліваць іх 3 секунды, каб уключыць функцыю спецыяльных магчымасцей.\n\n Бягучая функцыя спецыяльных магчымасцей:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Вы можаце змяніць гэту функцыю ў меню \"Налады > Спецыяльныя магчымасці\"."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Пуста"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Змяніць ярлыкі"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Скасаваць"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Дэактываваць камбінацыю хуткага доступу"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Выкарыстоўваць камбінацыю хуткага доступу"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Інверсія колеру"</string> @@ -1909,6 +1917,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Уключыць працоўны профіль?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Будуць уключаны вашы рабочыя праграмы, апавяшчэнні, даныя і іншыя функцыі працоўнага профілю"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Уключыць"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Гэта праграма была створана для больш старой версіі Android і можа не працаваць належным чынам. Праверце наяўнасць абнаўленняў або звярніцеся да распрацоўшчыка."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Праверыць на наяўнасць абнаўленняў"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"У вас ёсць новыя паведамленні"</string> @@ -2021,13 +2033,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Акумулятар можа разрадзіцца хутчэй, чым прыйдзе час звычайнай зарадкі"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Каб павялічыць тэрмін работы акумулятара, уключаны рэжым эканоміі зараду"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Эканомія зараду"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Рэжым эканоміі зараду ўключыцца зноў, калі ў акумулятара будзе нізкі зарад"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Акумулятар зараджаны да дастатковага ўзроўню. Рэжым эканоміі зараду ўключыцца зноў, калі ў акумулятара будзе нізкі зарад."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Узровень зараду тэлефона: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Узровень зараду планшэта: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Узровень зараду прылады: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Рэжым эканоміі зараду выключаны. Функцыі больш не абмежаваны."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Рэжым эканоміі зараду выключаны. Функцыі больш не абмежаваны."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index dfa4a2f28844..40e20d3ea2e0 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"има достъп до календара ви"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"да изпраща и преглежда SMS съобщения"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Хранилище"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Файлове и мултимедия"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"да има достъп до снимките, мултимедията и файловете на устройството ви"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"записва звук"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Можете да докосвате, да прекарвате пръст, да събирате пръсти и да извършвате други жестове."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Жестове за отпечатък"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да улавя жестовете, извършени върху сензора за отпечатъци на устройството."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Създаване на екранна снимка"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да създава екранни снимки."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"деактивиране или промяна на лентата на състоянието"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"изпълняване на ролята на лента на състоянието"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да се увеличи ли силата на звука над препоръчителното ниво?\n\nПродължителното слушане при висока сила на звука може да увреди слуха ви."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Искате ли да използвате пряк път към функцията за достъпност?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Когато прекият път е включен, можете да стартирате дадена функция за достъпност, като натиснете двата бутона за промяна на силата на звука и ги задържите 3 секунди.\n\n Текущата функция за достъпност е:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Можете да промените функцията от „Настройки“ > „Достъпност“."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Празно"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Редактиране на преките пътища"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Отказ"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Изключване на прекия път"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Използване на пряк път"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Инвертиране на цветовете"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Вкл. на служ. потр. профил?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Служебните ви приложения, известия и данни, както и другите функции на служебния потребителски профил ще бъдат включени"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Включване"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Приложението не е достъпно"</string> + <string name="app_blocked_message" msgid="542972921087873023">"В момента няма достъп до <xliff:g id="APP_NAME">%1$s</xliff:g>."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Това приложение бе създадено за по-стара версия на Android и може да не работи правилно. Опитайте да проверите за актуализации или се свържете с програмиста."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверка за актуализация"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Имате нови съобщения"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батерията може да се изтощи преди обичайното зареждане"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Режимът за запазване на батерията е активиран с цел удължаване на живота на батерията"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Режим за запазване на батерията"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Режимът за запазване на батерията няма да се активира отново, докато тя пак не се изтощи"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Батерията е достатъчно заредена. Режимът за запазването й няма да се активира отново, докато тя пак не се изтощи."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Телефонът е зареден на <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Таблетът е зареден на <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Устройството е заредено на <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Режимът за запазване на батерията е изключен. Функциите вече не са ограничени."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Режимът за запазване на батерията е изключен. Функциите вече не са ограничени."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Режимът за запазване на батерията е изключен"</string> + <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_apk" msgid="3168784749499623902">"Приложение за Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Файл"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 150fc7dfdd4c..3164bb68d42f 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"আপনার ক্যালেন্ডারে অ্যাক্সেস"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"এসএমএসগুলি পাঠাতে এবং দেখতে"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"স্টোরেজ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"আপনার ডিভাইসে ফটো, মিডিয়া এবং ফাইলগুলিতে অ্যাক্সেস"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"মাইক্রোফোন"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"অডিও রেকর্ড"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"আলতো চাপ দেওয়া, সোয়াইপ, পিঞ্চ করা এবং অন্যান্য ইঙ্গিতের কাজগুলি সম্পাদন করতে পারবেন৷"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"আঙ্গুলের ছাপ সেন্সরের উপর করা জেসচার"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইসের আঙ্গুলের ছাপের সেন্সরের উপরে ইঙ্গিত করলে বুঝতে পারে।"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"স্ট্যাটাস বার নিষ্ক্রিয় অথবা সংশোধন করে"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"অ্যাপ্লিকেশনকে স্ট্যাটাস বার অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দন্ডে থাকুন"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"প্রস্তাবিত স্তরের চেয়ে বেশি উঁচুতে ভলিউম বাড়াবেন?\n\nউঁচু ভলিউমে বেশি সময় ধরে কিছু শুনলে আপনার শ্রবনশক্তির ক্ষতি হতে পারে।"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"অ্যাক্সেসযোগ্যতা শর্টকাট ব্যবহার করবেন?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"শর্টকাটটি চালু থাকলে দুটি ভলিউম বোতাম একসাথে ৩ সেকেন্ড টিপে ধরে রাখলে একটি অ্যাকসেসিবিলিটি বৈশিষ্ট্য চালু হবে।\n\n বর্তমান অ্যাকসেসিবিলিটি বৈশিষ্ট্য:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n আপনি এই বৈশিষ্ট্যটি সেটিংস > অ্যাকসেসিবিলিটিতে গিয়ে পরিবর্তন করতে পারবেন।"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"খালি"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"শর্টকাট এডিট করুন"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"বাতিল করুন"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"শর্টকাট বন্ধ করুন"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শর্টকাট ব্যবহার করুন"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"রঙ উল্টানো"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"কাজের প্রোফাইল চালু করবেন?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"আপনার কাজের অ্যাপ, বিজ্ঞপ্তি, ডেটা এবং কাজের প্রোফাইলের অন্যান্য বৈশিষ্ট্য চালু করা হবে"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"চালু করুন"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"এই অ্যাপটি Android এর একটি পুরনো ভার্সনের জন্য তৈরি করা হয়েছিল, তাই এখানে সেটি ঠিকমতো কাজ নাও করতে পারে। আপডেট পাওয়া যাচ্ছে কিনা দেখুন বা ডেভেলপারের সাথে যোগাযোগ করুন।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"আপডেট পাওয়া যাচ্ছে কিনা দেখুন"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"আপনার নতুন মেসেজ আছে"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"সাধারণত যখন চার্জ দেন, তার আগে চার্জ শেষ হয়ে যেতে পারে"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ডিভাইস বেশিক্ষণ চালু রাখতে ব্যাটারি সেভার চালু করা হয়েছে"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ব্যাটারি সেভার"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"চার্জ কম না হওয়া পর্যন্ত ব্যাটারি সেভার আবার চালু হবে না"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ব্যাটারি পর্যাপ্ত পরিমাণ চার্জ করা হয়েছে। চার্জ কম না হওয়া পর্যন্ত ব্যাটারি সেভার আবার চালু হবে না।"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ফোনে <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> চার্জ আছে"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ট্যাবলেটে <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> চার্জ আছে"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"ডিভাইসে <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> চার্জ আছে"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"ব্যাটারি সেভার বন্ধ আছে। ফিচারগুলি আর সীমাবদ্ধ নেই।"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"ব্যাটারি সেভার বন্ধ করে দেওয়া হয়েছে। ফিচারগুলি আর সীমাবদ্ধ নেই।"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 36608245b513..e0a48869b16c 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -290,7 +290,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"pristupa vašem kalendaru"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"šalje i pregleda SMS poruke"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Pohrana"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Fajlovi i mediji"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"pristupa slikama, medijskim fajlovima i fajlovima na vašem uređaju"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"snima zvuk"</string> @@ -316,6 +316,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Može dodirivati, prevlačiti, hvatati prstima i praviti druge pokrete."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Pokreti otiska prsta"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Moguće je zabilježiti pokrete na senzoru za otisak prsta uređaja."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Snimanje ekrana"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Moguće je snimiti ekran."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili mijenjanje statusne trake"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji onemogućavanje statusne trake ili dodavanje i uklanjanje sistemskih ikona."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"funkcioniranje u vidu statusne trake"</string> @@ -1634,6 +1636,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučenog nivoa?\n\nDužim slušanjem glasnog zvuka možete oštetiti sluh."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li koristiti Prečicu za pristupačnost?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kada je prečica uključena, pritiskom na oba dugmeta za podešavanje jačine zvuka u trajanju od 3 sekunde pokrenut će se funkcija za pristupačnost.\n\n Trenutna funkcija za pristupačnost je:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkciju možete promijeniti ako odete u Postavke > Pristupačnost."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prazno"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi prečice"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Otkaži"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Isključi prečicu"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Koristi prečicu"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string> @@ -1879,6 +1884,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Uključiti radni profil?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Uključit će se poslovne aplikacije, obavještenja, podaci i druge funkcije radnog profila"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string> + <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ova aplikacija je pravljena za stariju verziju Androida i možda neće ispravno raditi. Provjerite jesu li dostupna ažuriranja ili kontaktirajte programera."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Provjeri je li dostupno ažuriranje"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string> @@ -1990,13 +1997,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Moguće je da će se baterija isprazniti prije uobičajenog punjenja"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Ušteda baterije je aktivirana da bi se produžio vijek trajanja baterije"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Ušteda baterije"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Ušteda baterije se neće ponovo aktivirati dok se baterija ponovo ne isprazni"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Baterija je dovoljno napunjena. Ušteda baterije se neće ponovo aktivirati dok se baterija ponovo ne isprazni."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefon je napunjen <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet je napunjen <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Uređaj je napunjen <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Ušteda baterije je isključena. Funkcije nisu više ograničene."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Ušteda baterije je isključena. Funkcije nisu više ograničene."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Ušteda baterije je isključena"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon se dovoljno napunio. Funkcije nisu više ograničene."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet se dovoljno napunio. Funkcije nisu više ograničene."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Uređaj se dovoljno napunio. Funkcije nisu više ograničene."</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">"Fajl"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index b265f66baee3..93a60d895e8f 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"accedir al calendari"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"enviar i llegir missatges SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Emmagatzematge"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Fitxers i multimèdia"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"accedir a fotos, contingut multimèdia i fitxers del dispositiu"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Micròfon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"gravar àudio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Permet tocar, lliscar, pinçar i fer altres gestos."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos d\'empremtes dactilars"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Captura gestos realitzats en el sensor d\'empremtes dactilars del dispositiu."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fes una captura de pantalla"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pots fer una captura de la pantalla."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra d\'estat"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"aparèixer a la barra d\'estat"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vols apujar el volum per sobre del nivell recomanat?\n\nSi escoltes música a un volum alt durant períodes llargs, pots danyar-te l\'oïda."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vols fer servir la drecera d\'accessibilitat?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Si la drecera està activada, prem els dos botons de volum durant 3 segons, per iniciar una funció d\'accessibilitat.\n\n Funció d\'accessibilitat actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Pots canviar la funció a Configuració > Accessibilitat."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Buida"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edita les dreceres"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel·la"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactiva la drecera"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilitza la drecera"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversió dels colors"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Activar el perfil professional?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"S\'activaran les teves aplicacions per a la feina, les notificacions, les dades i altres funcions del perfil professional"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Activa"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"L\'aplicació no està disponible"</string> + <string name="app_blocked_message" msgid="542972921087873023">"Ara mateix, <xliff:g id="APP_NAME">%1$s</xliff:g> no està disponible."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aquesta aplicació es va crear per a una versió antiga d\'Android i pot ser que no funcioni correctament. Prova de cercar actualitzacions o contacta amb el desenvolupador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Cerca actualitzacions"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tens missatges nous"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"És possible que la bateria s\'esgoti abans de la càrrega habitual"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"S\'ha activat l\'estalvi de bateria per prolongar-ne la durada"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Estalvi de bateria"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"L\'estalvi de bateria no es tornarà a activar fins que no tornis a tenir poca bateria"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"La bateria ja està suficientment carregada. L\'estalvi de bateria no es tornarà a activar fins que no tornis a tenir poca bateria."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"El telèfon està carregat un <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tauleta carregada un <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"El dispositiu està carregat un <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"L\'estalvi de bateria s\'ha desactivat. Les funcions ja no estan restringides."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"L\'estalvi de bateria s\'ha desactivat. Les funcions ja no estan restringides."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"L\'estalvi de bateria s\'ha desactivat"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"El telèfon té prou bateria. Les funcions ja no estan restringides."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"La tauleta té prou bateria. Les funcions ja no estan restringides."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"El dispositiu té prou bateria. Les funcions ja no estan restringides."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Carpeta"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplicació d\'Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fitxer"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 806cb7e1b7f9..81b1ebb55c51 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -293,7 +293,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"přístup ke kalendáři"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"odesílání a zobrazování zpráv SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Úložiště"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Soubory a média"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"přístup k fotkám, médiím a souborům v zařízení"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"nahrávání zvuku"</string> @@ -319,6 +319,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Může provádět gesta klepnutí, přejetí, stažení prstů a další."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gesta otiskem prstu"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dokáže rozpoznat gesta zadaná na snímači otisků prstů."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pořídit snímek obrazovky"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Může pořídit snímek obrazovky."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"zakázání či změny stavového řádku"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vydávání se za stavový řádek"</string> @@ -1654,6 +1656,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšit hlasitost nad doporučenou úroveň?\n\nDlouhodobý poslech hlasitého zvuku může poškodit sluch."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použít zkratku přístupnosti?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Když je tato zkratka zapnutá, můžete funkci přístupnosti spustit tím, že na tři sekundy podržíte obě tlačítka hlasitosti.\n\n Aktuální funkce přístupnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkci můžete změnit v Nastavení > Přístupnost."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prázdné"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Upravit zkratky"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Zrušit"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Vypnout zkratku"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použít zkratku"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Převrácení barev"</string> @@ -1909,6 +1914,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Zapnout pracovní profil?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Vaše pracovní aplikace, oznámení, data a ostatní funkce pracovního účtu budou zapnuty"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Zapnout"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Aplikace není k dispozici"</string> + <string name="app_blocked_message" msgid="542972921087873023">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> v tuto chvíli není k dispozici."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Tato aplikace byla vytvořena pro starší verzi systému Android a nemusí fungovat správně. Zkuste vyhledat aktualizace, případně kontaktujte vývojáře."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Zkontrolovat aktualizace"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Máte nové zprávy"</string> @@ -2021,13 +2028,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Baterie se možná vybije před obvyklým časem nabití"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Byl aktivován spořič baterie za účelem prodloužení výdrže"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Spořič baterie"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Spořič baterie se znovu aktivuje, až bude stav baterie opět nízký"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Baterie byla nabita na dostatečnou úroveň. Spořič baterie se znovu aktivuje, až bude baterie opět téměř vybitá."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefon je nabitý na <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet je nabitý na <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Zařízení je nabito na <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Spořič baterie je vypnutý. Funkce už nejsou omezeny."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Spořič baterie je vypnutý. Funkce už nejsou omezeny."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Spořič baterie je vypnutý"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon je dostatečně nabitý. Funkce už nejsou omezeny."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet je dostatečně nabitý. Funkce už nejsou omezeny."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Zařízení je dostatečně nabité. Funkce už nejsou omezeny."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Složka"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplikace pro Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Soubor"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 81449ad5ca8a..4374b22224ed 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"have adgang til din kalender"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"Sms"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"sende og se sms-beskeder"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Lagerplads"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"få adgang til billeder, medier og filer på din enhed"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"optage lyd"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan trykke, stryge, knibe sammen og udføre andre bevægelser."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingeraftryksbevægelser"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan registrere bevægelser, der foretages på enhedens fingeraftrykslæser."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller redigere statuslinje"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vær statusbjælken"</string> @@ -358,7 +363,7 @@ <string name="permlab_systemAlertWindow" msgid="5757218350944719065">"Denne app kan vises oven på andre apps"</string> <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"Denne app kan vises oven på andre apps eller andre dele af skærmen. Dette kan forstyrre den normale brug af appen og ændre visningen af andre apps."</string> <string name="permlab_runInBackground" msgid="541863968571682785">"kør i baggrunden"</string> - <string name="permdesc_runInBackground" msgid="4344539472115495141">"Denne app kan køre i baggrunden. Dette kan aflade batteriet hurtigere."</string> + <string name="permdesc_runInBackground" msgid="4344539472115495141">"Denne app kan køre i baggrunden. Dette kan dræne batteriet hurtigere."</string> <string name="permlab_useDataInBackground" msgid="783415807623038947">"brug data i baggrunden"</string> <string name="permdesc_useDataInBackground" msgid="1230753883865891987">"Denne app kan bruge data i baggrunden. Dette kan øge dataforbruget."</string> <string name="permlab_persistentActivity" msgid="464970041740567970">"sørge for, at appen altid kører"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du skrue højere op end det anbefalede lydstyrkeniveau?\n\nDu kan skade hørelsen ved at lytte til meget høj musik over længere tid."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruge genvejen til Hjælpefunktioner?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Når genvejen er slået til, kan du starte en hjælpefunktion ved at trykke på begge lydstyrkeknapper i tre sekunder.\n\n Nuværende hjælpefunktion:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan skifte funktion i Indstillinger > Hjælpefunktioner."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tom"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediger genveje"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annuller"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Deaktiver genvej"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Brug genvej"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Ombytning af farver"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Skal arbejdsprofilen slås til?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Dine arbejdsapps, notifikationer, data og andre funktioner til din arbejdsprofil deaktiveres"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Slå til"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Denne app er lavet til en ældre version af Android og fungerer muligvis ikke korrekt. Prøv at søge efter opdateringer, eller kontakt udvikleren."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Søg efter opdatering"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nye beskeder"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Enheden løber muligvis tør for batteri, inden du normalt oplader den"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterisparefunktion er aktiveret for at forlænge batteritiden"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterisparefunktion"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Batterisparefunktion genaktiveres ikke, før batteriet er lavt igen"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Batteriet er tilstrækkeligt opladet. Batterisparefunktion genaktiveres ikke, før batteriet er lavt igen."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefonen er <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> opladet"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Denne tablet er <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> opladet"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Enheden er <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> opladet"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Batterisparefunktion er slået fra. Funktionerne er ikke længere begrænsede."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Batterisparefunktion er slået fra. Funktionerne er ikke længere begrænsede."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Mappe"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android-app"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fil"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 857cdbdcabc5..7804e9e1c127 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"auf deinen Kalender zugreifen"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS senden und abrufen"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Speicher"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"auf Fotos, Medien und Dateien auf deinem Gerät zugreifen"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"Audio aufnehmen"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Tippen, Wischen, Zusammenziehen und andere Touch-Gesten möglich."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingerabdrucksensor-Gesten"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Erfasst Touch-Gesten auf dem Fingerabdrucksensor des Geräts."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"Statusleiste deaktivieren oder ändern"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"Statusleiste darstellen"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lautstärke über den Schwellenwert anheben?\n\nWenn du über einen längeren Zeitraum Musik in hoher Lautstärke hörst, kann dies dein Gehör schädigen."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Verknüpfung für Bedienungshilfen verwenden?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Wenn die Verknüpfung aktiviert ist, kannst du die beiden Lautstärketasten drei Sekunden lang gedrückt halten, um eine Bedienungshilfe zu starten.\n\n Aktuelle Bedienungshilfe:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kannst die Bedienungshilfe unter \"Einstellungen\" > \"Bedienungshilfen\" ändern."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Leeren"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Verknüpfungen bearbeiten"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Abbrechen"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Verknüpfung deaktivieren"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Verknüpfung verwenden"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Farbumkehr"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Arbeitsprofil aktivieren?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Deine geschäftlichen Apps, Benachrichtigungen, Daten und andere Funktionen des Arbeitsprofils werden aktiviert"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivieren"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Diese App wurde für eine ältere Android-Version entwickelt und funktioniert möglicherweise nicht mehr richtig. Prüfe, ob Updates verfügbar sind oder kontaktiere den Entwickler."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Auf Updates prüfen"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Du hast neue Nachrichten"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Dein Akku könnte vor der gewöhnlichen Ladezeit leer sein"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Energiesparmodus aktiviert, um die Akkulaufzeit zu verlängern"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Energiesparmodus"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Energiesparmodus wird erst bei niedrigem Ladestand wieder aktiviert"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Der Akku ist jetzt ausreichend aufgeladen. Der Energiesparmodus wird erst wieder bei schwachem Ladestand aktiviert."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Ladestand deines Smartphones: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Ladestand Tablet: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Ladestand des Geräts: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Energiesparmodus ist deaktiviert. Es sind keine Funktionen mehr beschränkt."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Energiesparmodus deaktiviert. Es sind keine Funktionen mehr beschränkt."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Ordner"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android-App"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Datei"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 817df16b6c3a..a5977ee082d3 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"έχει πρόσβαση στο ημερολόγιό σας"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"στέλνει και να διαβάζει μηνύματα SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Αποθηκευτικός χώρος"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Αρχεία και μέσα"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"έχει πρόσβαση στις φωτογραφίες/πολυμέσα/αρχεία στη συσκευή σας"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Μικρόφωνο"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ηχογραφεί"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Επιτρέπει το πάτημα, την ολίσθηση, το πλησίασμα και άλλες κινήσεις."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Κινήσεις δακτυλικών αποτυπωμάτων"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικού αποτυπώματος της συσκευής."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Λήψη στιγμιότυπου οθόνης"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Μπορεί να τραβήξει στιγμιότυπο της οθόνης."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ορίζεται ως γραμμή κατάστασης"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Αυξάνετε την ένταση ήχου πάνω από το επίπεδο ασφαλείας;\n\nΑν ακούτε μουσική σε υψηλή ένταση για μεγάλο χρονικό διάστημα ενδέχεται να προκληθεί βλάβη στην ακοή σας."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Να χρησιμοποιείται η συντόμευση προσβασιμότητας;"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Όταν η συντόμευση είναι ενεργοποιημένη, το πάτημα και των δύο κουμπιών έντασης ήχου για 3 δευτερόλεπτα θα ξεκινήσει μια λειτουργία προσβασιμότητας.\n\n Τρέχουσα λειτουργία προσβασιμότητας:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Μπορείτε να αλλάξετε τη λειτουργία από τις Ρυθμίσεις > Προσβασιμότητα."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Κενό"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Επεξεργασία συντομεύσεων"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Άκυρο"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Απενεργοποίηση συντόμευσης"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Χρήση συντόμευσης"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Αντιστροφή χρωμάτων"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Ενεργοποίηση προφίλ εργασίας;"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Οι εφαρμογές, οι ειδοποιήσεις και τα δεδομένα εργασίας σας, καθώς και άλλες λειτουργίες του προφίλ εργασίας, θα ενεργοποιηθούν"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Ενεργοποίηση"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Η εφαρμογή δεν είναι διαθέσιμη"</string> + <string name="app_blocked_message" msgid="542972921087873023">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν είναι διαθέσιμη αυτήν τη στιγμή."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Αυτή η εφαρμογή δημιουργήθηκε για παλαιότερη έκδοση του Android και μπορεί να μην λειτουργεί σωστά. Δοκιμάστε να ελέγξετε εάν υπάρχουν ενημερώσεις ή επικοινωνήστε με τον προγραμματιστή."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Έλεγχος για ενημέρωση"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Έχετε νέα μηνύματα"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Η μπαταρία μπορεί να εξαντληθεί πριν από τη συνηθισμένη φόρτιση"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Η Εξοικονόμηση μπαταρίας ενεργοποιήθηκε για την επέκταση της διάρκειας ζωής της μπαταρίας"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Εξοικονόμηση μπαταρίας"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Η Εξοικονόμηση μπαταρίας δεν θα ενεργοποιηθεί ξανά προτού η στάθμη της μπαταρίας είναι ξανά χαμηλή"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Η μπαταρία φορτίστηκε σε επαρκές επίπεδο. Η Εξοικονόμηση μπαταρίας δεν θα ενεργοποιηθεί ξανά προτού η στάθμη της μπαταρίας είναι ξανά χαμηλή."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Το τηλέφωνο <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> φορτίστηκε"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Επίπεδο φόρτισης tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Η συσκευή <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> φορτίστηκε"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Η Εξοικονόμηση μπαταρίας είναι ανενεργή. Οι λειτουργίες δεν περιορίζονται πλέον."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Η Εξοικονόμηση μπαταρίας απενεργοποιήθηκε. Οι λειτουργίες δεν περιορίζονται πλέον."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Η Εξοικονόμηση μπαταρίας απενεργοποιήθηκε"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Το τηλέφωνο είναι αρκετά φορτισμένο. Οι λειτουργίες δεν περιορίζονται πλέον."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Το tablet είναι αρκετά φορτισμένο. Οι λειτουργίες δεν περιορίζονται πλέον."</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_apk" msgid="3168784749499623902">"Εφαρμογή Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Αρχείο"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 33a84883c791..da897933675e 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"access your calendar"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"send and view SMS messages"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Storage"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Files and media"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"access photos, media and files on your device"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microphone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"record audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Can tap, swipe, pinch and perform other gestures."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingerprint gestures"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings > Accessibility."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Empty"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Turn on work profile?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Your work apps, notifications, data and other work profile features will be turned on"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Battery may run out before usual charge"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Battery Saver activated to extend battery life"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Battery Saver won’t reactivate until battery low again"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Battery has been charged to a sufficient level. Battery Saver won’t reactivate until the battery is low again."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Phone <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Device <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Battery Saver is off. Features no longer restricted."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Battery Saver turned off. Features no longer restricted."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Device has enough charge. Features no longer restricted."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android application"</string> <string name="mime_type_generic" msgid="4606589110116560228">"File"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index b2ba41946f0b..560c4cd13061 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"access your calendar"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"send and view SMS messages"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Storage"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Files and media"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"access photos, media and files on your device"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microphone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"record audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Can tap, swipe, pinch and perform other gestures."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingerprint gestures"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings > Accessibility."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Empty"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Turn on work profile?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Your work apps, notifications, data and other work profile features will be turned on"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Battery may run out before usual charge"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Battery Saver activated to extend battery life"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Battery Saver won’t reactivate until battery low again"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Battery has been charged to a sufficient level. Battery Saver won’t reactivate until the battery is low again."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Phone <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Device <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Battery Saver is off. Features no longer restricted."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Battery Saver turned off. Features no longer restricted."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Device has enough charge. Features no longer restricted."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android application"</string> <string name="mime_type_generic" msgid="4606589110116560228">"File"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 33a84883c791..da897933675e 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"access your calendar"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"send and view SMS messages"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Storage"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Files and media"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"access photos, media and files on your device"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microphone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"record audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Can tap, swipe, pinch and perform other gestures."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingerprint gestures"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings > Accessibility."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Empty"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Turn on work profile?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Your work apps, notifications, data and other work profile features will be turned on"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Battery may run out before usual charge"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Battery Saver activated to extend battery life"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Battery Saver won’t reactivate until battery low again"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Battery has been charged to a sufficient level. Battery Saver won’t reactivate until the battery is low again."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Phone <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Device <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Battery Saver is off. Features no longer restricted."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Battery Saver turned off. Features no longer restricted."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Device has enough charge. Features no longer restricted."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android application"</string> <string name="mime_type_generic" msgid="4606589110116560228">"File"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 33a84883c791..da897933675e 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"access your calendar"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"send and view SMS messages"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Storage"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Files and media"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"access photos, media and files on your device"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microphone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"record audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Can tap, swipe, pinch and perform other gestures."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingerprint gestures"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings > Accessibility."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Empty"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Turn on work profile?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Your work apps, notifications, data and other work profile features will be turned on"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Battery may run out before usual charge"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Battery Saver activated to extend battery life"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Battery Saver won’t reactivate until battery low again"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Battery has been charged to a sufficient level. Battery Saver won’t reactivate until the battery is low again."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Phone <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Device <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Battery Saver is off. Features no longer restricted."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Battery Saver turned off. Features no longer restricted."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Device has enough charge. Features no longer restricted."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android application"</string> <string name="mime_type_generic" msgid="4606589110116560228">"File"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index e256605e61f0..f7da05ec2a7a 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"access your calendar"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"send and view SMS messages"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Storage"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Files and media"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"access photos, media, and files on your device"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microphone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"record audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Can tap, swipe, pinch, and perform other gestures."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingerprint gestures"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings > Accessibility."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Empty"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancel"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Turn off Shortcut"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Color Inversion"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Turn on work profile?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Your work apps, notifications, data, and other work profile features will be turned on"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates, or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Battery may run out before usual charge"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Battery Saver activated to extend battery life"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Battery Saver won’t reactivate until battery low again"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Battery has been charged to a sufficient level. Battery Saver won’t reactivate until the battery is low again."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Phone <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Device <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> charged"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Battery Saver is off. Features no longer restricted."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Battery Saver turned off. Features no longer restricted."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver turned off"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Phone has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet has enough charge. Features no longer restricted."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Device has enough charge. Features no longer restricted."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android application"</string> <string name="mime_type_generic" msgid="4606589110116560228">"File"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index ad861f255e4d..aeec9f8dc446 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"acceder al calendario"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"enviar y ver mensajes SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Almacenamiento"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Archivos y contenido multimedia"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"acceder a las fotos, el contenido multimedia y los archivos"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Micrófono"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"grabar audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Permite presionar, deslizar, pellizcar y usar otros gestos."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos del sensor de huellas digitales"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Captura los gestos que se hacen en el sensor de huellas digitales del dispositivo."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tomar captura de pantalla"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede tomar una captura de la pantalla."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra de estado"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar a un alto volumen durante largos períodos puede dañar tu audición."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Usar acceso directo de accesibilidad?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Cuando el acceso directo está activado, puedes presionar los botones de volumen durante 3 segundos para iniciar una función de accesibilidad.\n\n Función de accesibilidad actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puedes cambiar la función en Configuración > Accesibilidad."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Vacío"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactivar acceso directo"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar acceso directo"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de color"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"¿Activar el perfil de trabajo?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Se activaran las apps de trabajo, los datos, las notificaciones y otras funciones del perfil de trabajo"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"La app no está disponible"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible en este momento."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta app se creó para una versión anterior de Android y es posible que no funcione correctamente. Busca actualizaciones o comunícate con el programador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualización"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tienes mensajes nuevos"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Es posible que la batería se agote antes de la carga habitual"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Se activó el Ahorro de batería para extender la duración de la batería"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Ahorro de batería"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"El Ahorro de batería no se volverá a activar hasta que la batería esté baja otra vez"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"La batería tiene suficiente carga. El Ahorro de batería no se volverá a activar hasta que la batería esté baja otra vez."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Nivel de batería: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Nivel de batería de la tablet: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Nivel de batería del dispositivo: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"El Ahorro de batería está desactivado. Ya no se restringen las funciones."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Se desactivó el Ahorro de batería. Ya no se restringen las funciones."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Se desactivó el Ahorro de batería"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"El teléfono tiene suficiente carga. Ya no se restringen las funciones."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"La tablet tiene suficiente carga. Ya no se restringen las funciones."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"El dispositivo tiene suficiente carga. Ya no se restringen las funciones."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Carpeta"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplicación de Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Archivo"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 9c64369bced3..1ef891acffb5 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"acceder a tu calendario"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"enviar y ver mensajes SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Almacenamiento"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Archivos y contenido multimedia"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"acceder a fotos, contenido multimedia y archivos de tu dispositivo"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Micrófono"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"grabar audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Puedes tocar y pellizcar la pantalla, deslizar el dedo y hacer otros gestos."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos de huellas digitales"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Puede capturar los gestos realizados en el sensor de huellas digitales del dispositivo."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Hacer captura de pantalla"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede hacer capturas de la pantalla."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"inhabilitar o modificar la barra de estado"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar sonidos fuertes durante mucho tiempo puede dañar los oídos."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Utilizar acceso directo de accesibilidad?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Si el acceso directo está activado, pulsa los dos botones de volumen durante tres segundos para iniciar una función de accesibilidad.\n\n Función de accesibilidad actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puedes cambiar la función en Ajustes > Accesibilidad."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Vacío"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactivar acceso directo"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar acceso directo"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de color"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"¿Activar el perfil de trabajo?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Tus aplicaciones, notificaciones, datos y otras funciones del perfil de trabajo se activarán"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"La aplicación no está disponible"</string> + <string name="app_blocked_message" msgid="542972921087873023">"En estos momentos, <xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta aplicación se ha diseñado para una versión anterior de Android y es posible que no funcione correctamente. Busca actualizaciones o ponte en contacto con el desarrollador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualizaciones"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tienes mensajes nuevos"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Es posible que te quedes sin batería antes de lo habitual"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Se ha activado el ahorro de batería para aumentar la duración de la batería"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Ahorro de batería"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"El modo Ahorro de batería no se activará hasta que la batería vuelva a estar baja"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"La batería se ha cargado lo suficiente. El modo Ahorro de batería no se activará hasta que la batería vuelva a estar baja."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Nivel de la batería del teléfono: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Nivel de batería del tablet: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Nivel de la batería del dispositivo: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Ahorro de batería desactivado. Las funciones ya no están restringidas."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Ahorro de batería desactivado. Las funciones ya no están restringidas."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Ahorro de batería desactivado"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"El teléfono tiene suficiente batería. Las funciones ya no están restringidas."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"El tablet tiene suficiente batería. Las funciones ya no están restringidas."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"El dispositivo tiene suficiente batería. Las funciones ya no están restringidas."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Carpeta"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplicación de Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Archivo"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index c9e74b3f9bae..9a4b6d376bf2 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"juurdepääs kalendrile"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"saata ja vaadata SMS-sõnumeid"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Mäluruum"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"juurdepääs seadmesse salvestatud fotodele, meediasisule ja failidele"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"heli salvestamine"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Saate puudutada, pühkida, sõrmi kokku-lahku liigutada ja teisi liigutusi teha."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Sõrmejälje liigutused"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Teil on võimalik jäädvustada seadme sõrmejäljeanduril tehtud liigutused."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"keela või muuda olekuriba"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"olekuribana kuvamine"</string> @@ -1454,7 +1459,7 @@ <string name="sync_really_delete" msgid="5657871730315579051">"Kustuta üksused"</string> <string name="sync_undo_deletes" msgid="5786033331266418896">"Võtke kustutamised tagasi"</string> <string name="sync_do_nothing" msgid="4528734662446469646">"Ära tee praegu midagi"</string> - <string name="choose_account_label" msgid="5557833752759831548">"Konto valimine"</string> + <string name="choose_account_label" msgid="5557833752759831548">"Valige konto"</string> <string name="add_account_label" msgid="4067610644298737417">"Konto lisamine"</string> <string name="add_account_button_label" msgid="322390749416414097">"Lisa konto"</string> <string name="number_picker_increment_button" msgid="7621013714795186298">"Suurendamine"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Kas suurendada helitugevuse taset üle soovitatud taseme?\n\nPikaajaline valju helitugevusega kuulamine võib kuulmist kahjustada."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Kas kasutada juurdepääsetavuse otseteed?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kui otsetee on sisse lülitatud, käivitab mõlema helitugevuse nupu kolm sekundit all hoidmine juurdepääsetavuse funktsiooni.\n\n Praegune juurdepääsetavuse funktsioon:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Saate seda funktsiooni muuta valikutega Seaded > Juurdepääsetavus."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tühi"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muuda otseteid"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Tühista"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Lülita otsetee välja"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kasuta otseteed"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Värvide ümberpööramine"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Kas lülitada tööprofiil sisse?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Teie töörakendused, märguanded, andmed ja muud tööprofiili funktsioonid lülitatakse sisse"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Lülita sisse"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"See rakendus on loodud Androidi vanema versiooni jaoks ega pruugi õigesti töötada. Otsige värskendusi või võtke ühendust arendajaga."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Otsi värskendust"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Teile on uusi sõnumeid"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Aku võib enne tavapärast laadimist tühjaks saada"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Akusäästja aktiveeriti aku tööea pikendamiseks"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akusäästja"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Akusäästja lülitatakse uuesti sisse, kui aku hakkab tühjaks saama"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Aku on piisavalt laetud. Akusäästja lülitatakse uuesti sisse, kui aku hakkab tühjaks saama."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefon on <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> laetud"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tahvelarvuti on <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> laetud"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Seade on <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> laetud"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Akusäästja on välja lülitatud. Funktsioonid ei ole enam piiratud."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Akusäästja on välja lülitatud. Funktsioonid ei ole enam piiratud."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Kaust"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Androidi rakendus"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fail"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index cae6b9986582..f0a0010cc584 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"atzitu egutegia"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS mezuak"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"bidali eta ikusi SMS mezuak"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Memoria"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"atzitu gailuko argazkiak, multimedia-edukia eta fitxategiak"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofonoa"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"grabatu audioa"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Sakatu, lerratu, atximurkatu eta beste hainbat keinu egin ditzake."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Hatz-marken keinuak"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Gailuaren hatz-marken sentsorean egindako keinuak atzeman ditzake."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"desgaitu edo aldatu egoera-barra"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"bihurtu egoera-barra"</string> @@ -1306,7 +1311,7 @@ <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Erantsitako gailua ez da telefono honekin bateragarria. Sakatu informazio gehiago lortzeko."</string> <string name="adb_active_notification_title" msgid="408390247354560331">"USB bidezko arazketa konektatuta"</string> <string name="adb_active_notification_message" msgid="5617264033476778211">"Sakatu USB bidezko arazketa desaktibatzeko"</string> - <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Hautatu USB arazketa desgaitzeko."</string> + <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Hautatu USB bidezko arazketa desgaitzeko."</string> <string name="test_harness_mode_notification_title" msgid="2282785860014142511">"Proba-materialeko modua gaitu da"</string> <string name="test_harness_mode_notification_message" msgid="3039123743127958420">"Proba-materialaren modua desgaitzeko, berrezarri jatorrizko datuak."</string> <string name="console_running_notification_title" msgid="6087888939261635904">"Serie-kontsola gaituta dago"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bolumena gomendatutako mailatik gora igo nahi duzu?\n\nMusika bolumen handian eta denbora luzez entzuteak entzumena kalte diezazuke."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erabilerraztasun-lasterbidea erabili nahi duzu?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea.\n\n Uneko erabilerraztasun-eginbidea:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Eginbidea aldatzeko, joan Ezarpenak > Erabilerraztasuna atalera."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Hustu"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editatu lasterbideak"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Utzi"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desaktibatu lasterbidea"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Erabili lasterbidea"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Koloreen alderantzikatzea"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Laneko profila aktibatu?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Laneko aplikazioak, jakinarazpenak, datuak eta laneko profileko bestelako eginbideak aktibatuko dira"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktibatu"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aplikazioa Android-en bertsio zaharrago baterako sortu zenez, baliteke behar bezala ez funtzionatzea. Bilatu eguneratzerik baden, edo jarri garatzailearekin harremanetan."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Bilatu eguneratzeak"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Mezu berriak dituzu"</string> @@ -1874,7 +1886,7 @@ <string name="app_category_maps" msgid="6395725487922533156">"Mapak eta nabigazioa"</string> <string name="app_category_productivity" msgid="1844422703029557883">"Produktibitatea"</string> <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"Gailuaren memoria"</string> - <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB arazketa"</string> + <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB bidezko arazketa"</string> <string name="time_picker_hour_label" msgid="4208590187662336864">"ordu"</string> <string name="time_picker_minute_label" msgid="8307452311269824553">"minutu"</string> <string name="time_picker_header_text" msgid="9073802285051516688">"Ezarri ordua"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Baliteke bateria ohi baino lehenago agortzea"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Bateria-aurrezlea aktibatuta dago bateriaren iraupena luzatzeko"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Bateria-aurrezlea"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Bateria-aurrezlea ez da aktibatuko berriro bateria gutxi gelditzen den arte"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Kargatu da behar adina bateria. Bateria-aurrezlea ez da aktibatuko berriro bateria gutxi gelditzen den arte."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefonoaren bateria: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tabletaren bateria: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Gailuaren bateria: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Desaktibatu egin da bateria-aurrezlea. Jada ez dago eginbiderik murriztuta."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Desaktibatu egin da bateria-aurrezlea. Jada ez dago eginbiderik murriztuta."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Karpeta"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android-erako aplikazioa"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fitxategia"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index b45c6f92fe56..7d122216b10a 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"دسترسی به تقویم شما"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"پیامک"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"ارسال و مشاهده پیامکها"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"حافظه"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"دسترسی به عکسها، رسانهها و فایلهای روی دستگاهتان"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"میکروفن"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ضبط صدا"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"میتوانید ضربه بزنید، انگشتتان را تند بکشید، انگشتانتان را به هم نزدیک یا از هم دور کنید و اشارههای دیگری اجرا کنید."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"اشارههای اثر انگشت"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"میتواند اشارههای اجراشده روی حسگر اثرانگشت دستگاه را ثبت کند."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"غیرفعال کردن یا تغییر نوار وضعیت"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"به برنامه اجازه میدهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"نوار وضعیت باشد"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"میزان صدا را به بالاتر از حد توصیه شده افزایش میدهید؟\n\nگوش دادن به صداهای بلند برای مدت طولانی میتواند به شنواییتان آسیب وارد کند."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"از میانبر دسترسپذیری استفاده شود؟"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"وقتی میانبر روشن است، اگر هر دو دکمه صدا را ۳ ثانیه فشار دهید یکی از قابلیتهای دسترسپذیری شروع میشود.\n\n قابلیت دسترسپذیری کنونی:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n میتوانید در «تنظیمات > دسترسپذیری»، قابلیت را تغییر دهید."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"خالی"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ویرایش میانبرها"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"لغو"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"خاموش کردن میانبر"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استفاده از میانبر"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"وارونگی رنگ"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"نمایه کاری روشن شود؟"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"برنامهها، اعلانها، دادهها و سایر قابلیتهای نمایه کاری شما روشن خواهد شد"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"روشن کردن"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"این برنامه برای نسخه قدیمیتری از Android ساخته شده است و ممکن است درست کار نکند. وجود بهروزرسانی را بررسی کنید یا با برنامهنویس تماس بگیرید."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"بررسی وجود بهروزرسانی"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"پیامهای جدیدی دارید"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ممکن است شارژ باتری قبل از شارژ معمول تمام شود"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"جهت افزایش عمر باتری، «بهینهسازی باتری» فعال شد"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"بهینهسازی باتری"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"تا وقتی شارژ باتری دوباره به سطح پایین نرسد، «بهینهسازی باتری» مجدداً فعال نخواهد شد"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"باتری درحد کافی شارژ شده است. تا وقتی شارژ باتری دوباره به سطح پایین نرسد، «بهینهسازی باتری» مجدداً فعال نخواهد شد."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"تلفن <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> شارژ شد"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"رایانه لوحی <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> شارژ شد"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"دستگاه <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> شارژ شد"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"«بهینهسازی باتری» خاموش است. ویژگیها دیگر محدود نمیشوند."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"«بهینهسازی باتری» خاموش شد. ویژگیها دیگر محدود نمیشوند."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index c1df18e23839..ba39b8c2ca64 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"käyttää kalenteria"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"Tekstiviestit"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"lähettää ja tarkastella tekstiviestejä"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Tallennustila"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"käyttää laitteellesi tallennettuja valokuvia, mediatiedostoja ja muita tiedostoja"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofoni"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"tallentaa ääntä"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Lupa napauttaa, pyyhkäistä, nipistää ja käyttää muita eleitä."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Sormenjälkieleet"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Voi tallentaa laitteen sormenjälkitunnistimelle tehtyjä eleitä."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"sijaita tilapalkissa"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Nostetaanko äänenvoimakkuus suositellun tason yläpuolelle?\n\nPitkäkestoinen kova äänenvoimakkuus saattaa heikentää kuuloa."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Käytetäänkö esteettömyyden pikanäppäintä?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kun pikanäppäin on käytössä, voit käynnistää esteettömyystoiminnon pitämällä molempia äänenvoimakkuuspainikkeita painettuna kolmen sekunnin ajan.\n\n Tällä hetkellä valittu esteettömyystoiminto:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Voit vaihtaa toimintoa valitsemalla Asetukset > Esteettömyys."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tyhjennä"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muokkaa pikakuvakkeita"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Peruuta"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Poista pikanäppäin käytöstä"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Käytä pikanäppäintä"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Käänteiset värit"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Otetaanko työprofiili käyttöön?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Työsovellukset, ‑ilmoitukset, ‑tiedot ja muut työprofiiliominaisuudet otetaan käyttöön"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Ota käyttöön"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Tämä sovellus on suunniteltu vanhemmalle Android-versiolle eikä välttämättä toimi oikein. Kokeile tarkistaa päivitykset tai ottaa yhteyttä kehittäjään."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tarkista päivitykset"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Sinulle on uusia viestejä"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akku saattaa loppua ennen normaalia latausaikaa"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Virransäästö otettu käyttöön akunkeston pidentämiseksi"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Virransäästö"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Virransäästö aktivoituu uudelleen vasta, kun akku on lähes tyhjä"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Akun varaus on riittävä. Virransäästö aktivoituu uudelleen vasta, kun akku on lähes tyhjä."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Puhelin <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ladattu"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tabletti <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ladattu"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Laite <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ladattu"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Virransäästö ei ole käytössä. Ominaisuuksia ei enää rajoiteta."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Virransäästö poistettiin käytöstä. Ominaisuuksia ei enää rajoiteta."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Kansio"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android-sovellus"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Tiedosto"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 9f2647d026e3..8df6ad6ed41b 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"accéder à votre agenda"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"Messagerie texte"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"envoyer et afficher des messages texte"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Stockage"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"accéder aux photos, aux contenus multimédias et aux fichiers sur votre appareil"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microphone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"enregistrer des fichiers audio"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Peut toucher, balayer, pincer et effectuer d\'autres gestes."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestes sur le capteur d\'empreintes digitales"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut capturer des gestes effectués sur le capteur d\'empreintes digitales de l\'appareil."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"désactiver ou modifier la barre d\'état"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"servir de barre d\'état"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au-dessus du niveau recommandé?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité.\n\n Fonctionnalité d\'accessibilité utilisée actuellement :\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Vous pouvez changer de fonctionnalité sous Paramètres > Accessibilité."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Vide"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annuler"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Désactiver le raccourci"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utiliser le raccourci"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversion des couleurs"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Activer le profil professionnel?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Vos applications professionnelles, vos notifications, vos données et les autres fonctionnalités de profil professionnel seront activées"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Activer"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Cette application a été conçue pour une ancienne version d\'Android et pourrait ne pas fonctionner correctement. Essayez de vérifier les mises à jour ou communiquez avec son concepteur."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Vérifier la présence de mises à jour"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Vous avez de nouveaux messages"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"La pile pourrait s\'épuiser avant la charge habituelle"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Le mode Économiseur de pile est activé afin de prolonger l\'autonomie"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Économiseur de pile"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Le mode Économiseur de pile ne se réactivera seulement lorsque la pile deviendra faible à nouveau"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"La pile a été suffisamment chargée. Le mode Économiseur de pile ne se réactivera seulement lorsque la pile deviendra faible à nouveau."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Téléphone chargé à <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablette chargée à <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Appareil chargé à <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Le mode Économiseur de pile est désactivé. Ces fonctionnalités ne sont plus restreintes."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Le mode Économiseur de pile est désactivé. Ces fonctionnalités ne sont plus restreintes."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Dossier"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Application Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fichier"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 7d8065363eb4..a64066a07818 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"accéder à votre agenda"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"envoyer et consulter des SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Stockage"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Fichiers et contenus multimédias"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"accéder aux photos, contenus multimédias et fichiers sur votre appareil"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microphone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"enregistrer des fichiers audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Permet d\'appuyer sur l\'écran, de le balayer, de le pincer et d\'effectuer d\'autres gestes."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestes avec l\'empreinte digitale"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut enregistrer des gestes effectués sur le lecteur d\'empreinte digitale de l\'appareil."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre des captures d\'écran."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"Désactivation ou modification de la barre d\'état"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"remplacer la barre d\'état"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au dessus du niveau recommandé ?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité ?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité.\n\n Fonctionnalité d\'accessibilité utilisée actuellement :\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Vous pouvez changer de fonctionnalité dans Paramètres > Accessibilité."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Vider"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annuler"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Désactiver le raccourci"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utiliser le raccourci"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversion des couleurs"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Activer profil professionnel ?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Vos applications professionnelles, notifications, données et d\'autres fonctionnalités de votre profil professionnel seront activées"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Activer"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Application non disponible"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas disponible pour le moment."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Cette application a été conçue pour une ancienne version d\'Android et risque de ne pas fonctionner correctement. Recherchez des mises à jour ou contactez le développeur."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Rechercher une mise à jour"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Vous avez de nouveaux messages"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Vous risquez d\'être à court de batterie plus tôt que prévu"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Économiseur de batterie activé pour prolonger l\'autonomie"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Économiseur de batterie"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"L\'économiseur d\'écran ne se réactivera que lorsque le niveau de la batterie sera à nouveau faible"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Le niveau de charge de la batterie est suffisant. L\'économiseur de batterie ne se réactivera que lorsque le niveau de la batterie sera à nouveau faible."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Téléphone chargé à <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablette chargée à <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Appareil chargé à <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Économiseur de batterie désactivé. Les fonctionnalités ne sont plus restreintes."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Économiseur de batterie désactivé. Les fonctionnalités ne sont plus restreintes."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Économiseur de batterie désactivé"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Téléphone suffisamment chargé. Les fonctionnalités ne sont plus restreintes."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablette suffisamment chargée. Les fonctionnalités ne sont plus restreintes."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Appareil suffisamment chargé. Les fonctionnalités ne sont plus restreintes."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Dossier"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Application Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fichier"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index eebe5ab20185..df08abc861ec 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"acceder ao teu calendario"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"enviar e consultar mensaxes de SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Almacenamento"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Ficheiros e contido multimedia"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"acceder a fotos, contido multimedia e ficheiros no teu dispositivo"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Micrófono"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"gravar audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Podes tocar, pasar o dedo, beliscar e realizar outros xestos."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Xestos de impresión dixital"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode rexistrar os xestos realizados no sensor de impresión dixital do dispositivo."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Facer captura de pantalla"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode facer capturas de pantalla."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"desactivar ou modificar a barra de estado"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite á aplicación desactivar a barra de estado ou engadir e eliminar as iconas do sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"actuar como a barra de estado"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Queres subir o volume máis do nivel recomendado?\n\nA reprodución de son a un volume elevado durante moito tempo pode provocar danos nos oídos."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Queres utilizar o atallo de accesibilidade?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Cando o atallo está activado, podes premer os dous botóns de volume durante 3 segundos para iniciar unha función de accesibilidade.\n\n Función de accesibilidade actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Podes cambiar a función en Configuración > Accesibilidade."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Baleirar"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atallos"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactivar atallo"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atallo"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de cor"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Activar o perfil de traballo?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Activaranse as túas aplicacións de traballo, as notificacións, os datos e outras funcións do perfil de traballo"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"A aplicación non está dispoñible"</string> + <string name="app_blocked_message" msgid="542972921087873023">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> non está dispoñible neste momento."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta aplicación deseñouse para unha versión anterior de Android e quizais non funcione correctamente. Proba a buscar actualizacións ou contacta co programador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualización"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tes mensaxes novas"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"A batería pode esgotarse antes do habitual"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Para ampliar a duración da batería activouse a función Aforro de batería"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Aforro de batería"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"A función Aforro de batería non se activará de novo ata que volva quedar pouca batería"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"A batería cargouse ata un nivel suficiente. A función Aforro de batería non se activará de novo ata que volva quedar pouca batería."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Nivel de batería do teléfono: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Nivel de batería da tableta: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Nivel de batería do dispositivo: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"A función Aforro de batería está desactivada. Xa non se restrinxirá ningunha función."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Desactivouse a función Aforro de batería. Xa non se restrinxirá ningunha función."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Desactivouse a función Aforro de batería."</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"O teléfono non ten suficiente batería. Xa non se restrinxirán as funcións."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"A tableta non ten suficiente batería. Xa non se restrinxirán as funcións."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"O dispositivo non ten suficiente batería. Xa non se restrinxirán as funcións."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Cartafol"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplicación Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Ficheiro"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 869a7528dda6..f663b87492e4 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -247,7 +247,7 @@ <string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"એરપ્લેન મોડ"</string> <string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"એરપ્લેન મોડ ચાલુ છે."</string> <string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"એરપ્લેન મોડ બંધ છે."</string> - <string name="global_action_settings" msgid="4671878836947494217">"સેટિંગ્સ"</string> + <string name="global_action_settings" msgid="4671878836947494217">"સેટિંગ"</string> <string name="global_action_assist" msgid="2517047220311505805">"સહાય"</string> <string name="global_action_voice_assist" msgid="6655788068555086695">"વૉઇસ સહાય"</string> <string name="global_action_lockdown" msgid="2475471405907902963">"લૉકડાઉન"</string> @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"તમારા કેલેન્ડરને ઍક્સેસ કરવાની"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS સંદેશા મોકલવાની અને જોવાની"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"સ્ટોરેજ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"તમારા ઉપકરણ પર ફોટો, મીડિયા અને ફાઇલો ઍક્સેસ કરવાની"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"માઇક્રોફોન"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ઑડિઓ રેકોર્ડ કરવાની"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ટૅપ, સ્વાઇપ, પિંચ કરી અને અન્ય હાવભાવ કરી શકે છે."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ફિંગરપ્રિન્ટ સંકેતો"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ડિવાઇસના ફિંગરપ્રિન્ટ સેન્સર પર કરવામાં આવેલા સંકેતો કૅપ્ચર કરી શકે છે."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"સ્ટેટસ બારને અક્ષમ કરો અથવા તેમાં ફેરફાર કરો"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ઍપ્લિકેશનને સ્ટેટસ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"સ્ટેટસ બારમાં બતાવો"</string> @@ -1552,7 +1557,7 @@ <string name="media_route_chooser_title" msgid="6646594924991269208">"ઉપકરણ સાથે કનેક્ટ કરો"</string> <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"ઉપકરણ પર સ્ક્રીન કાસ્ટ કરો"</string> <string name="media_route_chooser_searching" msgid="6119673534251329535">"ઉપકરણો માટે શોધી રહ્યું છે…"</string> - <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"સેટિંગ્સ"</string> + <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"સેટિંગ"</string> <string name="media_route_controller_disconnect" msgid="7362617572732576959">"ડિસ્કનેક્ટ કરો"</string> <string name="media_route_status_scanning" msgid="8045156315309594482">"સ્કેન કરી રહ્યું છે..."</string> <string name="media_route_status_connecting" msgid="5845597961412010540">"કનેક્ટ કરી રહ્યું છે..."</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ભલામણ કરેલ સ્તરની ઉપર વૉલ્યૂમ વધાર્યો?\n\nલાંબા સમય સુધી ઊંચા અવાજે સાંભળવું તમારી શ્રવણક્ષમતાને નુકસાન પહોંચાડી શકે છે."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ઍક્સેસિબિલિટી શૉર્ટકટનો ઉપયોગ કરીએ?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"જ્યારે શૉર્ટકટ ચાલુ હોય, ત્યારે બન્ને વૉલ્યૂમ બટનને 3 સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા શરૂ થઈ જશે.\n\n વર્તમાન ઍક્સેસિબિલિટી સુવિધા:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n તમે સેટિંગ્સ > ઍક્સેસિબિલિટીમાં જઈને આ સુવિધા બદલી શકો છો."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ખાલી કરો"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"શૉર્ટકટમાં ફેરફાર કરો"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"રદ કરો"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"શૉર્ટકટ બંધ કરો"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"શૉર્ટકટનો ઉપયોગ કરો"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"રંગનો વ્યુત્ક્રમ"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"કાર્યાલયની પ્રોફાઇલ ચાલુ કરીએ?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"તમારી કાર્યાલયની ઍપ, નોટિફિકેશન, ડેટા અને અન્ય કાર્યાલયની પ્રોફાઇલ સુવિધાઓ ચાલુ કરવામાં આવશે"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ચાલુ કરો"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"આ ઍપ Androidના જૂના વર્ઝન માટે બનાવવામાં આવ્યું હતું અને તે કદાચ તે યોગ્ય રીતે કાર્ય કરી શકશે નહીં. અપડેટ માટે તપાસવાનો પ્રયાસ કરો અથવા ડેવલપરનો સંપર્ક કરો."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"અપડેટ માટે તપાસો"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"તમારી પાસે નવા સંદેશા છે"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"સામાન્ય રીતે ચાર્જ કરવાના સમય પહેલાં બૅટરી સમાપ્ત થઈ શકે છે"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"બૅટરી આવરદા વધારવા માટે બૅટરી સેવર ચાલુ કર્યું"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"બૅટરી સેવર"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"બૅટરી ફરીથી ઓછી નહીં થાય ત્યાં સુધી બૅટરી સેવર ફરીથી સક્રિય નહીં થાય"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"બૅટરી પૂરતા લેવલ સુધી ચાર્જ થઈ ગઈ છે. બૅટરી ફરીથી ઓછી નહીં થાય ત્યાં સુધી બૅટરી સેવર ફરીથી સક્રિય નહીં થાય"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ફોન <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ચાર્જ થયો છે"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ટૅબ્લેટ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ચાર્જ થયું છે"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"ડિવાઇસ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ચાર્જ થયું છે"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"બૅટરી સેવર બંધ છે. સુવિધાઓ હવે મર્યાદિત નથી."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"બૅટરી સેવર બંધ કર્યું. સુવિધાઓ હવે મર્યાદિત નથી."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 612854cf6f8b..81054419ca7b 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"अपने कैलेंडर को ऐक्सेस करने"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"मैसेज (एसएमएस)"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"मैसेज (एसएमएस) भेजें और देखें"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"मेमोरी"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"अपने डिवाइस पर मौजूद फ़ोटो, मीडिया और फ़ाइलें ऐक्सेस करने की"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"माइक्रोफ़ोन"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ऑडियो रिकॉर्ड करें"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"इस सेवा के ज़रिए टैप, स्वाइप, पिंच और बाकी जेस्चर किए जा सकते हैं."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"फ़िंगरप्रिंट जेस्चर"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिवाइस के फ़िंगरप्रिंट सेंसर पर किए गए हाथ के जेस्चर (स्पर्श) कैप्चर किए जा सकते हैं."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार को अक्षम करें या बदलें"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ऐप को, स्टेटस बार को बंद करने या सिस्टम आइकॉन को जोड़ने और निकालने की अनुमति देता है."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार को रहने दें"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"वॉल्यूम को सुझाए गए स्तर से ऊपर बढ़ाएं?\n\nअत्यधिक वॉल्यूम पर ज़्यादा समय तक सुनने से आपकी सुनने की क्षमता को नुकसान हो सकता है."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"सुलभता शॉर्टकट का इस्तेमाल करना चाहते हैं?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"इस शॉर्टकट के चालू होने पर, दोनों वॉल्यूम बटनों को 3 सेकंड तक दबाने से सुलभता सुविधा शुरू हो जाएगी.\n\n मौजूदा सुलभता सुविधा:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n आप इस सुविधा को सेटिंग > सुलभता पर जाकर बदल सकते हैं."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"खाली करें"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"शॉर्टकट में बदलाव करें"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"अभी नहीं"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"शॉर्टकट बंद करें"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट का उपयोग करें"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"रंग बदलने की सुविधा"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"वर्क प्रोफ़ाइल चालू करें?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"आपके काम से जुड़े ऐप्लिकेशन, सूचनाएं, डेटा और वर्क प्रोफ़ाइल से जुड़ी दूसरी सुविधाएं चालू हो जाएंगी"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"चालू करें"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"यह ऐप्लिकेशन Android के पुराने वर्शन के लिए बनाया गया था, इसलिए हो सकता है कि यह सही से काम न करे. देखें कि अपडेट मौजूद हैं या नहीं, या फिर डेवलपर से संपर्क करें."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"देखें कि अपडेट मौजूद है या नहीं"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"आपके पास नए संदेश हैं"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"बैटरी आम तौर पर जितने समय चलती है, उससे पहले खत्म हो सकती है"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"बैटरी लाइफ़ बढ़ाने के लिए \'बैटरी सेवर\' चालू हो गया है"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"बैटरी सेवर"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"जब तक कि बैटरी फिर से कम नहीं हो जाती, तब तक बैटरी सेवर फिर से चालू नहीं होगा"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"बैटरी ज़रूरत भर की चार्ज हो गई है. जब तक कि बैटरी फिर से कम नहीं हो जाती, तब तक बैटरी सेवर फिर से चालू नहीं होगा."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"फ़ोन <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> चार्ज हो गया"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"टैबलेट <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> प्रतिशत चार्ज हो गया है"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"डिवाइस <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> चार्ज हो गया"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"बैटरी सेवर बंद है. सुविधाओं पर अब पाबंदी नहीं है."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"बैटरी सेवर बंद कर दिया गया है. सुविधाओं पर अब पाबंदी नहीं है."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 0b7a3571450f..973718747c62 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -290,7 +290,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"pristupati kalendaru"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"slati i pregledavati SMS poruke"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Prostor za pohranu"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Datoteke i mediji"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"pristupiti fotografijama, medijima i datotekama na vašem uređaju"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"snimati zvuk"</string> @@ -316,6 +316,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Može dodirnuti, prijeći prstom, spojiti prste i izvoditi druge pokrete."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Pokreti za otisak prsta"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Može snimati pokrete izvršene na senzoru otiska prsta na uređaju."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Snimi zaslon"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Možete napraviti snimku zaslona."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmjena trake statusa"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikaciji omogućuje onemogućavanje trake statusa ili dodavanje i uklanjanje sistemskih ikona."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"biti traka statusa"</string> @@ -1632,6 +1634,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučene razine?\n\nDugotrajno slušanje glasne glazbe može vam oštetiti sluh."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li upotrebljavati prečac za pristupačnost?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kada je taj prečac uključen, pritiskom na obje tipke za glasnoću na 3 sekunde pokrenut će se značajka pristupačnosti.\n\n Trenutačna značajka pristupačnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Značajku možete promijeniti u Postavkama > Pristupačnost."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prazno"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi prečace"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Otkaži"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Isključi prečac"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Upotrijebi prečac"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string> @@ -1877,6 +1882,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Želite uključiti radni profil?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Uključit će se vaše radne aplikacije, obavijesti, podaci i druge značajke radnog profila"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string> + <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutačno nije dostupna."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ova je aplikacija razvijena za stariju verziju Androida i možda neće funkcionirati pravilno. Potražite ažuriranja ili se obratite razvojnom programeru."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Provjeri ažuriranja"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string> @@ -1988,13 +1995,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Baterija se može isprazniti prije uobičajenog vremena punjenja"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Štednja baterije aktivirana je kako bi se produljilo trajanje baterije"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Štednja baterije"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Štednja baterije neće se ponovo aktivirati dok baterija opet ne postane slaba"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Baterija je napunjena do zadovoljavajuće razine. Štednja baterije neće se ponovo aktivirati dok baterija opet ne postane slaba."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefon je napunjen <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet je napunjen <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Uređaj je napunjen <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Isključena je Štednja baterije. Značajke više nisu ograničene."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Isključena je Štednja baterije. Značajke više nisu ograničene."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Isključena je Štednja baterije"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterija mobilnog telefona dovoljno je napunjena. Značajke više nisu ograničene."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Baterija tableta dovoljno je napunjena. Značajke više nisu ograničene."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Baterija uređaja dovoljno je napunjena. Značajke više nisu ograničene."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Mapa"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android aplikacija"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Datoteka"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index cc53c7b43419..4884cf7bc2a0 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"hozzáférés a naptárhoz"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS-ek küldése és megtekintése"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Tárhely"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Fájlok és média"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"az eszközön lévő fotók, médiatartalmak és fájlok elérése"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"hanganyag rögzítése"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Koppintás, ujjak gyors csúsztatása és összehúzása, illetve egyéb kézmozdulatok végrehajtása."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Kézmozdulatok az ujjlenyomat-érzékelőn"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Érzékeli az eszköz ujjlenyomat-érzékelőjén végzett kézmozdulatokat."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Képernyőkép készítése"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Készíthet képernyőképet a kijelzőről."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"állapotsor kikapcsolása vagy módosítása"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"az állapotsor szerepének átvétele"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Az ajánlott szint fölé szeretné emelni a hangerőt?\n\nHa hosszú időn át teszi ki magát nagy hangerőnek, azzal károsíthatja a hallását."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Szeretné használni a Kisegítő lehetőségek billentyűparancsot?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Ha be van kapcsolva a billentyűparancs, a két hangerőgomb 3 másodpercig tartó lenyomásával elindíthatja a kisegítő lehetőségek egyik funkcióját.\n\n A kisegítő lehetőségek jelenleg beállított funkciója:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n A funkciót a Beállítások > Kisegítő lehetőségek menüpontban módosíthatja."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Üres"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Gyorsparancsszerkesztés"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Mégse"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Billentyűparancs kikapcsolása"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Billentyűparancs használata"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Színek invertálása"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Bekapcsolja a munkaprofilt?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"A munkahelyi alkalmazások, értesítések, adatok és a munkaprofilhoz tartozó egyéb funkciók be lesznek kapcsolva"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Bekapcsolás"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Az alkalmazás nem hozzáférhető"</string> + <string name="app_blocked_message" msgid="542972921087873023">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> jelenleg nem hozzáférhető."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ez az alkalmazás az Android egyik korábbi verziójához készült, így elképzelhető, hogy nem működik majd megfelelően ezen a rendszeren. Keressen frissítéseket, vagy vegye fel a kapcsolatot a fejlesztővel."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Frissítés keresése"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Új üzenetei érkeztek"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Előfordulhat, hogy az akkumulátor lemerül a szokásos töltési időszak előtt"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Akkumulátorkímélő mód aktiválva az akkumulátor üzemidejének növelése érdekében"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akkumulátorkímélő mód"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Az Akkumulátorkímélő mód nem aktiválódik újra addig, amíg az akkumulátor közel nem kerül a lemerüléshez"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Az akkumulátor töltöttségi szintje elégséges. Az Akkumulátorkímélő mód nem aktiválódik újra addig, amíg az akkumulátor közel nem kerül a lemerüléshez."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"A telefon töltöttségi szintje: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"A táblagép töltöttségi szintje: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Az eszköz töltöttségi szintje: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Akkumulátorkímélő mód kikapcsolva. A funkciók használata most már nincs korlátozva."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Akkumulátorkímélő mód kikapcsolva. A funkciók használata most már nincs korlátozva."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akkumulátorkímélő mód kikapcsolva"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"A telefon töltöttsége elegendő. A funkciók használata már nincs korlátozva."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"A táblagép töltöttsége elegendő. A funkciók használata már nincs korlátozva."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Az eszköz töltöttsége elegendő. A funkciók használata már nincs korlátozva."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Mappa"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android-alkalmazás"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fájl"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index e69329898807..74915393770f 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"օգտագործել օրացույցը"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"ուղարկել և դիտել SMS-ները"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Տարածք"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"օգտագործել լուսանկարները, մեդիա ֆայլերը և ձեր սարքում պահվող մյուս ֆայլերը"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Խոսափող"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ձայնագրել"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Կարող է հպել, թերթել, պտղունցել և կատարել այլ ժեստեր:"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Մատնահետքերի սկաների ժեստեր"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Կարող է արձանագրել մատնահետքերի սկաների վրա կատարվող ժեստերը"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"լինել կարգավիճակի գոտի"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ձայնը բարձրացնե՞լ խորհուրդ տրվող մակարդակից ավել:\n\nԵրկարատև բարձրաձայն լսելը կարող է վնասել ձեր լսողությունը:"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Օգտագործե՞լ Մատչելիության դյուրանցումը։"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Հատուկ գործառույթն օգտագործելու համար սեղմեք և 3 վայրկյան սեղմած պահեք ձայնի ուժգնության երկու կոճակները, երբ գործառույթը միացված է։\n\n Մատչելիության ակտիվ գործառույթը՝\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Գործառույթը կարող եք փոփոխել՝ անցնելով Կարգավորումներ > Հատուկ գործառույթներ։"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Դատարկ"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Փոփոխել դյուրանցումները"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Չեղարկել"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Անջատել դյուրանցումը"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Օգտագործել դյուրանցումը"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Գունաշրջում"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Միացնե՞լ աշխատանքային պրոֆիլը"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Ձեր աշխատանքային հավելվածները, ծանուցումները, տվյալները և աշխատանքային պրոֆիլի մյուս գործառույթները կմիանան"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Միացնել"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Այս հավելվածը ստեղծվել է Android-ի ավելի հին տարբերակի համար և կարող է պատշաճ չաշխատել: Ստուգեք թարմացումների առկայությունը կամ դիմեք մշակողին:"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Ստուգել նոր տարբերակի առկայությունը"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Դուք ունեք նոր հաղորդագրություններ"</string> @@ -1858,7 +1870,7 @@ <string name="pin_specific_target" msgid="7824671240625957415">"Ամրացնել <xliff:g id="LABEL">%1$s</xliff:g> հավելվածը"</string> <string name="unpin_target" msgid="3963318576590204447">"Ապամրացնել"</string> <string name="unpin_specific_target" msgid="3859828252160908146">"Ապամրացնել <xliff:g id="LABEL">%1$s</xliff:g> հավելվածը"</string> - <string name="app_info" msgid="6113278084877079851">"Հավելվածի տվյալներ"</string> + <string name="app_info" msgid="6113278084877079851">"Հավելվածի մասին"</string> <string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="demo_starting_message" msgid="6577581216125805905">"Ցուցադրական օգտատերը գործարկվում է…"</string> <string name="demo_restarting_message" msgid="1160053183701746766">"Սարաքը վերակայվում է…"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Մարտկոցի լիցքը կարող է սովորականից շուտ սպառվել"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Մարտկոցի կյանքը երկարացնելու համար ակտիվացվել է մարտկոցի տնտեսման ռեժիմը"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Մարտկոցի տնտեսում"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Մարտկոցի տնտեսումը նորից կմիանա, երբ մարտկոցի լիցքը ցածր լինի"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Մարտկոցը բավարար լիցքավորված է։ Մարտկոցի տնտեսման ռեժիմը նորից կմիանա, երբ մարտկոցի լիցքը ցածր լինի։"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Հեռախոսի լիցքը՝ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Պլանշետի լիցքը՝ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Սարքի լիցքը՝ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Մարտկոցի տնտեսման ռեժիմն անջատված է: Գործառույթներն այլևս չեն սահմանափակվում։"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Մարտկոցի տնտեսումն անջատված է։ Գործառույթներն այլևս չեն սահմանափակվում։"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 299f23b817a7..9cfe6d9254e7 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"mengakses kalender"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"mengirim dan melihat pesan SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Penyimpanan"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"File dan media"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"mengakses foto, media, dan file di perangkat"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"merekam audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Dapat mengetuk, menggeser, mencubit, dan melakukan isyarat lainnya."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestur sidik jari"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dapat merekam gestur yang dilakukan di sensor sidik jari perangkat."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil screenshot"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Dapat mengambil screenshot tampilan."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"nonaktifkan atau ubah bilah status"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"jadikan bilah status"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Mengeraskan volume di atas tingkat yang disarankan?\n\nMendengarkan dengan volume keras dalam waktu yang lama dapat merusak pendengaran Anda."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Aksesibilitas?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Saat pintasan aktif, menekan kedua tombol volume selama 3 detik akan memulai fitur aksesibilitas.\n\n Fitur aksesibilitas saat ini:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Anda dapat mengubah fitur di Setelan > Aksesibilitas."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Kosong"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit pintasan"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Batal"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Nonaktifkan Pintasan"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gunakan Pintasan"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversi Warna"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Aktifkan profil kerja?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Aplikasi kerja, notifikasi, data, dan fitur profil kerja lainnya akan diaktifkan"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktifkan"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Aplikasi tidak tersedia"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak tersedia saat ini."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aplikasi ini dibuat untuk Android versi lama dan mungkin tidak berfungsi sebagaimana mestinya. Coba periksa apakah ada update, atau hubungi developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Periksa apakah ada update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Ada pesan baru"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Baterai mungkin habis sebelum pengisian daya biasanya"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Penghemat Baterai diaktifkan untuk memperpanjang masa pakai baterai"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Penghemat Baterai"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Penghemat Baterai tidak akan aktif lagi sampai baterai lemah kembali"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Baterai telah terisi ke tingkat yang memadai. Penghemat Baterai tidak akan aktif lagi sampai baterai lemah kembali."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Ponsel terisi <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet terisi <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Perangkat terisi <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Penghemat Baterai nonaktif. Fitur tidak lagi dibatasi."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Penghemat Baterai dinonaktifkan. Fitur tidak lagi dibatasi."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Penghemat Baterai dinonaktifkan"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterai ponsel cukup terisi. Fitur tidak lagi dibatasi."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Baterai tablet cukup terisi. Fitur tidak lagi dibatasi."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Baterai perangkat cukup terisi. Fitur tidak lagi dibatasi."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplikasi Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"File"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index fe55b4ca566a..f7c3b5cec73d 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"fá aðgang að dagatalinu þínu"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"senda og skoða SMS-skilaboð"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Geymslurými"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Skrár og margmiðlunarefni"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"fá aðgang að myndum, efni og skrám í tækinu"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Hljóðnemi"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"taka upp hljóð"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Getur ýtt, strokið, fært fingur saman og gert ýmsar aðrar bendingar."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingrafarabendingar"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Getur fangað bendingar sem eru gerðar á fingrafaralesara tækisins."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Taka skjámynd"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Getur tekið skjámynd af skjánum."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"slökkva á eða breyta stöðustiku"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vera stöðustikan"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Hækka hljóðstyrk umfram ráðlagðan styrk?\n\nEf hlustað er á háum hljóðstyrk í langan tíma kann það að skaða heyrnina."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Viltu nota aðgengisflýtileið?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Þegar flýtileiðin er virk er kveikt á aðgengiseiginleikanum með því að halda báðum hljóðstyrkshnöppunum inni í þrjár sekúndur.\n\n Virkur aðgengiseiginleiki:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Hægt er að skipta um eiginleika í Stillingar > Aðgengi."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Autt"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Breyta flýtileiðum"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Hætta við"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Slökkva á flýtileið"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Nota flýtileið"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Umsnúningur lita"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Kveikja á vinnusniði?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Kveikt verður á vinnuforritum, tilkynningum, gögnum og öðrum eiginleikum vinnusniðsins"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Kveikja"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Forrit er ekki tiltækt"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ekki tiltækt núna."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Þetta forrit var hannað fyrir eldri útgáfu af Android og ekki er víst að það virki eðlilega. Athugaðu hvort uppfærslur séu í boði eða hafðu samband við þróunaraðilann."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Leita að uppfærslu"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Þú ert með ný skilaboð"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Rafhlaðan kann að tæmast áður en hún kemst í hleðslu"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Kveikt á rafhlöðusparnaði til að lengja endingu rafhlöðunnar"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Rafhlöðusparnaður"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Rafhlöðusparnaður verður ekki virkur þar til næst þegar lítil hleðsla er á rafhlöðunni"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Rafhlaðan hefur fengið nægilega hleðslu. Rafhlöðusparnaður verður ekki virkur aftur fyrr en hleðslan verður lítil aftur."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Síminn er með <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> hleðslu"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Hleðsla spjaldtölvunnar er <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Tækið er með <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> hleðslu"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Slökkt er á rafhlöðusparnaði. Eiginleikar eru ekki lengur takmarkaðir."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Slökkt á rafhlöðusparnaði. Eiginleikar eru ekki lengur takmarkaðir."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Slökkt á rafhlöðusparnaði"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Síminn er með næga hleðslu. Eiginleikar eru ekki lengur takmarkaðir."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Spjaldtölva er með næga hleðslu. Eiginleikar eru ekki lengur takmarkaðir."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Tæki er með næga hleðslu. Eiginleikar eru ekki lengur takmarkaðir."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Mappa"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android forrit"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Skrá"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 87a1191da101..387d52e0536d 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"accedere al calendario"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"inviare e visualizzare SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Archiviazione"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"File e contenuti multimediali"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"accedere a foto, contenuti multimediali e file sul dispositivo"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microfono"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"registrare audio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Consente di toccare, far scorrere, pizzicare ed eseguire altri gesti."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gesti con sensore di impronte"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"È in grado di rilevare i gesti compiuti con il sensore di impronte dei dispositivi."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Acquisire screenshot"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Può acquisire uno screenshot del display."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disattivazione o modifica della barra di stato"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ruolo di barra di stato"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vuoi aumentare il volume oltre il livello consigliato?\n\nL\'ascolto ad alto volume per lunghi periodi di tempo potrebbe danneggiare l\'udito."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usare la scorciatoia Accessibilità?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando la scorciatoia è attiva, puoi premere entrambi i pulsanti del volume per tre secondi per avviare una funzione di accessibilità.\n\n Funzione di accessibilità corrente:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puoi cambiare la funzione in Impostazioni > Accessibilità."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Svuota"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifica scorciatoie"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annulla"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Disattiva scorciatoia"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usa scorciatoia"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversione colori"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Attivare il profilo di lavoro?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Le tue app di lavoro, le notifiche, i dati e altri elementi del profilo di lavoro saranno attivati."</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Attiva"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"L\'app non è disponibile"</string> + <string name="app_blocked_message" msgid="542972921087873023">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> non è al momento disponibile."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Questa app è stata realizzata per una versione precedente di Android e potrebbe non funzionare correttamente. Prova a verificare la disponibilità di aggiornamenti o contatta lo sviluppatore."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Verifica la presenza di aggiornamenti"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Hai nuovi messaggi"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"La batteria potrebbe esaurirsi prima della ricarica abituale"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Risparmio energetico attivo per far durare di più la batteria"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Risparmio energetico"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Risparmio energetico non si riattiverà finché la batteria non raggiungerà nuovamente un livello di carica basso"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"La batteria ha raggiunto un livello di carica sufficiente. Risparmio energetico non si riattiverà finché la batteria non raggiungerà nuovamente un livello di carica basso"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Livello di carica del telefono: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Livello di carica del tablet: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Livello di carica del dispositivo: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Il risparmio energetico è disattivato. Funzionalità non più limitate."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Risparmio energetico disattivato. Funzionalità non più limitate."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Risparmio energetico disattivato"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Il telefono ha carica sufficiente. Funzionalità non più limitate."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Il tablet ha carica sufficiente. Funzionalità non più limitate."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Il dispositivo ha carica sufficiente. Funzionalità non più limitate."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Cartella"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Applicazione Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"File"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index f4624ba1a0cf..cf6fa224e4ea 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -293,7 +293,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"גישה אל היומן"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"שליחה והצגה של הודעות SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"אחסון"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"גישה לתמונות, למדיה ולקבצים במכשיר שלך"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"מיקרופון"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"הקלטת אודיו"</string> @@ -319,6 +320,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"יכול להקיש, להחליק, לעשות תנועת צביטה ולבצע תנועות אחרות."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"תנועות של טביעות אצבעות"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"השבת או שנה את שורת המצב"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"מאפשר לאפליקציה להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"להיות שורת הסטטוס"</string> @@ -1654,6 +1659,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"האם להעלות את עוצמת הקול מעל לרמה המומלצת?\n\nהאזנה בעוצמת קול גבוהה למשכי זמן ממושכים עלולה לפגוע בשמיעה."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"להשתמש בקיצור הדרך לתכונת הנגישות?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"כשקיצור הדרך מופעל, לחיצה על שני לחצני עוצמת השמע למשך שלוש שניות מפעילה את תכונת הנגישות.\n\n תכונת הנגישות המוגדרת כרגע:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n אפשר לשנות את התכונה בקטע \'הגדרות ונגישות\'."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ריק"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"עריכת קיצורי הדרך"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ביטול"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"כבה את קיצור הדרך"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"השתמש בקיצור הדרך"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"היפוך צבעים"</string> @@ -1909,6 +1917,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"להפעיל את פרופיל העבודה?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"אפליקציות העבודה, התראות, נתונים ותכונות נוספות של פרופיל העבודה יופעלו"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"הפעל"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"האפליקציה הזו עוצבה לגרסה ישנה יותר של Android וייתכן שלא תפעל כראוי. ניתן לבדוק אם יש עדכונים או ליצור קשר עם המפתח."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"האם יש עדכון חדש?"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"יש לך הודעות חדשות"</string> @@ -2021,13 +2033,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"הסוללה עלולה להתרוקן לפני המועד הרגיל של הטעינה"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"תכונת החיסכון בסוללה הופעלה כדי להאריך את חיי הסוללה"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"חיסכון בסוללה"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"\'חיסכון בסוללה\' יופעל שוב רק כשהסוללה תהיה שוב חלשה"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"רמת הטעינה של הסוללה מספיקה. \'חיסכון בסוללה\' יופעל מחדש רק כשהסוללה תהיה שוב חלשה."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"הטלפון טעון בשיעור <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"הטאבלט טעון בשיעור <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"המכשיר טעון בשיעור <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"\'חיסכון בסוללה\' כבוי. התכונות כבר לא מוגבלות."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"\'חיסכון בסוללה\' כבוי. התכונות כבר לא מוגבלות."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 79d9faa107e4..e7f5e854db4b 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"カレンダーへのアクセス"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMSメッセージの送信と表示"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"ストレージ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"デバイス内の写真、メディア、ファイルへのアクセス"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"マイク"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"音声の録音"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"タップ、スワイプ、ピンチ、その他の操作を行えます。"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"指紋認証センサーでの操作"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"デバイスの指紋認証センサーで行われた操作をキャプチャできます。"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ステータスバーの無効化や変更"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ステータスバーへの表示"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"推奨レベルを超えるまで音量を上げますか?\n\n大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ユーザー補助機能のショートカットの使用"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ショートカットが ON の場合、両方の音量ボタンを 3 秒間押し続けるとユーザー補助機能が起動します。\n\n現在のユーザー補助機能:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nユーザー補助機能は [設定] > [ユーザー補助] で変更できます。"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"空"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ショートカットの編集"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"キャンセル"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ショートカットを OFF にする"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ショートカットを使用"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"色反転"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"仕事用プロファイルの有効化"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"仕事用のアプリ、通知、データなど、仕事用プロファイルの機能が ON になります"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ON にする"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"このアプリは以前のバージョンの Android 用に作成されており、正常に動作しない可能性があります。アップデートを確認するか、デベロッパーにお問い合わせください。"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"アップデートを確認"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"新着メッセージがあります"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"通常の充電を行う前に電池が切れる可能性があります"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"電池を長持ちさせるため、バッテリー セーバーが有効になりました"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"バッテリー セーバー"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"バッテリー セーバーは、電池残量が再び低下するまで有効に戻りません。"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"電池が十分なレベルまで充電されました。バッテリー セーバーは、電池残量が再び低下するまで有効に戻りません。"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"スマートフォンの電池残量 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"タブレットの電池残量 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"デバイスの電池残量 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"バッテリー セーバーが無効になりました。機能は制限されなくなりました。"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"バッテリー セーバーが無効になりました。機能は制限されなくなりました。"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index a0f631e4c992..5d4a56083e23 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"თქვენს კალენდარზე წვდომა"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS შეტყობინებების გაგზავნა და ნახვა"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"შესანახი სივრცე"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"თქვენს მოწყობილობაზე არსებულ ფოტოებზე, მედიასა და ფაილებზე წვდომა"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"მიკროფონი"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"აუდიოს ჩაწერა"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"შეუძლია შეხება, გადაფურცვლა, მასშტაბირება და სხვა ჟესტების შესრულება."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"თითის ანაბეჭდის ჟესტები"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"შეუძლია აღბეჭდოს მოწყობილობის თითის ანაბეჭდის სენსორზე განხორციელებული ჟესტები."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"სტატუსის ზოლის ჩანაცვლება"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"გსურთ ხმის რეკომენდებულ დონეზე მაღლა აწევა?\n\nხანგრძლივად ხმამაღლა მოსმენით შესაძლოა სმენადობა დაიზიანოთ."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"გსურთ მარტივი წვდომის მალსახმობის გამოყენება?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"მალსახმობის ჩართვის შემთხვევაში, ხმის ორივე ღილაკზე 3 წამის განმავლობაში დაჭერით მარტივი წვდომის ფუნქცია ჩაირთვება.\n\n მარტივი წვდომის ამჟამინდელი ფუნქციაა:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ამ ფუნქციის შეცვლა შეგიძლიათ აქ: პარამეტრები > მარტივი წვდომა."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ცარიელი"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"მალსახმობების რედაქტირება"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"გაუქმება"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"მალსახმობის გამორთვა"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"მალსახმობის გამოყენება"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"ფერთა ინვერსია"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"ჩაირთოს სამსახურის პროფილი?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"თქვენი სამსახურის აპები, შეტყობინებები, მონაცემები და სამსახურის პროფილის ყველა სხვა ფუნქცია ჩაირთვება"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ჩართვა"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ეს აპი Android-ის ძველი ვერსიისთვის შეიქმნა და შესაძლოა სათანადოდ არ მუშაობდეს. გადაამოწმეთ განახლებები ან დაუკავშირდით დეველოპერს."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"განახლების შემოწმება"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"თქვენ ახალი შეტყობინებები გაქვთ"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ბატარეა შეიძლება დაჯდეს დატენის ჩვეულ დრომდე"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ბატარეის დამზოგი გააქტიურდა ბატარეის მუშაობის გასახანგრძლივლებლად"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ბატარეის დამზოგი"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"ბატარეის დამზოგი ხელახლა არ გააქტიურდება, სანამ ბატარეა ისევ არ დაიცლება"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ბატარეა საკმარისად არის დატენილი. ბატარეის დამზოგი ხელახლა არ გააქტიურდება, სანამ ბატარეა ისევ არ დაიცლება."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ტელეფონი <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> დატენილია"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ტაბლეტი <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> დატენილია"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"მოწყობილობა <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> დატენილია"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"ბატარეის დამზოგი გამორთულია. ფუნქციები შეზღუდული აღარ არის."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"ბატარეის დამზოგი გამორთულია. ფუნქციები შეზღუდული აღარ არის."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index e6562c4c93e5..2acbb17564f1 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"күнтізбеге кіру"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS хабарларын жіберу және көру"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Жад"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"құрылғыдағы фотосуреттерге, мультимедиаға және файлдарға қол жеткізу"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"аудио жазу"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Түртуге, сырғытуға, қысуға және басқа қимылдарды орындауға болады."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Саусақ ізі сканеріндегі қимылдар"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Құрылғының саусақ ізі сенсорында орындалған қимылдарды сақтайды."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"күйін көрсету тақтасын өшіру немесе өзгерту"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"күй жолағы болу"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дыбыс деңгейін ұсынылған деңгейден көтеру керек пе?\n\nЖоғары дыбыс деңгейінде ұзақ кезеңдер бойы тыңдау есту қабілетіңізге зиян тигізуі мүмкін."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Арнайы мүмкіндік төте жолын пайдалану керек пе?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Бұл төте жол қосулы кезде дыбыс деңгейі түймелерінің екеуін де 3 секунд бойы басқанда арнайы мүмкіндік іске қосылады.\n\n Ағымдағы арнайы мүмкіндік:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Бұл мүмкіндікті \"Параметрлер\" > \"Арнайы мүмкіндіктер\" тармағында өзгертуге болады."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Бос"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Таңбашаларды өзгерту"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Бас тарту"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Төте жолды өшіру"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Төте жолды пайдалану"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Түстер инверсиясы"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Жұмыс профилі қосылсын ба?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Жұмыс қолданбалары, хабарландырулар, деректер және басқа да жұмыс профильдерінің мүмкіндіктері қосылады"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Қосу"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Қолданба Android жүйесінің ескі нұсқасына арналған және дұрыс жұмыс істемеуі мүмкін. Жаңартылған нұсқаны тексеріңіз немесе әзірлеушіге хабарласыңыз."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Жаңартылған нұсқаны тексеру"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Сізде жаңа хабарлар бар"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея заряды азаюы мүмкін"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарея ұзаққа жетуі үшін, Battery Saver іске қосылды"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Батарея қуаты азаймайынша, Battery Saver қайта қосылмайды."</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Батарея сәйкес деңгейге дейін зарядталды. Батарея қуаты азаймайынша, Battery Saver қайта қосылмайды."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Телефон батареясының қуат деңгейі: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Планшет батареясының қуат деңгейі: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Құрылғының батарея қуатының деңгейі: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Battery Saver өшірулі. Функцияларға енді шектеу қойылмайды."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Battery Saver өшірілді. Функцияларға енді шектеу қойылмайды."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index e6397ad253f2..0e277ef59dad 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ចូលប្រើប្រិតិទិនរបស់អ្នក"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"សារ SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"ផ្ញើ និងមើលសារ SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"ទំហំផ្ទុក"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"ចូលដំណើការរូបភាព មេឌៀ និងឯកសារនៅលើឧបករណ៍របស់អ្នក"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"មីក្រូហ្វូន"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ថតសំឡេង"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"អាចប៉ះ អូស ច្បិច និងធ្វើកាយវិការផ្សេងទៀត"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ចលនាស្នាមម្រាមដៃ"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"អាចចាប់យកចលនាដែលធ្វើនៅលើនៅលើឧបករណ៍ចាប់ស្នាមម្រាមដៃរបស់ឧបករណ៍បាន។"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"បិទ ឬកែរបារស្ថានភាព"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ឲ្យកម្មវិធីបិទរបារស្ថានភាព ឬបន្ថែម និងលុបរូបតំណាងប្រព័ន្ធ។"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ធ្វើជារបារស្ថានភាព"</string> @@ -1612,6 +1617,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"បង្កើនកម្រិតសំឡេងលើសពីកម្រិតបានផ្ដល់យោបល់?\n\nការស្ដាប់នៅកម្រិតសំឡេងខ្លាំងយូរអាចធ្វើឲ្យខូចត្រចៀក។"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ប្រើប្រាស់ផ្លូវកាត់ភាពងាយស្រួល?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"នៅពេលផ្លូវកាត់នេះបើក ការចុចប៊ូតុងកម្រិតសំឡេងទាំងពីរឲ្យជាប់រយៈពេល 3 វិនាទីនឹងចាប់ផ្តើមមុខងារភាពងាយស្រួល។\n\n មុខងារភាពងាយស្រួលបច្ចុប្បន្ន៖\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n អ្នកអាចផ្លាស់ប្តូរមុខងារនេះបាននៅក្នុងការ កំណត់ > ភាពងាយស្រួល។"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"លុបទាំងអស់"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"កែផ្លូវកាត់"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"បោះបង់"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"បិទផ្លូវកាត់"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ប្រើប្រាស់ផ្លូវកាត់"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"បញ្ច្រាសពណ៌"</string> @@ -1847,6 +1855,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"បើកកម្រងព័ត៌មានការងារ?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"កម្មវិធីការងារ ការជូនដំណឹង ទិន្នន័យ និងមុខងារកម្រងព័ត៌មានការងារផ្សេងទៀតរបស់អ្នកនឹងត្រូវបានបើក"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"បើក"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"កម្មវិធីនេះត្រូវបានបង្កើតឡើងសម្រាប់កំណែប្រព័ន្ធប្រតិបត្តិការ Android ចាស់ ហើយវាអាចដំណើរការខុសប្រក្រតី។ សូមសាកល្បងពិនិត្យមើលកំណែថ្មី ឬទាក់ទងទៅអ្នកអភិវឌ្ឍន៍។"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"រកមើលកំណែថ្មី"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"អ្នកមានសារថ្មី"</string> @@ -1957,13 +1969,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ថ្មអាចនឹងអស់ មុនពេលសាកថ្មធម្មតា"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"បានបើកដំណើរការកម្មវិធីសន្សំថ្ម ដើម្បីបង្កើនកម្រិតថាមពលថ្ម"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"កម្មវិធីសន្សំថ្ម"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"កម្មវិធីសន្សំថ្មនឹងមិនបើកដំណើរការឡើងវិញទេ រហូតទាល់តែថ្មមានកម្រិតទាបម្ដងទៀត"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ថ្មបានសាកដល់កម្រិតគ្រប់គ្រាន់ហើយ។ កម្មវិធីសន្សំថ្មនឹងមិនបើកដំណើរការឡើងវិញទេ រហូតទាល់តែថ្មមានកម្រិតទាបម្ដងទៀត។"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"បានសាកថ្មទូរសព្ទ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"បានសាកថ្មថេប្លេត <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"បានសាកថ្មឧបករណ៍ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"កម្មវិធីសន្សំថ្មបានបិទ។ មុខងារផ្សេងៗមិនត្រូវបានរឹតបន្តឹងទៀតទេ។"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"បានបិទកម្មវិធីសន្សំថ្ម។ មុខងារផ្សេងៗមិនត្រូវបានរឹតបន្តឹងទៀតទេ។"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 22edcae82312..50b1bba0131e 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಪ್ರವೇಶಿಸಲು"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಮತ್ತು ನಿರ್ವಹಿಸಲು"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"ಸಂಗ್ರಹಣೆ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"ಸಾಧನದಲ್ಲಿ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ ಮತ್ತು ಫೈಲ್ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"ಮೈಕ್ರೋಫೋನ್"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ಟ್ಯಾಪ್ ಮಾಡಬಹುದು, ಸ್ವೈಪ್ ಮಾಡಬಹುದು, ಪಿಂಚ್ ಮಾಡಬಹುದು ಮತ್ತು ಇತರ ಗೆಸ್ಚರ್ಗಳನ್ನು ಮಾಡಬಹುದು."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಗೆಶ್ಚರ್ಗಳು"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ಸಾಧನದ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ನಲ್ಲಿ ನಡೆಸಿದ ಗೆಶ್ಚರ್ಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ವಾಲ್ಯೂಮ್ ಅನ್ನು ಶಿಫಾರಸು ಮಾಡಲಾದ ಮಟ್ಟಕ್ಕಿಂತಲೂ ಹೆಚ್ಚು ಮಾಡುವುದೇ?\n\nದೀರ್ಘ ಅವಧಿಯವರೆಗೆ ಹೆಚ್ಚಿನ ವಾಲ್ಯೂಮ್ನಲ್ಲಿ ಆಲಿಸುವುದರಿಂದ ನಿಮ್ಮ ಆಲಿಸುವಿಕೆ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಹಾನಿಯುಂಟು ಮಾಡಬಹುದು."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್ಕಟ್ ಬಳಸುವುದೇ?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ಶಾರ್ಟ್ಕಟ್ ಆನ್ ಆಗಿರುವಾಗ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯ ಆನ್ ಮಾಡಲು, ಎರಡೂ ವಾಲ್ಯೂಮ್ ಬಟನ್ಗಳನ್ನು ನೀವು 3 ಸೆಕೆಂಡುಗಳ ಕಾಲ ಒತ್ತಬೇಕು.\n\nಪ್ರಸ್ತುತ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯ: \n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಪ್ರವೇಶಿಸುವಿಕೆಯಲ್ಲಿ ನೀವು ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬದಲಾಯಿಸಬಹುದು."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ಖಾಲಿ"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ರದ್ದುಗೊಳಿಸಿ"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ಶಾರ್ಟ್ಕಟ್ ಆಫ್ ಮಾಡಿ"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ಶಾರ್ಟ್ಕಟ್ ಬಳಸಿ"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"ಬಣ್ಣ ವಿಲೋಮ"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಆನ್ ಮಾಡುವುದೇ?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"ನಿಮ್ಮ ಕೆಲಸದ ಅಪ್ಲಿಕೇಶನ್ಗಳು, ಅಧಿಸೂಚನೆಗಳು, ಡೇಟಾ ಮತ್ತು ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ನ ಇತರ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆನ್ ಮಾಡಲಾಗುತ್ತದೆ"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ಆನ್ ಮಾಡಿ"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು Android ನ ಹಳೆಯ ಆವೃತ್ತಿಗೆ ರಚಿಸಲಾಗಿದೆ ಮತ್ತು ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡದಿರಬಹುದು. ಅಪ್ಡೇಟ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಲು ಪ್ರಯತ್ನಿಸಿ ಅಥವಾ ಡೆವಲಪರ್ ಅನ್ನು ಸಂಪರ್ಕಿಸಿ."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ಅಪ್ಡೇಟ್ಗಾಗಿ ಪರಿಶೀಲಿಸಿ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ನೀವು ಹೊಸ ಸಂದೇಶಗಳನ್ನು ಹೊಂದಿರುವಿರಿ"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ಚಾರ್ಜ್ಗೆ ಮೊದಲೆ ಬ್ಯಾಟರಿ ಮುಗಿದು ಬಿಡಬಹುದು"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ಬ್ಯಾಟರಿ ಅವಧಿ ಹೆಚ್ಚಿಸಲು ಬ್ಯಾಟರಿ ಸೇವರ್ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"ಇನ್ನೊಮ್ಮೆ ಬ್ಯಾಟರಿ ಕಡಿಮೆಯಾಗುವವರೆಗೂ ಬ್ಯಾಟರಿ ಸೇವರ್ ಮರುಸಕ್ರಿಯವಾಗುವುದಿಲ್ಲ"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ಬ್ಯಾಟರಿಯನ್ನು ಬೇಕಾಗಿರುವಷ್ಟು ಮಟ್ಟಕ್ಕೆ ಚಾರ್ಜ್ ಮಾಡಲಾಗಿದೆ. ಇನ್ನೊಮ್ಮೆ ಬ್ಯಾಟರಿ ಕಡಿಮೆಯಾಗುವವರೆಗೂ ಬ್ಯಾಟರಿ ಸೇವರ್ ಮರುಸಕ್ರಿಯವಾಗುವುದಿಲ್ಲ."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ಫೋನ್ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ಚಾರ್ಜ್ ಆಗಿದೆ"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ಟ್ಯಾಬ್ಲೆಟ್ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ಚಾರ್ಜ್ ಆಗಿದೆ"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"ಸಾಧನ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ಚಾರ್ಜ್ ಆಗಿದೆ"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಆಫ್ ಆಗಿದೆ. ಇನ್ನು ಮುಂದೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗುವುದಿಲ್ಲ."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ. ಇನ್ನು ಮುಂದೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗುವುದಿಲ್ಲ."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index df26c4eee099..7e12490989cc 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"캘린더에 액세스"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS 메시지 전송 및 보기"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"저장용량"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"기기 사진, 미디어, 파일 액세스"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"마이크"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"오디오 녹음"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"탭, 스와이프, 확대/축소 및 기타 동작을 실행할 수 있습니다."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"지문 동작"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"기기 지문 센서에서 동작을 캡처합니다."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"상태 표시줄 사용 중지 또는 수정"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"상태 표시줄에 위치"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"권장 수준 이상으로 볼륨을 높이시겠습니까?\n\n높은 볼륨으로 장시간 청취하면 청력에 손상이 올 수 있습니다."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"접근성 단축키를 사용하시겠습니까?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"단축키가 사용 설정된 경우 두 개의 볼륨 버튼을 3초간 누르면 접근성 기능이 시작됩니다.\n\n 현재 접근성 기능:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n \'설정 > 접근성\'에서 기능을 변경할 수 있습니다."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"비우기"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"단축키 수정"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"취소"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"단축키 사용 중지"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"단축키 사용"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"색상 반전"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"직장 프로필을 사용 설정하시겠어요?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"업무용 앱, 알림, 데이터 및 기타 직장 프로필 기능이 사용 설정됩니다."</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"사용 설정"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"이 앱은 Android 이전 버전에 맞게 개발되었기 때문에 제대로 작동하지 않을 수 있습니다. 업데이트를 확인하거나 개발자에게 문의하세요."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"업데이트 확인"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"새 메시지 있음"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"평소에 충전하는 시간 전에 배터리가 소진될 수 있습니다."</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"배터리 수명을 연장하기 위해 배터리 세이버가 활성화되었습니다."</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"절전 모드"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"배터리가 다시 부족해지기 전까지 절전 모드가 재활성화되지 않음"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"배터리가 충분히 충전되었습니다. 배터리가 다시 부족해지기 전까지는 절전 모드가 재활성화되지 않습니다."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"휴대전화 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> 충전됨"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"태블릿 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> 충전됨"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"기기 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> 충전됨"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"절전 모드가 꺼져 있습니다. 기능이 더 이상 제한되지 않습니다."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"절전 모드가 사용 중지되었습니다. 기능이 더 이상 제한되지 않습니다."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index adcc4c1b46e1..c887c3451046 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"жылнаамаңызды пайдалануу"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS билдирүүлөрдү жиберүү жана көрсөтүү"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Сактагыч"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"түзмөгүңүздөгү сүрөттөрдү жана башка мультимедиа файлдарын пайдаланууга"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"аудио жаздыруу"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Таптап, серпип, чымчып жана башка жаңсоолорду аткара алат."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Манжа изинин жаңсоолору"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Түзмөктөгү манжа изинин сенсорунда жасалган жаңсоолорду жаздырып алат."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"абал тилкесин өчүрүү же өзгөртүү"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"абал тилкесинин милдетин аткаруу"</string> @@ -1395,7 +1400,7 @@ <string name="ime_action_default" msgid="8265027027659800121">"Аткаруу"</string> <string name="dial_number_using" msgid="6060769078933953531">"<xliff:g id="NUMBER">%s</xliff:g> менен\nномерди терүү"</string> <string name="create_contact_using" msgid="6200708808003692594">"<xliff:g id="NUMBER">%s</xliff:g> менен\nбайланыш түзүү"</string> - <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"Төмөнкү бир же бир нече колдонмо каттоо эсебиңизге азыр жана кийинчерээк кирүү мүмкүнчүлүгүн сурап жатат."</string> + <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"Төмөнкү бир же бир нече колдонмо аккаунтуңузга азыр жана кийинчерээк кирүү мүмкүнчүлүгүн сурап жатат."</string> <string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"Бул өтүнүчкө уруксат бересизби?"</string> <string name="grant_permissions_header_text" msgid="3420736827804657201">"Жетки талабы"</string> <string name="allow" msgid="6195617008611933762">"Уруксат берүү"</string> @@ -1602,14 +1607,17 @@ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"Сиз планшетиңизди <xliff:g id="NUMBER">%d</xliff:g> жолу ийгиликсиз бөгөттөн чыгаруу аракетин кылдыңыз. Планшет баштапкы абалына кайтарылат."</string> <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"Android TV түзмөгүңүздүн кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Android TV түзмөгүңүз эми демейки жөндөөлөргө кайтарылат."</string> <string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"Сиз телефонуңузду <xliff:g id="NUMBER">%d</xliff:g> жолу ийгиликсиз бөгөттөн чыгаруу аракетин кылдыңыз. Телефон баштапкы абалына кайтарылат."</string> - <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес көрсөттүңүз. <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес көрсөтүлгөндөн кийин, планшетиңиздин кулпусун ачуу үчүн Google каттоо эсебиңизге кирүүгө туура келет.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин кайталап көрсөңүз болот."</string> + <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес көрсөттүңүз. <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес көрсөтүлгөндөн кийин, планшетиңиздин кулпусун ачуу үчүн Google аккаунтуңузга кирүүгө туура келет.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин кайталап көрсөңүз болот."</string> <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"Графикалык ачкычыңызды <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес чийдиңиз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин, Android TV түзмөгүңүздүн кулпусун электрондук почта аккаунтуңуз менен ачышыңыз керек болот.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракет кылыңыз."</string> - <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес көрсөттүңүз. <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес көрсөтүлгөндөн кийин, телефондун кулпусун ачуу үчүн Google каттоо эсебиңизге кирүүгө туура келет.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин кайталап көрсөңүз болот."</string> + <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес көрсөттүңүз. <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес көрсөтүлгөндөн кийин, телефондун кулпусун ачуу үчүн Google аккаунтуңузга кирүүгө туура келет.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин кайталап көрсөңүз болот."</string> <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string> <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Алып салуу"</string> <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Сунушталган деңгээлден да катуулатып уккуңуз келеби?\n\nМузыканы узакка чейин катуу уксаңыз, угууңуз начарлап кетиши мүмкүн."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ыкчам иштетесизби?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн, ал күйгүзүлгөндө, үндү катуулатып/акырындаткан эки баскычты тең үч секунддай кое бербей басып туруңуз.\n\n Учурдагы атайын мүмкүнчүлүктөрдүн жөндөөлөрү:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nЖөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнөн өзгөртө аласыз."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Бошотуу"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Кыска жолдорду түзөтүү"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Жокко чыгаруу"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Кыска жолду өчүрүү"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Кыска жолду колдонуу"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Түстү инверсиялоо"</string> @@ -1843,8 +1851,12 @@ <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> колдонмосу учурда жеткиликсиз. Анын жеткиликтүүлүгү <xliff:g id="APP_NAME_1">%2$s</xliff:g> тарабынан башкарылат."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"Кеңири маалымат"</string> <string name="work_mode_off_title" msgid="5503291976647976560">"Жумуш профили күйгүзүлсүнбү?"</string> - <string name="work_mode_off_message" msgid="8417484421098563803">"Жумуш колдонмолоруңуз, эскертмелериңиз, дайындарыңыз жана жумуш профилинин башка функциялары күйгүзүлөт."</string> + <string name="work_mode_off_message" msgid="8417484421098563803">"Жумуш колдонмолоруңуз, эскертмелериңиз, дайын-даректериңиз жана жумуш профилинин башка функциялары күйгүзүлөт."</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Күйгүзүү"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Бул колдонмо Android\'дин эски версиясы үчүн иштеп чыгарылган, андыктан туура эмес иштеши мүмкүн. Жаңыртууларды издеп көрүңүз же иштеп чыгуучуга кайрылыңыз."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Жаңыртууну издөө"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Сизге жаңы билдирүүлөр келди"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея кубаттоого чейин отуруп калышы мүмкүн"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батареянын отуруп калбашы үчүн Батареяны үнөмдөгүч режими иштетилди"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батареяны үнөмдөгүч"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Батареяны үнөмдөгүч батарея кайра азаймайынча күйгүзүлбөйт"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Батарея жетиштүү деңгээлге чейин кубатталды. Батареяны үнөмдөгүч батарея кайра азайганча чейин күйгүзүлбөйт."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Телефон <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> кубатталды"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Планшет <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> кубатталды"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Түзмөк <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> кубатталды"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Батареяны үнөмдөгүч өчүк. Функцияны колдоно берсеңиз болот."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Батареяны үнөмдөгүч режими өчүрүлдү. Функцияны колдоно берсеңиз болот."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 230f2b52a3d6..52674c0b09b2 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ເຂົ້າຫາປະຕິທິນຂອງທ່ານ"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"ສົ່ງ ແລະເບິ່ງຂໍ້ຄວາມ SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"ພື້ນທີ່ຈັດເກັບຂໍ້ມູນ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"ເຂົ້າເຖິງຮູບຖ່າຍ, ສື່ ແລະໄຟລ໌ຢູ່ເທິງອຸປະກອນຂອງທ່ານ"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"ໄມໂຄຣໂຟນ"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ບັນທຶກສຽງ"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ສາມາດແຕະ, ປັດນີ້ວມື, ຢິບນິ້ວມື ແລະ ດຳເນີນທ່າທາງອື່ນ."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ທ່າທາງລາຍນິ້ວມື"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ສາມາດບັນທຶກທ່າທາງທີ່ເກີດຂຶ້ນໃນອຸປະກອນເຊັນເຊີລາຍນິ້ວມືໄດ້."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ເປັນແຖບສະຖານະ"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ເພີ່ມລະດັບສຽງໃຫ້ເກີນກວ່າລະດັບທີ່ແນະນຳບໍ?\n\nການຮັບຟັງສຽງໃນລະດັບທີ່ສູງເປັນໄລຍະເວລາດົນອາດເຮັດໃຫ້ການຟັງຂອງທ່ານມີບັນຫາໄດ້."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ໃຊ້ປຸ່ມລັດການຊ່ວຍເຂົ້າເຖິງບໍ?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ເມື່ອເປີດໃຊ້ປຸ່ມລັດແລ້ວ, ໃຫ້ກົດປຸ່ມສຽງທັງສອງຄ້າງໄວ້ 3 ວິນາທີເພື່ອເລີ່ມຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ.\n\n ຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງປັດຈຸບັນ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ທ່ານສາມາດປ່ຽນຄຸນສົມບັດໄດ້ໃນການຕັ້ງຄ່າ > ການຊ່ວຍເຂົ້າເຖິງ."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ຫວ່າງເປົ່າ"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ແກ້ໄຂທາງລັດ"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ຍົກເລີກ"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ປິດປຸ່ມລັດ"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ໃຊ້ປຸ່ມລັດ"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"ການປີ້ນສີ"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"ເປີດໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກບໍ?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"ແອັບວຽກຂອງທ່ານ, ການແຈ້ງເຕືອນ, ຂໍ້ມູນ ແລະ ຄຸນສົມບັດໂປຣໄຟລ໌ວຽກຈະຖືກເປີດໃຊ້"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ເປີດ"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ແອັບນີ້ຖືກສ້າງຂຶ້ນສຳລັບ Android ເວີຊັນທີ່ເກົ່າກວ່າ ແລະ ອາດເຮັດວຽກໄດ້ບໍ່ປົກກະຕິ. ໃຫ້ລອງກວດສອບເບິ່ງອັບເດດ ຫຼື ຕິດຕໍ່ຜູ້ພັດທະນາ."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ກວດເບິ່ງອັບເດດ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ທ່ານມີຂໍ້ຄວາມໃໝ່"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ແບັດເຕີຣີອາດໝົດກ່ອນການສາກຕາມປົກກະຕິ"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ເປີດຕົວປະຢັດແບັດເຕີຣີເພື່ອຂະຫຍາຍອາຍຸແບັດເຕີຣີ"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ຕົວປະຢັດແບັດເຕີຣີ"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"ຈະບໍ່ມີການເປີດໃຊ້ຕົວປະຢັດແບັດເຕີຣີຄືນໃໝ່ຈົນກວ່າແບັດເຕີຣີຈະເຫຼືອໜ້ອຍອີກເທື່ອໜຶ່ງ"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ສາກແບັດເຕີຣີຮອດລະດັບທີ່ພຽງພໍແລ້ວ. ຕົວປະຢັດແບັດເຕີຣີຈະບໍ່ເປີດໃຊ້ຄືນໃໝ່ຈົນກວ່າແບັດເຕີຣີຈະເຫຼືອໜ້ອຍກີເທື່ອໜຶ່ງ."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ສາກໂທລະສັບແລ້ວ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ສາກແທັບເລັດແລ້ວ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"ສາກອຸປະກອນແລ້ວ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"ຕົວປະຢັດແບັດເຕີຣີປິດຢູ່. ບໍ່ມີການຈຳກັດຄຸນສົມບັດອີກຕໍ່ໄປແລ້ວ."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"ປິດຕົວປະຢັດແບັດເຕີຣີແລ້ວ. ບໍ່ມີການຈຳກັດຄຸນສົມບັດອີກຕໍ່ໄປແລ້ວ."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 5a85f481e73b..5097d45e9095 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -293,7 +293,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"pasiekti kalendorių"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"siųsti ir peržiūrėti SMS pranešimus"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Saugykla"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Failai ir medija"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"pasiekti nuotraukas, mediją ir failus įrenginyje"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofonas"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"įrašyti garso įrašą"</string> @@ -319,6 +319,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Galima paliesti, perbraukti, suimti ir atlikti kitus veiksmus gestais."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Piršto antspaudo gestai"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Gali užfiksuoti gestus, atliktus naudojant įrenginio piršto antspaudo jutiklį."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrano kopijos kūrimas"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Galima sukurti vaizdo ekrano kopiją."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"išjungti ar keisti būsenos juostą"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"būti būsenos juosta"</string> @@ -1654,6 +1656,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Padidinti garsą daugiau nei rekomenduojamas lygis?\n\nIlgai klausydami dideliu garsu galite pažeisti klausą."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Naudoti spartųjį pritaikymo neįgaliesiems klavišą?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kai spartusis klavišas įjungtas, spaudžiant abu garsumo mygtukus 3 sekundes bus paleista pritaikymo neįgaliesiems funkcija.\n\n Dabartinė pritaikymo neįgaliesiems funkcija:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>„\n“\n Funkciją galite pakeisti skiltyje „Nustatymai“ > „Pritaikymas neįgaliesiems“."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Išvalyti"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redaguoti sparčiuosius klavišus"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Atšaukti"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Išjungti spartųjį klavišą"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Naudoti spartųjį klavišą"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Spalvų inversija"</string> @@ -1909,6 +1914,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Įjungti darbo profilį?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Darbo programos, pranešimai, duomenys ir kitos darbo profilio funkcijos bus išjungtos"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Įjungti"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Programa nepasiekiama."</string> + <string name="app_blocked_message" msgid="542972921087873023">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ šiuo metu nepasiekiama."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ši programa sukurta naudoti senesnės versijos sistemoje „Android“ ir gali tinkamai neveikti. Pabandykite patikrinti, ar yra naujinių, arba susisiekite su kūrėju."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tikrinti, ar yra naujinių"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Turite naujų pranešimų"</string> @@ -2021,13 +2028,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akumuliatoriaus energija gali išsekti prieš įprastą įkrovimą"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Akumuliatoriaus tausojimo priemonė suaktyvinta, kad akumuliatorius veiktų ilgiau"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akumuliatoriaus tausojimo priemonė"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Akumuliatoriaus tausojimo priemonė nebus iš naujo suaktyvinta, kol akumuliatorius vėl beveik išseks"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Pasiektas tinkamas akumuliatoriaus įkrovimo lygis. Akumuliatoriaus tausojimo priemonė nebus iš naujo suaktyvinta, kol akumuliatorius vėl beveik išseks."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefono įkrovimo lygis: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Planšetinio kompiuterio įkrovimo lygis: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Įrenginio įkrovimo lygis: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Akumuliatoriaus tausojimo priemonė išjungta. Funkcijos neberibojamos."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Akumuliatoriaus tausojimo priemonė išjungta. Funkcijos neberibojamos."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akumuliatoriaus tausojimo priemonė išjungta"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonas pakankamai įkrautas. Funkcijos neberibojamos."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Planšetinis kompiuteris pakankamai įkrautas. Funkcijos neberibojamos."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Įrenginys pakankamai įkrautas. Funkcijos neberibojamos."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Aplankas"</string> <string name="mime_type_apk" msgid="3168784749499623902">"„Android“ programa"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Failas"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 17c0c17a7769..7d11634f8980 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -290,7 +290,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"piekļūt jūsu kalendāram"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"Īsziņas"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"sūtīt un skatīt īsziņas"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Krātuve"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"piekļūt fotoattēliem, multividei un failiem jūsu ierīcē"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofons"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ierakstīt audio"</string> @@ -316,6 +317,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Atbalsta pieskaršanos, vilkšanu, savilkšanu un citus žestus."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Pirksta nospieduma žesti"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Var uztvert žestus ierīces pirksta nospieduma sensorā."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"atspējot vai pārveidot statusa joslu"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"Būt par statusa joslu"</string> @@ -1632,6 +1637,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vai palielināt skaļumu virs ieteicamā līmeņa?\n\nIlgstoši klausoties skaņu lielā skaļumā, var tikt bojāta dzirde."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vai izmantot pieejamības saīsni?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Ja saīsne ir iespējota, vienlaikus nospiežot abas skaļuma regulēšanas pogas un trīs sekundes turot tās, tiks palaista pieejamības funkcija.\n\n Pašreiz iestatītā pieejamības funkcija:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Šo funkciju var mainīt sadaļā Iestatījumi > Pieejamība."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Notīrīt"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediģēt īsinājumtaustiņus"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Atcelt"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Izslēgt saīsni"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Izmantot saīsni"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Krāsu inversija"</string> @@ -1877,6 +1885,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Vai ieslēgt darba profilu?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Tiks ieslēgtas jūsu darba lietotnes, paziņojumi, dati un citas darba profila funkcijas."</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Ieslēgt"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Šī lietotne tika izstrādāta vecākai Android versijai un var nedarboties pareizi. Meklējiet atjauninājumus vai sazinieties ar izstrādātāju."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Meklēt atjauninājumu"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Jums ir jaunas īsziņas."</string> @@ -1988,13 +2000,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akumulators var izlādēties pirms parastā uzlādes laika"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Aktivizēts akumulatora jaudas taupīšanas režīms, lai palielinātu akumulatora darbības ilgumu"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akumulatora jaudas taupīšanas režīms"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Akumulatora jaudas taupīšanas režīms tiks atkārtoti aktivizēts tikai tad, kad akumulatora uzlādes līmenis atkal būs zems"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Akumulatora uzlādes līmenis ir pietiekams. Akumulatora jaudas taupīšanas režīms tiks atkārtoti aktivizēts tikai tad, kad akumulatora uzlādes līmenis atkal būs zems."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Tālruņa uzlādes līmenis ir <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Planšetdatora uzlādes līmenis ir <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Ierīces uzlādes līmenis ir <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Akumulatora jaudas taupīšanas režīms ir izslēgts. Funkcijas vairs netiek ierobežotas."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Akumulatora jaudas taupīšanas režīms ir izslēgts. Funkcijas vairs netiek ierobežotas."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Mape"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android lietojumprogramma"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fails"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 2898129efd8c..72048b5dc6bb 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"пристапува до календарот"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"испраќа и прикажува SMS-пораки"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Капацитет"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Датотеки и аудиовизуелни содржини"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"пристапува до фотографии, аудио-видео и датотеки на уредот"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"снима аудио"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Може да допрете, повлечете, штипнете и да користите други движења."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Движења за отпечатоци"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да сними движења што се направени на сензорот за отпечатоци на уредот."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Правење слика од екранот"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да направи слика од екранот."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"оневозможи или измени статусна лента"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"да стане статусна лента"</string> @@ -1454,7 +1456,7 @@ <string name="sync_really_delete" msgid="5657871730315579051">"Избриши ги ставките"</string> <string name="sync_undo_deletes" msgid="5786033331266418896">"Врати ги избришаните"</string> <string name="sync_do_nothing" msgid="4528734662446469646">"Не прави ништо засега"</string> - <string name="choose_account_label" msgid="5557833752759831548">"Избери сметка"</string> + <string name="choose_account_label" msgid="5557833752759831548">"Изберете сметка"</string> <string name="add_account_label" msgid="4067610644298737417">"Додај сметка"</string> <string name="add_account_button_label" msgid="322390749416414097">"Додај сметка"</string> <string name="number_picker_increment_button" msgid="7621013714795186298">"Зголеми"</string> @@ -1612,6 +1614,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да го зголемиме звукот над препорачаното ниво?\n\nСлушањето звуци со голема јачина подолги периоди може да ви го оштети сетилото за слух."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Да се користи кратенка за „Пристапност“?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Кога е вклучена кратенката, ако ги притиснете двете копчиња за јачина на звук во времетраење од 3 секунди, ќе се стартува функција на пристапност.\n\n Тековна функција на пристапност:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Функцијата може да ја промените во „Поставки“ > „Пристапност“."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Испразни"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Изменете ги кратенките"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Откажи"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Исклучи ја кратенката"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Користи кратенка"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Инверзија на бои"</string> @@ -1847,6 +1852,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Да се вклучи работниот профил?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Вашите работни апликации, известувања, податоци и други функции на работниот профил ќе бидат вклучени"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Вклучи"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Апликацијата не е достапна"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> не е достапна во моментов."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Апликацијава е создадена за постара верзија на Android и може да не функционира правилно. Проверете за ажурирања или контактирајте со програмерот."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверка за ажурирање"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Имате нови пораки"</string> @@ -1957,13 +1964,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батеријата може да се потроши пред вообичаеното време за полнење"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Активиран е „Штедачот на батерија“ за да се продолжи траењето на батеријата"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Штедач на батерија"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Штедачот на батерија нема да се реактивира додека батеријата не се потроши до одредено ниво повторно"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Батеријата е доволно полна. Штедачот на батерија нема да се реактивира додека батеријата не се потроши до одредено ниво повторно."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Телефонот е наполнет <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Таблетот е наполнет <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Уредот е наполнет <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Штедачот на батерија е исклучен. Функциите веќе не се ограничени."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Штедачот на батерија е исклучен. Функциите веќе не се ограничени."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Штедачот на батерија е исклучен"</string> + <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_apk" msgid="3168784749499623902">"Апликација за Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Датотека"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 1abf88d03c20..b0bbb670146d 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"നിങ്ങളുടെ കലണ്ടർ ആക്സസ്സ് ചെയ്യുക"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS സന്ദേശങ്ങൾ അയയ്ക്കുകയും കാണുകയും ചെയ്യുക"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"സ്റ്റോറേജ്"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"നിങ്ങളുടെ ഉപകരണത്തിലെ ഫോട്ടോകളും മീഡിയയും ഫയലുകളും ആക്സസ് ചെയ്യുക"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"മൈക്രോഫോണ്"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ഓഡിയോ റെക്കോർഡ് ചെയ്യുക"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ടാപ്പുചെയ്യാനോ സ്വൈപ്പുചെയ്യാനോ പിഞ്ചുചെയ്യാനോ മറ്റ് ജെസ്റ്ററുകൾ നിർവഹിക്കാനോ കഴിയും."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ഫിംഗർപ്രിന്റ് ജെസ്റ്ററുകൾ"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്ത ജെസ്റ്ററുകൾ ക്യാപ്ചർ ചെയ്യാനാകും."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്ക്കരിക്കുക"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"മുകളിൽക്കൊടുത്തിരിക്കുന്ന ശുപാർശചെയ്ത ലെവലിലേക്ക് വോളിയം വർദ്ധിപ്പിക്കണോ?\n\nഉയർന്ന വോളിയത്തിൽ ദീർഘനേരം കേൾക്കുന്നത് നിങ്ങളുടെ ശ്രവണ ശേഷിയെ ദോഷകരമായി ബാധിക്കാം."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ഉപയോഗസഹായി കുറുക്കുവഴി ഉപയോഗിക്കണോ?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"കുറുക്കുവഴി ഓണാണെങ്കിൽ, രണ്ട് വോളിയം ബട്ടണുകളും 3 സെക്കൻഡ് നേരത്തേക്ക് അമർത്തുന്നത് ഉപയോഗസഹായി ഫീച്ചർ ആരംഭിക്കും.\n\n നിലവിലെ ഉപയോഗസഹായി ഫീച്ചർ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ക്രമീകരണം > ഉപയോഗസഹായി എന്നതിൽ ഏത് സമയത്തും നിങ്ങൾക്ക് ഫീച്ചർ മാറ്റാവുന്നതാണ്."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ശൂന്യം"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"കുറുക്കുവഴികൾ തിരുത്തുക"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"റദ്ദാക്കുക"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"കുറുക്കുവഴി ഓഫാക്കുക"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"കുറുക്കുവഴി ഉപയോഗിക്കുക"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"വർണ്ണ വിപര്യയം"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"ഔദ്യോഗിക പ്രൊഫൈൽ ഓണാക്കണോ?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"നിങ്ങളുടെ ഔദ്യോഗിക ആപ്പുകൾ, അറിയിപ്പുകൾ, ഡാറ്റ, മറ്റ് ഔദ്യോഗിക പ്രൊഫൈൽ ഫീച്ചറുകൾ എന്നിവ ഓണാക്കും"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ഓണാക്കുക"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ഈ ആപ്പ് Android-ന്റെ പഴയ പതിപ്പിനായി നിർമ്മിച്ചിരിക്കുന്നതിനാൽ ശരിയായി പ്രവർത്തിച്ചേക്കില്ല. അപ്ഡേറ്റിനായി പരിശോധിക്കുക, അല്ലെങ്കിൽ ഡെവലപ്പറുമായി ബന്ധപ്പെടുക."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"അപ്ഡേറ്റിനായി പരിശോധിക്കുക"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"നിങ്ങൾക്ക് പുതിയ സന്ദേശങ്ങൾ ഉണ്ട്"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"സാധാരണയുള്ളതിലും നേരത്തെ ബാറ്ററിയുടെ ചാർജ് തീർന്നേക്കാം"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ബാറ്ററി ലൈഫ് വര്ദ്ധിപ്പിക്കാൻ, ബാറ്ററി ലാഭിക്കൽ സജീവമാക്കി"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ബാറ്ററി ലാഭിക്കൽ"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"ബാറ്ററി ചാർജ് വീണ്ടും കുറയുന്നത് വരെ ബാറ്ററി ലാഭിക്കൽ പിന്നെയും സജീവമാവുകയില്ല"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"മതിയായ നില വരെ ബാറ്ററി ചാർജായി. വീണ്ടും ബാറ്ററി ചാർജ് കുറയുന്നത് വരെ ബാറ്ററി ലാഭിക്കൽ പിന്നെയും സജീവമാവുകയില്ല."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ഫോൺ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ചാർജായി"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ടാബ്ലെറ്റ് <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ചാർജായി"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"ഉപകരണം <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ചാർജായി"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"ബാറ്ററി ലാഭിക്കൽ ഓഫാണ്. ഫീച്ചറുകൾക്ക് ഇനിമുതൽ നിയന്ത്രണമില്ല."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"ബാറ്ററി ലാഭിക്കൽ ഓഫാക്കി. ഫീച്ചറുകൾക്ക് ഇനിമുതൽ നിയന്ത്രണമില്ല."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 0f17c00b82c9..205df2770748 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"Хуанли руу хандах"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"Мессеж"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS мессежийг илгээх, харах"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Хадгалах сан"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"Tөхөөрөмж дээрх зураг, медиа болон файлд хандалт хийх"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"дуу хураах"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Товших, шудрах, жижигрүүлэх болон бусад зангааг хийх боломжтой."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Хурууны хээний зангаа"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Төхөөрөмжийн хурууны хээ мэдрэгчид зангасан зангааг танина."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"статусын хэсэг болох"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дууг санал болгосноос чанга болгож өсгөх үү?\n\nУрт хугацаанд чанга хөгжим сонсох нь таны сонсголыг муутгаж болно."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Хүртээмжийн товчлолыг ашиглах уу?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Товчлолыг асаасан үед дуун товчлуурыг 3 секунд дарснаар хүртээмжийн онцлогийг эхлүүлнэ.\n\n Одоогийн хүртээмжийн онцлог:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Онцлогийг Тохиргоо > Хүртээмж хэсэгт өөрчлөх боломжтой."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Хоосон"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Товчлолуудыг засах"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Болих"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Товчлолыг унтраах"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Товчлол ашиглах"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Өнгө хувиргалт"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Ажлын профайлыг асаах уу?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Таны ажлын апп, мэдэгдэл, өгөгдөл болон бусад ажлын профайлын онцлогийг асаана"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Асаах"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Энэ аппыг Андройдын хуучин хувилбарт зориулсан бөгөөд буруу ажиллаж болзошгүй. Шинэчлэлтийг шалгаж эсвэл хөгжүүлэгчтэй холбогдоно уу."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Шинэчлэлтийг шалгах"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Танд шинэ зурвасууд байна"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарей ихэвчлэн цэнэглэдэг хугацаанаас өмнө дуусаж болзошгүй"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарейн ажиллах хугацааг уртасгахын тулд Батарей хэмнэгчийг идэвхжүүллээ"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батарей хэмнэгч"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Батарей хэмнэгч батарейг дахин багасах хүртэл дахин идэвхжихгүй"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Батарейг хангалттай түвшинд цэнэглэлээ. Батарей хэмнэгч батарейг дахин багасах хүртэл дахин идэвхжихгүй."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Утсыг <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> цэнэглэсэн байна"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Таблетыг <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> цэнэглэсэн"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Төхөөрөмжийг <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> цэнэглэсэн байна"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Батарей хэмнэгч унтраалттай байна. Онцлогуудыг хязгаарлахаа больсон."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Батарей хэмнэгчийг унтраасан байна. Онцлогуудыг хязгаарлахаа больсон."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Фолдер"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Андройд апп"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Файл"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index fa8cbb0208d1..b27e1c9c8f94 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"आपल्या कॅलेंडरवर प्रवेश"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS मेसेज पाठवणे आणि पाहणे हे"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"स्टोरेज"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"तुमच्या डिव्हाइस वरील फोटो, मीडिया आणि फायलींमध्ये अॅक्सेस"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"मायक्रोफोन"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ऑडिओ रेकॉर्ड"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"टॅप, स्वाइप, पिंच आणि इतर जेश्चर करू शकते."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"फिंगरप्रिंट जेश्चर"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिव्हाइसच्या फिंगरप्रिंट सेंन्सरवरील जेश्चर कॅप्चर करू शकते."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार होऊ द्या"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"शिफारस केलेल्या पातळीच्या वर आवाज वाढवायचा?\n\nउच्च आवाजात दीर्घ काळ ऐकण्याने आपल्या श्रवणशक्तीची हानी होऊ शकते."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"प्रवेशयोग्यता शॉर्टकट वापरायचा?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"शॉर्टकट चालू असताना, दोन्ही आवाज बटणे 3 सेकंद दाबल्याने प्रवेशयोग्यता वैशिष्ट्य सुरू होईल.\n\n वर्तमान प्रवेशयोग्यता वैशिष्ट्य:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n तुम्ही सेटिंग्ज > प्रवेशयोग्यता मध्ये वैशिष्ट्य बदलू शकता."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"रिकामे करा"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"शॉर्टकट संपादित करा"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"रद्द करा"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"शॉर्टकट बंद करा"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट वापरा"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"रंगांची उलटापालट"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"कार्य प्रोफाइल चालू ठेवायची?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"तुमची कार्य अॅप्स, सूचना, डेटा आणि अन्य कार्य प्रोफाइल वैशिष्ट्ये चालू केली जातील"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"चालू करा"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"हे अॅप Android च्या जुन्या आवृत्ती साठी तयार करण्यात आले होते आणि योग्यरितीने कार्य करू शकणार नाही. अपडेट आहेत का ते तपासून पाहा, किंवा डेव्हलपरशी संपर्क साधण्याचा प्रयत्न करा."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेट आहे का ते तपासा"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"आपल्याकडे नवीन मेसेज आहेत"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"चार्जिंगची सामान्य पातळी गाठेपर्यंत कदाचित बॅटरी संपू शकते"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"बॅटरी लाइफ वाढवण्यासाठी बॅटरी सेव्हर सुरू केला आहे"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"बॅटरी सेव्हर"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"बॅटरी पुन्हा कमी होईपर्यंत बॅटरी सेव्हर पुन्हा अॅक्टिव्हेट होणार नाही"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"बॅटरी पुरेशा पातळीवर चार्ज झालेली आहे. बॅटरी पुन्हा कमी होईपर्यंत बॅटरी सेव्हर पुन्हा अॅक्टिव्हेट होणार नाही."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"फोन <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> चार्ज झाला"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"टॅबलेट <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> चार्ज झाले"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"डिव्हाइस <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> चार्ज झाले"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"बॅटरी सेव्हर बंद आहे. वैशिष्ट्ये मर्यादित नाहीत."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"बॅटरी सेव्हर बंद केलेला आहे. वैशिष्ट्ये मर्यादित नाहीत."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 1386e7a6802d..a29e363d56c7 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"mengakses kalendar"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"menghantar dan melihat mesej SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Storan"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"mengakses foto, media dan fail pada peranti anda"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"rakam audio"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Boleh ketik, leret, cubit dan laksanakan gerak isyarat lain."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gerak isyarat cap jari"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Boleh menangkap gerak isyarat yang dilakukan pada penderia cap jari peranti."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"lumpuhkan atau ubah suai bar status"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"jadi bar status"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Naikkan kelantangan melebihi paras yang disyokorkan?\n\nMendengar pada kelantangan yang tinggi untuk tempoh yang lama boleh merosakkan pendengaran anda."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Kebolehaksesan?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Apabila pintasan dihidupkan, tindakan menekan kedua-dua butang kelantangan selama 3 saat akan memulakan ciri kebolehaksesan.\n\n Ciri kebolehaksesan semasa:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Anda boleh menukar ciri itu dalam Tetapan > Kebolehaksesan."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Kosong"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit pintasan"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Batal"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Matikan pintasan"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gunakan Pintasan"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Penyongsangan Warna"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Hidupkan profil kerja?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Apl kerja, pemberitahuan, data dan ciri profil kerja anda yang lain akan dihidupkan"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Hidupkan"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Apl ini dibina untuk versi Android yang lebih lama dan mungkin tidak berfungsi dengan betul. Cuba semak kemas kini atau hubungi pembangun."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Semak kemas kini"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Anda mempunyai mesej baharu"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateri mungkin habis sebelum pengecasan biasa"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Penjimat Bateri diaktifkan untuk memanjangkan hayat bateri"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Penjimat Bateri"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Penjmat Bateri tidak akan diaktifkan semula sehingga bateri rendah sekali lagi"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Bateri sudah dicas pada aras yang mencukupi Penjimat Bateri tidak akan diaktifkan semula sehingga bateri rendah sekali lagi."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefon dicas <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet dicas <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Peranti dicas <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Penjimat Bateri dimatikan. Ciri tidak lagi dihadkan."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Penjimat Bateri dimatikan. Ciri tidak lagi dihadkan."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplikasi Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fail"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index ff08a592a906..a53deafd6fd8 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"သင့်ပြက္ခဒိန်အား ဝင်ရောက်သုံးရန်"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS စာတိုစနစ်"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS စာများကို ပို့ကာ ကြည့်မည်"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"သိုလှောင်မှုများ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"သင့်ဖုန်းရှိ ဓာတ်ပုံများ၊ မီဒီယာနှင့် ဖိုင်များအား ဝင်သုံးပါ"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"မိုက်ခရိုဖုန်း"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"အသံဖမ်းခြင်း"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"တို့ခြင်း၊ ပွတ်ဆွဲခြင်း၊ နှင့် အခြား လက်ဟန်များကို အသုံးပြုနိုင်ပါသည်။"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"လက်ဗွေဟန်များ"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"စက်ပစ္စည်း၏ လက်ဗွေအာရုံခံကိရိယာတွင် လုပ်ဆောင်ထားသည့် လက်ဟန်များကို မှတ်သားထားနိုင်သည်။"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"အသံကို အကြံပြုထားသည့် ပမာဏထက် မြှင့်ပေးရမလား?\n\nအသံကို မြင့်သည့် အဆင့်မှာ ကြာရှည်စွာ နားထောင်ခြင်းက သင်၏ နားကို ထိခိုက်စေနိုင်သည်။"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ်ကို အသုံးပြုလိုပါသလား။"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ဖြတ်လမ်းလင့်ခ်ကို ဖွင့်ထားစဉ် အသံအတိုးအလျှော့ခလုတ် နှစ်ခုစလုံးကို ၃ စက္ကန့်ခန့် ဖိထားခြင်းဖြင့် အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုကို ဖွင့်နိုင်သည်။\n\n လက်ရှိ အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှု−\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ဝန်ဆောင်မှုကို ဆက်တင်များ > အများသုံးစွဲနိုင်မှုတွင် ပြောင်းလဲနိုင်ပါသည်။"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"အလွတ်"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ဖြတ်လမ်းများကို တည်းဖြတ်ရန်"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"မလုပ်တော့"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ဖြတ်လမ်းလင့်ခ်ကို ပိတ်ရန်"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ဖြတ်လမ်းလင့်ခ်ကို သုံးရန်"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"အရောင် ပြောင်းပြန်လှန်ခြင်း"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"အလုပ်ပရိုဖိုင် ဖွင့်လိုသလား။"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"သင်၏ အလုပ်အက်ပ်၊ အကြောင်းကြားချက်၊ ဒေတာနှင့် အခြားအလုပ်ပရိုဖိုင် ဝန်ဆောင်မှုများကို ဖွင့်လိုက်ပါမည်"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ဖွင့်ပါ"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ဤအက်ပ်ကို Android ဗားရှင်းဟောင်းအတွက် ပြုလုပ်ထားခြင်းဖြစ်ပြီး ပုံမှန်အလုပ်မလုပ်နိုင်ပါ။ အပ်ဒိတ်များအတွက် ရှာကြည့်ပါ သို့မဟုတ် ဆော့ဖ်ဝဲအင်ဂျင်နီယာကို ဆက်သွယ်ပါ။"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"အပ်ဒိတ်စစ်ရန်"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"သင့်ထံတွင် စာအသစ်များရောက်နေသည်"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ပုံမှန်အားသွင်းမှုမပြုလုပ်မီ ဘက်ထရီကုန်သွားနိုင်သည်"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ဘက်ထရီသက်တမ်းကို တိုးမြှင့်ရန် \'ဘက်ထရီအားထိန်း\' စတင်ပြီးပါပြီ"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ဘက်ထရီ အားထိန်း"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"နောက်တစ်ကြိမ် ဘက်ထရီအားနည်းသွားသည်အထိ \'ဘက်ထရီအားထိန်း\' ပြန်ပွင့်မည် မဟုတ်ပါ"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ဘက်ထရီကို လုံလောက်သည့်ပမာဏသို့ အားသွင်းထားပါသည်။ နောက်တစ်ကြိမ် ဘက်ထရီအားနည်းသွားသည်အထိ \'ဘက်ထရီအားထိန်း\' ပြန်ပွင့်မည် မဟုတ်ပါ။"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ဖုန်း <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> အားသွင်းထားသည်"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"တက်ဘလက် <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> အားသွင်းထားသည်"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"စက်ပစ္စည်း <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> အားသွင်းထားသည်"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"\'ဘက်ထရီအားထိန်း\' ကိုပိတ်ထားသည်။ ဝန်ဆောင်မှုများကို ကန့်သတ်မထားတော့ပါ။"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"\'ဘက်ထရီ အားထိန်း\' ပိတ်ထားသည်။ ဝန်ဆောင်မှုများကို ကန့်သတ်မထားတော့ပါ။"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 3e236798d657..ee16f90e6077 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"åpne kalenderen din"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"sende og lese SMS-meldinger"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Lagring"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"åpne bilder, medieinnhold og filer på enheten din"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ta opp lyd"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan trykke, sveipe, klype og gjøre andre bevegelser."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Bevegelser på fingeravtrykkssensor"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan fange inn bevegelser som utføres på enhetens fingeravtrykkssensor."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller endre statusfeltet"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vise appen i statusfeltet"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du øke volumet til over anbefalt nivå?\n\nHvis du hører på et høyt volum over lengre perioder, kan det skade hørselen din."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruke tilgjengelighetssnarveien?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Når snarveien er på, starter en tilgjengelighetsfunksjon når du trykker inn begge volumknappene i tre sekunder.\n\n Nåværende tilgjengelighetsfunksjon:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan endre funksjonen i Innstillinger > Tilgjengelighet."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tøm"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Endre snarveier"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Avbryt"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Slå av snarveien"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Bruk snarveien"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Fargeinvertering"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Vil du slå på jobbprofilen?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Jobbappene dine samt varsler, data og andre funksjoner i jobbprofilen din blir slått på"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Slå på"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Denne appen er utviklet for en eldre versjon av Android og fungerer kanskje ikke som den skal. Prøv å se etter oppdateringer, eller kontakt utvikleren."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Se etter oppdateringer"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nye meldinger"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batteriet kan gå tomt før den vanlige ladingen"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterisparing er aktivert for å forlenge batterilevetiden"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterisparing"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Batterisparing blir ikke aktivert igjen før batteriet er lavt"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Batteriet er blitt ladet til et tilstrekkelig nivå. Batterisparing blir ikke aktivert igjen før batteriet er lavt."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefonen er <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ladet"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Nettbrettet er <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ladet"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Enheten er <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ladet"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Batterisparing er av. Funksjoner begrenses ikke lenger."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Batterisparing er slått av. Funksjoner begrenses ikke lenger."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Mappe"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android-app"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fil"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index d7e121cac6fb..1b85b28e6a61 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"तपाईंको पात्रोमाथि पहुँच गर्नुहोस्"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS सन्देशहरू पठाउनुहोस् र हेर्नुहोस्"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"भण्डारण"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"तपाईंको यन्त्रमा तस्बिर, मिडिया, र फाइलहरूमाथि पहुँच गर्नुहोस्"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"माइक्रोफोन"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"अडियो रेकर्ड गर्नुहोस्"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ट्याप, स्वाइप गर्न, थिच्न र अन्य इसाराहरू सम्बन्धी कार्य गर्न सक्छ"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"फिंगरप्रिन्टका इसाराहरू"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"यसले यन्त्रको फिंगरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्न सक्छ।"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन अनुप्रयोगलाई अनुमति दिन्छ।"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"वस्तुस्थिति पट्टी हुन दिनुहोस्"</string> @@ -1616,6 +1621,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"सिफारिस तहभन्दा आवाज ठुलो गर्नुहुन्छ?\n\nलामो समय सम्म उच्च आवाजमा सुन्दा तपाईँको सुन्ने शक्तिलाई हानी गर्न सक्छ।"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"पहुँच सम्बन्धी सर्टकट प्रयोग गर्ने हो?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"सर्टकट सक्रिय हुँदा, भोल्युमका दुवै बटनहरूलाई ३ सेकेन्डसम्म थिची राख्नाले पहुँच सम्बन्धी कुनै सुविधा सुरु हुनेछ।\n\n हाल व्यवहारमा रहेको पहुँच सम्बन्धी सुविधा:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n तपाईं सेटिङहरू अन्तर्गतको पहुँच सम्बन्धी विकल्पमा गई उक्त सुविधालाई बदल्न सक्नुहुन्छ।"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"खाली"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"सर्टकटहरू सम्पादन गर्नुहोस्"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"रद्द गर्नुहोस्"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"सर्टकटलाई निष्क्रिय पार्नुहोस्"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"सर्टकट प्रयोग गर्नुहोस्"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"रङ्ग उल्टाउने सुविधा"</string> @@ -1851,6 +1859,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"कार्य प्रोफाइल सक्रिय गर्ने?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"तपाईंका कार्यसम्बन्धी अनुप्रयोग, सूचना, डेटा र कार्य प्रोफाइलका अन्य सुविधाहरू सक्रिय गरिने छन्"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"सक्रिय गर्नुहोस्"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"यो अनुप्रयोग Android को पुरानो संस्करणका लागि बनाइएको हुनाले यसले सही ढङ्गले काम नगर्न सक्छ। अद्यावधिकहरू उपलब्ध छन् वा छैनन् भनी जाँच गरी हेर्नुहोस् वा यसको विकासकर्तालाई सम्पर्क गर्नुहोस्।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अद्यावधिक उपलब्ध छ वा छैन भनी जाँच गर्नुहोस्"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"तपाईंलाई नयाँ सन्देश आएको छ"</string> @@ -1961,13 +1973,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"प्रायः चार्ज गर्ने समय हुनुभन्दा पहिले नै ब्याट्री सकिन सक्छ"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ब्याट्रीको आयु बढाउन ब्याट्री सेभर सक्रिय गरियो"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ब्याट्री सेभर"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"फेरि ब्याट्री कम नभएसम्म ब्याट्री सेभर पुनः सक्रिय हुने छैन"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ब्याट्री पर्याप्त हुने गरी चार्ज गरिएको छ। ब्याट्रीको चार्ज कम नभएसम्म ब्याट्री सेभर पुनः सक्रिय हुने छैन।"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"फोन <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> चार्ज भयो"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ट्याब्लेट <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> चार्ज भयो"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"यन्त्र <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> चार्ज गरियो"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"ब्याट्री सेभर निष्क्रिय छ। सुविधाहरूलाई अब उप्रान्त प्रतिबन्ध लगाइँदैन।"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"ब्याट्री सेभर निष्क्रिय पारियो। सुविधाहरूलाई अब उप्रान्त प्रतिबन्ध लगाइँदैन।"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index b342941ebadb..dece9ae55b7f 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"toegang krijgen tot je agenda"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"Sms"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"sms\'jes verzenden en bekijken"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Opslagruimte"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Bestanden en media"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"toegang krijgen tot foto\'s, media en bestanden op je apparaat"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microfoon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"audio opnemen"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan tikken, vegen, samenknijpen en andere gebaren uitvoeren."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Vingerafdrukgebaren"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebaren registreren die op de vingerafdruksensor van het apparaat worden getekend."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot maken"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan een screenshot van het scherm maken."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"statusbalk uitschakelen of wijzigen"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Hiermee kan de app de statusbalk uitschakelen of systeempictogrammen toevoegen en verwijderen."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"de statusbalk zijn"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Volume verhogen tot boven het aanbevolen niveau?\n\nAls je langere tijd op hoog volume naar muziek luistert, raakt je gehoor mogelijk beschadigd."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Snelkoppeling toegankelijkheid gebruiken?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Wanneer de snelkoppeling is ingeschakeld, kun je drie seconden op beide volumeknoppen drukken om een toegankelijkheidsfunctie te starten.\n\n Huidige toegankelijkheidsfunctie:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Je kunt de functie wijzigen in Instellingen > Toegankelijkheid."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Leeg"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Snelkoppelingen bewerken"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Annuleren"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Sneltoets uitschakelen"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sneltoets gebruiken"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Kleurinversie"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Werkprofiel inschakelen?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Je werk-apps, meldingen, gegevens en andere functies van je werkprofiel worden uitgeschakeld"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Inschakelen"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"App is niet beschikbaar"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is momenteel niet beschikbaar."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Deze app is ontwikkeld voor een oudere versie van Android en werkt mogelijk niet op de juiste manier. Controleer op updates of neem contact op met de ontwikkelaar."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Controleren op update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Je hebt nieuwe berichten"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"De batterij raakt mogelijk leeg voordat deze normaal gesproken wordt opgeladen"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterijbesparing is geactiveerd om de batterijduur te verlengen"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterijbesparing"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Batterijbesparing kan pas opnieuw worden geactiveerd zodra de batterij bijna leeg is"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Batterij is voldoende opgeladen. Batterijbesparing kan pas opnieuw worden geactiveerd zodra de batterij bijna leeg is."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefoon is <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> opgeladen"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet is <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> opgeladen"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Apparaat is <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> opgeladen"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Batterijbesparing staat uit. Functies worden niet meer beperkt."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Batterijbesparing is uitgeschakeld. Functies worden niet meer beperkt."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterijbesparing is uitgeschakeld"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefoon is voldoende opgeladen. Functies worden niet meer beperkt."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Tablet is voldoende opgeladen. Functies worden niet meer beperkt."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Apparaat is voldoende opgeladen. Functies worden niet meer beperkt."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Map"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android-app"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Bestand"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index b12c6553a7ae..2018a7fd4a27 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ଆପଣଙ୍କ କ୍ୟାଲେଣ୍ଡର୍ ଆକ୍ସେସ୍ କରେ"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ମେସେଜ୍ ପଠାନ୍ତୁ ଓ ଦେଖନ୍ତୁ"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"ଷ୍ଟୋରେଜ୍"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"ଆପଣଙ୍କ ଡିଭାଇସ୍ରେ ଥିବା ଫଟୋ, ମିଡିଆ ଓ ଫାଇଲ୍ ଆକ୍ସେସ୍ କରେ"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"ମାଇକ୍ରୋଫୋନ୍"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ଅଡିଓ ରେକର୍ଡ କରେ"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ଟାପ୍, ସ୍ୱାଇପ୍, ପିଞ୍ଚ ଓ ଅନ୍ୟାନ୍ୟ ଜେଶ୍ଚର୍ ସମ୍ପାଦନ କରିପାରିବ।"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ଟିପଚିହ୍ନ ଜେଶ୍ଚର"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ଡିଭାଇସ୍ର ଟିପଚିହ୍ନ ସେନସର୍ ଉପରେ ଜେଶ୍ଚର୍ କ୍ୟାପଚର୍ କାର୍ଯ୍ୟ କରାଯାଇପାରିବ।"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ଷ୍ଟାଟସ୍ ବାର୍କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ଆପ୍କୁ, ସ୍ଥିତି ବାର୍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍ ଆଇକନ୍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ଷ୍ଟାଟସ୍ ବାର୍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ମାତ୍ରା ବଢ଼ାଇ ସୁପାରିଶ ସ୍ତର ବଢ଼ାଉଛନ୍ତି? \n\n ଲମ୍ବା ସମୟ ପର୍ଯ୍ୟନ୍ତ ଉଚ୍ଚ ଶବ୍ଦରେ ଶୁଣିଲେ ଆପଣଙ୍କ ଶ୍ରବଣ ଶକ୍ତି ଖରାପ ହୋଇପାରେ।"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ଆକ୍ସେସବିଲିଟି ଶର୍ଟକଟ୍ ବ୍ୟବହାର କରିବେ?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ସର୍ଟକଟ୍ ଅନ୍ ଥିବା ବେଳେ, ଉଭୟ ଭଲ୍ୟୁମ୍ ବଟନ୍ 3 ସେକେଣ୍ଡ ପାଇଁ ଦବାଇବା ଦ୍ୱାରା ଆକ୍ସେସବିଲିଟି ବୈଶିଷ୍ଟ ଆରମ୍ଭ ହେବ।\n\n ସମ୍ପ୍ରତି ଆକ୍ସେସବିଲିଟି ବୈଶିଷ୍ଟ୍ୟ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ସେଟିଙ୍ଗ ଓ ଆକ୍ସେସବିଲିଟିରେ ଆପଣ ବୈଶିଷ୍ଟ୍ୟ ବଦଳାଇ ପାରିବେ।"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ଖାଲି କରନ୍ତୁ"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ସର୍ଟକଟଗୁଡ଼ିକୁ ସମ୍ପାଦନ କରନ୍ତୁ"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ବାତିଲ୍ କରନ୍ତୁ"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ଶର୍ଟକଟ୍ ବନ୍ଦ କରନ୍ତୁ"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ଶର୍ଟକଟ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"ରଙ୍ଗ ବଦଳାଇବାର ସୁବିଧା"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"ୱର୍କ ପ୍ରୋଫାଇଲ୍କୁ ଚାଲୁ କରିବେ?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"ଆପଣଙ୍କର କାର୍ଯ୍ୟକାରୀ ଆପ୍, ବିଜ୍ଞପ୍ତି, ଡାଟା ଓ ଅନ୍ୟ ୱର୍କ ପ୍ରୋଫାଇଲ୍ଗୁଡ଼ିକ ଚାଲୁ ହୋଇଯିବ"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ଅନ୍ କରନ୍ତୁ"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ଏହି ଆପ୍କୁ Androidର ପୁରୁଣା ଭର୍ସନ୍ ପାଇଁ ନିର୍ମାଣ କରାଯାଇଥିଲା ଏବଂ ଠିକ୍ ଭାବେ କାମ କରିନପାରେ। ଏହାପାଇଁ ଅପଡେଟ୍ ଅଛି କି ନାହିଁ ଯାଞ୍ଚ କରନ୍ତୁ କିମ୍ବା ଡେଭେଲପର୍ଙ୍କ ସହିତ ସମ୍ପର୍କ କରନ୍ତୁ।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ଅପଡେଟ୍ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ଆପଣଙ୍କ ପାଖରେ ନୂଆ ମେସେଜ୍ ରହିଛି"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ସାଧାରଣ ଭାବରେ ଚାର୍ଜ୍ କରିବା ପୂର୍ବରୁ ବ୍ୟାଟେରୀ ସରିଯାଇପାରେ"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ବ୍ୟାଟେରୀର ସମୟକୁ ବଢ଼ାଇବା ପାଇଁ ବ୍ୟଟେରୀ ସେଭର୍କୁ କାର୍ଯ୍ୟକାରୀ କରାଯାଇଛି"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ବ୍ୟାଟେରୀ ସେଭର୍"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"ବ୍ୟାଟେରୀ ଟାର୍ଜ କମ୍ ନହେବା ପର୍ଯ୍ୟନ୍ତ ବ୍ୟାଟେରୀ ସେଭର୍ ପୁନଃସକ୍ରିୟ ହୁଏ ନାହିଁ"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ବ୍ୟାଟେରୀ ଏକ ପର୍ଯ୍ୟାପ୍ତ ସ୍ତର ପର୍ଯ୍ୟନ୍ତ ଚାର୍ଜ ହୋଇଛି। ବ୍ୟାଟେରୀ ପୁଣି କମ୍ ନହେବା ପର୍ଯ୍ୟନ୍ତ ବ୍ୟାଟେରୀ ସେଭର୍ ପୁନଃସକ୍ରିୟ ହେବନାହିଁ।"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ଫୋନ୍ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ଚାର୍ଜ ହୋଇଛି"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ଟାବ୍ଲେଟ୍ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ଚାର୍ଜ ହୋଇଛି"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"ଡିଭାଇସ୍ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ଚାର୍ଜ ହୋଇଛି"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"ବ୍ୟାଟେରୀ ସେଭର୍ ବନ୍ଦ ଅଛି ବୈଶିଷ୍ଟ୍ୟ ଆଉ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ।"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"ବ୍ୟାଟେରୀ ସେଭର୍ ବନ୍ଦ ଅଛି। ବୈଶିଷ୍ଟ୍ୟ ଆଉ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ।"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 72e695efad80..552f77d9307b 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ਸੁਨੇਹੇ ਭੇਜੋ ਅਤੇ ਦੇਖੋ"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"ਸਟੋਰੇਜ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਫ਼ਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨਾ"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">" ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"ਟੈਪ ਕਰ ਸਕਦੀ ਹੈ, ਸਵਾਈਪ ਕਰ ਸਕਦੀ ਹੈ, ਚੂੰਢੀ ਭਰ ਸਕਦੀ ਹੈ, ਅਤੇ ਹੋਰ ਸੰਕੇਤ ਕਰ ਸਕਦੀ ਹੈ।"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੰਕੇਤ"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ਡੀਵਾਈਸਾਂ ਦੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ \'ਤੇ ਕੀਤੇ ਗਏ ਸੰਕੇਤਾਂ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੇ ਹਨ।"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ਸਥਿਤੀ ਪੱਟੀ ਬੰਦ ਕਰੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਨੂੰ ਚਾਲੂ ਕਰਨ ਜਾਂ ਸਿਸਟਮ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ਕੀ ਵੌਲਿਊਮ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੇ ਪੱਧਰ ਤੋਂ ਵਧਾਉਣੀ ਹੈ?\n\nਲੰਮੇ ਸਮੇਂ ਤੱਕ ਉੱਚ ਵੌਲਿਊਮ ਤੇ ਸੁਣਨ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ।"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਵਰਤਣਾ ਹੈ?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਅਵਾਜ਼ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।\n\n ਵਰਤਮਾਨ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ > ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ਖਾਲੀ"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ਸ਼ਾਰਟਕੱਟਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ਰੱਦ ਕਰੋ"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ਸ਼ਾਰਟਕੱਟ ਬੰਦ ਕਰੋ"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ਸ਼ਾਰਟਕੱਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"ਰੰਗ ਦੀ ਉਲਟੀ ਤਰਤੀਬ"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"ਕੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਚਾਲੂ ਕਰਨੀ ਹੈ?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"ਤੁਹਾਡੀਆਂ ਕਾਰਜ-ਸਥਾਨ ਐਪਾਂ, ਸੂਚਨਾਵਾਂ, ਡਾਟਾ ਅਤੇ ਹੋਰ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚਾਲੂ ਕੀਤੀਆਂ ਜਾਣਗੀਆਂ"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ਚਾਲੂ ਕਰੋ"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ਇਹ ਐਪ Android ਦੇ ਕਿਸੇ ਵਧੇਰੇ ਪੁਰਾਣੇ ਵਰਜਨ ਲਈ ਬਣਾਈ ਗਈ ਸੀ ਅਤੇ ਸ਼ਾਇਦ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ। ਅੱਪਡੇਟਾਂ ਲਈ ਜਾਂਚ ਕਰੋ ਜਾਂ ਵਿਕਾਸਕਾਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ਅੱਪਡੇਟ ਦੀ ਜਾਂਚ ਕਰੋ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ਤੁਹਾਨੂੰ ਨਵੇਂ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਹੋਏ ਹਨ"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ਬੈਟਰੀ ਚਾਰਜ ਕਰਨ ਦੇ ਮਿੱਥੇ ਸਮੇਂ ਤੋਂ ਪਹਿਲਾਂ ਸ਼ਾਇਦ ਬੈਟਰੀ ਖਤਮ ਹੋ ਜਾਵੇ"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ਬੈਟਰੀ ਲਾਈਫ਼ ਵਧਾਉਣ ਲਈ ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"ਬੈਟਰੀ ਸੇਵਰ"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"ਬੈਟਰੀ ਸੇਵਰ ਦੁਬਾਰਾ ਬੈਟਰੀ ਘਟਣ ਤੱਕ ਮੁੜ-ਕਿਰਿਆਸ਼ੀਲ ਨਹੀਂ ਹੁੰਦਾ ਹੈ"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ਬੈਟਰੀ ਲੋੜੀਂਦੇ ਪੱਧਰ ਤੱਕ ਚਾਰਜ ਹੋ ਗਈ ਹੈ। ਬੈਟਰੀ ਸੇਵਰ ਦੁਬਾਰਾ ਬੈਟਰੀ ਘਟਣ ਤੱਕ ਮੁੜ-ਕਿਰਿਆਸ਼ੀਲ ਨਹੀਂ ਹੁੰਦਾ।"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ਫ਼ੋਨ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ਚਾਰਜ ਹੋਇਆ"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ਟੈਬਲੈੱਟ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ਚਾਰਜ ਹੋਇਆ"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"ਡੀਵਾਈਸ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ਚਾਰਜ ਹੋਇਆ"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਹੈ। ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਹੁਣ ਪ੍ਰਤਿਬੰਧਿਤ ਨਹੀਂ ਹਨ।"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਕੀਤਾ ਗਿਆ। ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਹੁਣ ਪ੍ਰਤਿਬੰਧਿਤ ਨਹੀਂ ਹਨ।"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 4f6e74824992..5f94b185e427 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -293,7 +293,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"dostęp do kalendarza"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"wysyłanie i wyświetlanie SMS‑ów"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Pamięć"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"dostęp do zdjęć, multimediów i plików na Twoim urządzeniu"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"nagrywanie dźwięku"</string> @@ -319,6 +320,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Obsługuje kliknięcia, przesunięcia, ściągnięcia palców i inne gesty."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gesty związane z odciskiem palca"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Może przechwytywać gesty wykonywane na czytniku linii papilarnych w urządzeniu."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"wyłączanie lub zmienianie paska stanu"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"działanie jako pasek stanu"</string> @@ -1654,6 +1659,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zwiększyć głośność ponad zalecany poziom?\n\nSłuchanie głośno przez długi czas może uszkodzić Twój słuch."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Użyć skrótu do ułatwień dostępu?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Gdy skrót jest włączony, jednoczesne naciśnięcie przez trzy sekundy obu klawiszy sterowania głośnością uruchomi funkcję ułatwień dostępu.\n\nBieżąca funkcja ułatwień dostępu:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nFunkcję możesz zmienić, wybierając Ustawienia > Ułatwienia dostępu."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Puste"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edytuj skróty"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Anuluj"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Wyłącz skrót"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Użyj skrótu"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Odwrócenie kolorów"</string> @@ -1909,6 +1917,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Włączyć profil służbowy?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Aplikacje do pracy, powiadomienia, dane i inne funkcje profilu do pracy zostaną włączone"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Włącz"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ta aplikacja jest na starszą wersję Androida i może nie działać prawidłowo. Sprawdź dostępność aktualizacji lub skontaktuj się z programistą."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Sprawdź dostępność aktualizacji"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Masz nowe wiadomości"</string> @@ -2021,13 +2033,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria może się wyczerpać przed zwykłą porą ładowania"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Włączono Oszczędzanie baterii, by wydłużyć czas pracy na baterii"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Oszczędzanie baterii"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Oszczędzanie baterii nie włączy się ponownie do czasu rozładowania baterii"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Poziom naładowania baterii jest wystarczający. Oszczędzanie baterii nie włączy się ponownie do czasu rozładowania baterii."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Poziom naładowania telefonu: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Poziom naładowania tabletu: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Poziom naładowania urządzenia: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Oszczędzanie baterii jest wyłączone. Funkcje nie są już ograniczone."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Oszczędzanie baterii zostało wyłączone. Funkcje nie są już ograniczone."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplikacja na Androida"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Plik"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index f4c9e3436eb7..567d6d4ba476 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"acesse sua agenda"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"envie e veja mensagens SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Armazenamento"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Arquivos e mídia"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"acesse fotos, mídia e arquivos do dispositivo"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microfone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"grave áudio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Toque, deslize, faça gestos de pinça e faça outros gestos."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos de impressão digital"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando o atalho está ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade.\n\n Recurso de acessibilidade atual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n É possível alterar o recurso em Configurações > Acessibilidade."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Limpar"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Ativar o perfil de trabalho?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Seus apps, notificações, dados e outros recursos do perfil de trabalho serão ativados"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"O app não está disponível"</string> + <string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Este app foi criado para uma versão mais antiga do Android e pode não funcionar corretamente. Tente verificar se há atualizações ou entre em contato com o desenvolvedor."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Procurar atualizações"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Você tem mensagens novas"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"A bateria pode acabar antes da recarga normal"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"A Economia de bateria foi ativada para aumentar a duração da carga"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Economia de bateria"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"A Economia de bateria só será reativada quando a bateria estiver acabando novamente"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"A bateria foi carregada até o nível suficiente. A Economia de bateria só será reativada quando a bateria estiver acabando novamente."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Smartphone <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> carregado"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> carregado"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Dispositivo <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> carregado"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Economia de bateria desativada. Os recursos não estão mais restritos."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Economia de bateria desativada. Os recursos não estão mais restritos."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"\"Economia de bateria\" desativada"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Não há carga suficiente no smartphone. Os recursos não estão mais restritos."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Não há carga suficiente no tablet. Os recursos não estão mais restritos."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Não há carga suficiente no dispositivo. Os recursos não estão mais restritos."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Pasta"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplicativo Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Arquivo"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 65913cec79ac..b746c923a4d9 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"aceder ao calendário"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"enviar e ver mensagens SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Armazenamento"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Ficheiros e multimédia"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"aceder a fotos, multimédia e ficheiros no dispositivo"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microfone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"gravar áudio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"É possível tocar, deslizar rapidamente, juntar os dedos e realizar outros gestos"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos de impressão digital"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode capturar gestos realizados no sensor de impressões digitais do dispositivo."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tirar captura de ecrã"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"É possível tirar uma captura de ecrã."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar barra de estado"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite à aplicação desativar a barra de estado ou adicionar e remover ícones do sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ser apresentada na barra de estado"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir com um volume elevado durante longos períodos poderá ser prejudicial para a sua audição."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Pretende utilizar o atalho de acessibilidade?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando o atalho está ativado, premir ambos os botões de volume durante 3 segundos inicia uma funcionalidade de acessibilidade.\n\n Funcionalidade de acessibilidade atual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Pode alterar a funcionalidade em Definições > Acessibilidade."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Esvaziar"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atalho"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string> @@ -1731,7 +1736,7 @@ <string name="restr_pin_try_later" msgid="5897719962541636727">"Tente novamente mais tarde"</string> <string name="immersive_cling_title" msgid="2307034298721541791">"Visualização de ecrã inteiro"</string> <string name="immersive_cling_description" msgid="7092737175345204832">"Para sair, deslize rapidamente para baixo a partir da parte superior."</string> - <string name="immersive_cling_positive" msgid="7047498036346489883">"Compreendi"</string> + <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string> <string name="done_label" msgid="7283767013231718521">"Concluído"</string> <string name="hour_picker_description" msgid="5153757582093524635">"Controlo de deslize circular das horas"</string> <string name="minute_picker_description" msgid="9029797023621927294">"Controlo de deslize circular dos minutos"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Ativar o perfil de trabalho?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"As aplicações de trabalho, as notificações, os dados e outras funcionalidades do perfil de trabalho serão desativados"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"A app não está disponível"</string> + <string name="app_blocked_message" msgid="542972921087873023">"De momento, a app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta aplicação foi concebida para uma versão mais antiga do Android e pode não funcionar corretamente. Experimente verificar se existem atualizações ou contacte o programador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Verificar se existem atualizações"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tem mensagens novas"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Pode ficar sem bateria antes do carregamento habitual"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Poupança de bateria ativada para prolongar a duração da bateria"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Poupança de bateria"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"A Poupança de bateria não será reativada até a bateria estar novamente fraca"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"A bateria foi carregada até um nível suficiente. A Poupança de bateria não será reativada até a bateria estar novamente fraca."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"O telemóvel tem um nível de carga de <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"O tablet tem um nível de carga de <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"O dispositivo tem um nível de carga de <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"A Poupança de bateria está desativada. As funcionalidades já não estão restritas."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"A Poupança de bateria está desativada. As funcionalidades já não estão restritas."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"A Poupança de bateria está desativada"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"O telemóvel tem carga suficiente. As funcionalidades já não estão restritas."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"O tablet tem carga suficiente. As funcionalidades já não estão restritas."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"O dispositivo tem carga suficiente. As funcionalidades já não estão restritas."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Pasta"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplicação para Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Ficheiro"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index f4c9e3436eb7..567d6d4ba476 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"acesse sua agenda"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"envie e veja mensagens SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Armazenamento"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Arquivos e mídia"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"acesse fotos, mídia e arquivos do dispositivo"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microfone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"grave áudio"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Toque, deslize, faça gestos de pinça e faça outros gestos."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos de impressão digital"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando o atalho está ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade.\n\n Recurso de acessibilidade atual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n É possível alterar o recurso em Configurações > Acessibilidade."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Limpar"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Cancelar"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Ativar o perfil de trabalho?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Seus apps, notificações, dados e outros recursos do perfil de trabalho serão ativados"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"O app não está disponível"</string> + <string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Este app foi criado para uma versão mais antiga do Android e pode não funcionar corretamente. Tente verificar se há atualizações ou entre em contato com o desenvolvedor."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Procurar atualizações"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Você tem mensagens novas"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"A bateria pode acabar antes da recarga normal"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"A Economia de bateria foi ativada para aumentar a duração da carga"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Economia de bateria"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"A Economia de bateria só será reativada quando a bateria estiver acabando novamente"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"A bateria foi carregada até o nível suficiente. A Economia de bateria só será reativada quando a bateria estiver acabando novamente."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Smartphone <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> carregado"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> carregado"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Dispositivo <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> carregado"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Economia de bateria desativada. Os recursos não estão mais restritos."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Economia de bateria desativada. Os recursos não estão mais restritos."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"\"Economia de bateria\" desativada"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Não há carga suficiente no smartphone. Os recursos não estão mais restritos."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Não há carga suficiente no tablet. Os recursos não estão mais restritos."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Não há carga suficiente no dispositivo. Os recursos não estão mais restritos."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Pasta"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplicativo Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Arquivo"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 5b50ef733a5f..5b1153750547 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -290,7 +290,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"acceseze calendarul"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"trimită și să vadă mesajele SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Stocare"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"acceseze fotografiile, conținutul media și fișierele de pe dispozitiv"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Microfon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"înregistreze sunet"</string> @@ -316,6 +317,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Poate atinge, glisa, ciupi sau folosi alte gesturi."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gesturi ce implică amprente"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Poate reda gesturile făcute pe senzorul de amprentă al dispozitivului."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"dezactivare sau modificare bare de stare"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"să fie bara de stare"</string> @@ -1632,6 +1637,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ridicați volumul mai sus de nivelul recomandat?\n\nAscultarea la volum ridicat pe perioade lungi de timp vă poate afecta auzul."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utilizați comanda rapidă pentru accesibilitate?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Când comanda rapidă este activată, dacă apăsați ambele butoane de volum timp de 3 secunde, veți lansa o funcție de accesibilitate.\n\n Funcția actuală de accesibilitate:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puteți schimba funcția în Setări > Accesibilitate."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Goliți"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editați comenzile rapide"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Anulați"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Dezactivați comanda rapidă"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizați comanda rapidă"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inversarea culorilor"</string> @@ -1877,6 +1885,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Activați profilul de serviciu?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Se vor activa aplicațiile dvs. de serviciu, notificările, datele și alte funcții ale profilului de serviciu"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Activați"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Această aplicație a fost creată pentru o versiune Android mai veche și este posibil să nu funcționeze corect. Încercați să căutați actualizări sau contactați dezvoltatorul."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Căutați actualizări"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Aveți mesaje noi"</string> @@ -1988,13 +2000,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria se poate descărca înainte de încărcarea obișnuită"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Economisirea bateriei este activată pentru a prelungi durata de funcționare a bateriei"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Economisirea bateriei"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Economisirea bateriei se va reactiva când bateria va fi descărcată din nou"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Bateria s-a încărcat la un nivel suficient. Economisirea bateriei se va reactiva când bateria va fi descărcată din nou."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefonul este încărcat <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tableta este încărcată <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Dispozitivul este încărcat <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Economisirea bateriei este dezactivată. Funcțiile nu mai sunt limitate."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Economisirea bateriei a fost dezactivată. Funcțiile nu mai sunt limitate."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Dosar"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplicație Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fișier"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 9e8e13af4eed..fa283d82b209 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -293,7 +293,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"доступ к календарю"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"отправлять и просматривать SMS-сообщения"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Хранилище"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"доступ к фото, мультимедиа и файлам на вашем устройстве"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"записывать аудио"</string> @@ -319,6 +320,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Может выполнять жесты нажатия, пролистывания, масштабирования и т. д."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Регистрировать жесты на сканере отпечатков пальцев"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Использовать сканер отпечатков пальцев для дополнительных жестов."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"Отключение/изменение строки состояния"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"Замена строки состояния"</string> @@ -1654,6 +1659,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Установить громкость выше рекомендуемого уровня?\n\nВоздействие громкого звука в течение долгого времени может привести к повреждению слуха."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Использовать быстрое включение?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Чтобы использовать функцию специальных возможностей, когда она включена, нажмите и удерживайте три секунды обе кнопки регулировки громкости.\n\nТекущая функция специальных возможностей:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nВы можете изменить ее в разделе \"Настройки > Специальные возможности\"."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Очистить"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Изменить быстрые клавиши"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Отмена"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Деактивировать быстрое включение"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Использовать быстрое включение"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Инверсия цветов"</string> @@ -1909,6 +1917,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Включить рабочий профиль?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Будут включены корпоративные приложения, уведомления, данные и другие функции рабочего профиля."</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Включить"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Это приложение было создано для более ранней версии Android и может работать со сбоями. Проверьте наличие обновлений или свяжитесь с разработчиком."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверить обновления"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Новые сообщения"</string> @@ -2021,13 +2033,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея может разрядиться"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Чтобы увеличить время работы от батареи, был включен режим энергосбережения."</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Режим энергосбережения"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Режим энергосбережения будет включен снова при низком уровне заряда батареи."</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Батарея заряжена достаточно. Режим энергосбережения будет включен снова при низком уровне заряда батареи."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Телефон заряжен на <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Планшет заряжен на <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Устройство заряжено на <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Режим энергосбережения выключен. Функции больше не ограничены."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Режим энергосбережения выключен. Функции больше не ограничены."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index a28e0362fb75..3899cd79c62d 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ඔබේ දින දර්ශනයට පිවිසෙන්න"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"කෙටි පණිවිඩ"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS පණිවිඩ යැවීම සහ බැලීම"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"ආචයනය"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"ඔබේ උපාංගයේ ඇති ඡායාරූප, මාධ්ය සහ ගොනුවලට පිවිසීම"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"මයික්රොෆෝනය"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ශ්රව්ය පටිගත කරන්න"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"තට්ටු කිරීමට, ස්වයිප් කිරීමට, පින්ච් කිරීමට, සහ වෙනත් අභින සිදු කිරීමට හැකිය."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ඇඟිලි සලකුණු ඉංගිත"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"උපාංගයෙහි ඇඟිලි සලකුණු සංවේදකය මත සිදු කරන ඉංගිත ග්රහණය කළ හැකිය."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"තත්ව තීරුව අක්රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"තත්ත්ව තීරුව බවට පත්වීම"</string> @@ -1612,6 +1617,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"නිර්දේශිතයි මට්ටමට වඩා ශබ්දය වැඩිද?\n\nදිගු කාලයක් සඳහා ඉහළ ශබ්දයක් ඇසීමෙන් ඇතැම් විට ඔබගේ ඇසීමට හානි විය හැක."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ප්රවේශ්යතා කෙටිමඟ භාවිතා කරන්නද?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"කෙටිමඟ සක්රිය විට, හඬ බොත්තම් දෙකම තත්පර 3ක් අල්ලාගෙන සිටීමෙන් ප්රවේශ්යත අංගයක් ඇරඹේ.\n\n වත්මන් ප්රවේශ්යතා අංගය:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n සැකසීම් > ප්රවේශ්යතාව තුළ ඔබට අංගය වෙනස් කළ හැක."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"හිස්"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"කෙටිමං සංස්කරණ කරන්න"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"අවලංගු කරන්න"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"කෙටිමඟ ක්රියාවිරහිත කරන්න"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"කෙටිමඟ භාවිතා කරන්න"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"වර්ණ අපවර්තනය"</string> @@ -1847,6 +1855,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"කාර්යාල පැතිකඩ ක්රියාත්මක කරන්නද?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"ඔබගේ වැඩ යෙදුම්, දැනුම්දීම්, දත්ත සහ වෙනත් කාර්යාල පැතිකඩ විශේෂාංග ක්රියාත්මක කරනු ඇත"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ක්රියාත්මක කරන්න"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"මෙම යෙදුම Android හි පැරණි අනුවාදයක් සඳහා තනා ඇති අතර නිසියාකාරව ක්රියා නොකරනු ඇත. යාවත්කාලීන සඳහා පරික්ෂා කිරීම උත්සාහ කරන්න, නැතහොත් සංවර්ධක අමතන්න."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"යාවත්කාලීන සඳහා පරික්ෂා කරන්න"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ඔබට නව පණිවිඩ තිබේ"</string> @@ -1957,13 +1969,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"බැටරිය සුපුරුදු ආරෝපණයට පෙර ඉවර විය හැක"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"බැටරි සුරැකුම බැටරි ආයු කාලය දීර්ඝ කිරීමට සක්රිය කෙරිණි"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"බැටරි සුරැකුම"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"බැටරිය නැවතත් අඩු වන තෙක් බැටරි සුරැකුම යළි ක්රියාත්මක නොවේ"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"බැටරිය ප්රමාණවත් මට්ටමකට ආරෝපණ කර ඇත. බැටරිය නැවතත් අඩු වන තෙක් බැටරි සුරැකුම යළි ක්රියාත්මක නොවේ"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"<xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> දුරකථනය ආරෝපණ විය"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"<xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ටැබ්ලටය ආරෝපණ කළා"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"<xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> උපාංගය ආරෝපණ විය"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"බැටරි සුරැකුම අක්රියයි. විශේෂාංග තවදුරටත් සීමිත නොවේ."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"බැටරි සුරැකුම අක්රියයි. විශේෂාංග තවදුරටත් සීමිත නොවේ."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 6bf54b0ddc89..f48368f5ccd6 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -293,7 +293,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"prístup ku kalendáru"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"posielanie a zobrazovanie SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Úložisko"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"prístup k fotkám, médiám a súborom v zariadení"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofón"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"nahrávanie zvuku"</string> @@ -319,6 +320,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Je možné použiť klepnutie, prejdenie, stiahnutie prstami a ďalšie gestá."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestá odtlačkom prsta"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dokáže zaznamenať gestá na senzore odtlačkov prstov zariadenia."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"zakázanie alebo zmeny stavového riadka"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vydávanie sa za stavový riadok"</string> @@ -1654,6 +1659,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšiť hlasitosť nad odporúčanú úroveň?\n\nDlhodobé počúvanie pri vysokej hlasitosti môže poškodiť váš sluch."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použiť skratku dostupnosti?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Keď je skratka zapnutá, stlačením obidvoch tlačidiel hlasitosti na tri sekundy spustíte funkciu dostupnosti.\n\n Aktuálna funkcia dostupnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkciu môžete zmeniť v časti Nastavenia > Dostupnosť."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prázdne"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Upraviť skratky"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Zrušiť"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Vypnúť skratku"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použiť skratku"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzia farieb"</string> @@ -1909,6 +1917,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Zapnúť pracovný profil?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Pracovné aplikácie, upozornenia, dáta a ďalšie funkcie pracovného profilu sa zapnú"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Zapnúť"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Táto aplikácia bola zostavená pre staršiu verziu Androidu a nemusí správne fungovať. Skúste skontrolovať dostupnosť aktualizácií alebo kontaktovať vývojára."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Skontrolovať dostupnosť aktualizácie"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Máte nové správy."</string> @@ -2021,13 +2033,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batéria sa môže vybiť pred obvyklým nabitím"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Bol aktivovaný šetrič batérie na predĺženie výdrže batérie"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Šetrič batérie"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Šetrič batérie sa znova aktivuje až pri nízkej úrovni nabitia batérie"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Batéria bola nabitá na dostatočnú úroveň. Šetrič batérie sa znova aktivuje až pri nízkej úrovni nabitia batérie."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Úroveň nabitia telefónu: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Úroveň nabitia tabletu: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Úroveň nabitia zariadenia: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Šetrič batérie je vypnutý. Funkcie už nie sú obmedzené."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Šetrič batérie bol vypnutý. Funkcie už nie sú obmedzené."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Priečinok"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplikácia pre Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Súbor"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 7aa91f7245ea..6343e0efc7ea 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -293,7 +293,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"dostop do koledarja"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"pošiljanje in ogled sporočil SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Shramba"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"dostop do fotografij, predstavnosti in datotek v napravi"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"snemanje zvoka"</string> @@ -319,6 +320,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Mogoče je izvajanje dotikov, vlečenja, primikanja in razmikanja prstov ter drugih potez."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Poteze po tipalu prstnih odtisov"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Prepoznava poteze, narejene po tipalu prstnih odtisov naprave."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"onemogočanje ali spreminjanje vrstice stanja"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"postane vrstica stanja"</string> @@ -1654,6 +1659,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ali želite povečati glasnost nad priporočeno raven?\n\nDolgotrajno poslušanje pri veliki glasnosti lahko poškoduje sluh."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite uporabljati bližnjico funkcij za ljudi s posebnimi potrebami?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Ko je bližnjica vklopljena, pritisnite gumba za glasnost in ju pridržite tri sekunde, če želite zagnati funkcijo za ljudi s posebnimi potrebami.\n\n Trenutna funkcija za ljudi s posebnimi potrebami:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkcijo lahko spremenite v »Nastavitve > Funkcije za ljudi s posebnimi potrebami«."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Prazno"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi bližnjice"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Prekliči"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Izklopi bližnjico"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Uporabi bližnjico"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija barv"</string> @@ -1909,6 +1917,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Želite vklopiti delovni profil?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Vklopili boste svoje delovne aplikacije, obvestila, podatke in druge funkcije delovnega profila"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Vklop"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ta aplikacija je bila zasnovana za starejšo različico Androida in morda ne bo delovala pravilno. Preverite, ali so na voljo posodobitve, ali pa se obrnite na razvijalca."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Preveri, ali je na voljo posodobitev"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nova sporočila."</string> @@ -2021,13 +2033,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akumulator se bo morda izpraznil, preden ga običajno priključite na polnjenje"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Vklopilo se je varčevanje z energijo akumulatorja za podaljšanje časa delovanja akumulatorja"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Varčevanje z energijo akumulatorja"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Varčevanje z energijo akumulatorja se ne bo znova aktiviralo, dokler akumulator ne bo znova skoraj prazen"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Akumulator je dovolj napolnjen. Varčevanje z energijo akumulatorja se ne bo znova aktiviralo, dokler akumulator ne bo znova skoraj prazen."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Napolnjenost telefona: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Napolnjenost tabličnega računalnika: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Napolnjenost naprave: <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Varčevanje z energijo akumulatorja je izklopljeno. Funkcije niso več omejene."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Varčevanje z energijo akumulatorja je izklopljeno. Funkcije niso več omejene."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Mapa"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplikacija za Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Datoteka"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index f38d354b6ae8..ceba0be195f2 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"qasje te kalendari yt"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"dërgo dhe shiko mesazhet SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Hapësira e ruajtjes"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"qasjen te fotografitë, përmbajtjet audio-vizuale dhe skedarët në pajisje"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofoni"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"regjistro audio"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Mund të trokasë, rrëshqasë, bashkojë gishtat dhe kryejë gjeste të tjera."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gjestet e gjurmës së gishtit"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Mund të regjistrojë gjestet e kryera në sensorin e gjurmës së gishtit të pajisjes."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"çaktivizo ose modifiko shiritin e statusit"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"të bëhet shiriti i statusit"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Të ngrihet volumi mbi nivelin e rekomanduar?\n\nDëgjimi me volum të lartë për periudha të gjata mund të dëmtojë dëgjimin."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Të përdoret shkurtorja e qasshmërisë?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kur shkurtorja është e aktivizuar, shtypja e të dy butonave për 3 sekonda do të nisë një funksion qasshmërie.\n\n Funksioni aktual i qasshmërisë:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Mund ta ndryshosh funksionin te Cilësimet > Qasshmëria."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Boshatis"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redakto shkurtoret"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Anulo"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Çaktivizo shkurtoren"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Përdor shkurtoren"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Kthimi i ngjyrës"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Të aktivizohet profili i punës?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Aplikacionet e punës, njoftimet, të dhënat e tua dhe funksionet e tjera të profilit të punës do të aktivizohen"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivizo"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ky aplikacion është ndërtuar për një version më të vjetër të Android dhe mund të mos funksionojë mirë. Provo të kontrollosh për përditësime ose kontakto me zhvilluesin."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kontrollo për përditësim"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Ke mesazhe të reja"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Bateria mund të mbarojë përpara ngarkimit të zakonshëm"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"\"Kursyesi i baterisë\" u aktivizua për të zgjatur jetëgjatësinë e baterisë"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Kursyesi i baterisë"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"\"Kursyesi i baterisë\" nuk do të aktivizohet përsëri derisa bateria të jetë përsëri në nivel të ulët"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Bateria është karikuar në një nivel të mjaftueshëm. \"Kursyesi i baterisë\" nuk do të aktivizohet përsëri deri sa bateria të jetë përsëri në nivel të ulët."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefoni është karikuar në <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tableti është karikuar në <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Pajisja është karikuar në <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"\"Kursyesi i baterisë\" është joaktiv. Funksionet nuk janë më të kufizuara."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"\"Kursyesi i baterisë\" është çaktivizuar. Funksionet nuk janë më të kufizuara."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Dosje"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Aplikacion i Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Skedar"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index c3881cbf62fc..f3a2ce532df5 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -290,7 +290,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"приступи календару"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"шаље и прегледа SMS поруке"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Меморијски простор"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Датотеке и медији"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"приступа сликама, медијима и датотекама на уређају"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"снима звук"</string> @@ -316,6 +316,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Може да додирује, листа, скупља приказ и обавља друге покрете."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Покрети за отисак прста"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да региструје покрете на сензору за отисак прста на уређају."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Направи снимак екрана"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да направи снимак екрана."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"онемогућавање или измена статусне траке"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"функционисање као статусна трака"</string> @@ -1632,6 +1634,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Желите да појачате звук изнад препорученог нивоа?\n\nСлушање гласне музике дуже време може да вам оштети слух."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Желите ли да користите пречицу за приступачност?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Када је пречица укључена, притисните оба дугмета за јачину звука да бисте покренули функцију приступачности.\n\n Актуелна функција приступачности:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Можете да промените функцију у одељку Подешавања > Приступачност."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Празно"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Измените пречице"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Откажи"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Искључи пречицу"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Користи пречицу"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Инверзија боја"</string> @@ -1877,6 +1882,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Да укључимо профил за Work?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Укључиће се пословне апликације, обавештења, подаци и друге функције профила за Work"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Укључи"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Апликација није доступна"</string> + <string name="app_blocked_message" msgid="542972921087873023">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> тренутно није доступна."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ова апликација је направљена за старију верзију Android-а, па можда неће радити исправно. Потражите ажурирања или контактирајте програмера."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Потражи ажурирање"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Имате нове поруке"</string> @@ -1988,13 +1995,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батерија ће се можда испразнити пре уобичајеног пуњења"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Уштеда батерије је активирана да би се продужило трајање батерије"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Уштеда батерије"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Уштеда батерије се неће поново активирати док батерија не буде скоро празна"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Батерија је напуњена до задовољавајућег нивоа. Уштеда батерије се неће поново активирати док батерија не буде скоро празна."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Телефон је напуњен <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Таблет је напуњен <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Уређај је напуњен <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Уштеда батерије је искључена. Функције више нису ограничене."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Уштеда батерије је искључена. Функције више нису ограничене."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Уштеда батерије је искључена"</string> + <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_apk" msgid="3168784749499623902">"Android апликација"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Датотека"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index feef35b0949b..ade5e6af081a 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"få tillgång till din kalender"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"Sms"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"skicka och visa sms"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Lagring"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Filer och media"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"få åtkomst till foton, media och filer på din enhet"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"spela in ljud"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan trycka, svepa, nypa och göra andra rörelser."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Fingeravtrycksrörelser"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan registrera rörelser som utförs med hjälp av enhetens fingeravtryckssensor."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skärmdump"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Du kan ta en skärmdump av skärmen."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"inaktivera eller ändra statusfält"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"visas i statusfältet"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vill du höja volymen över den rekommenderade nivån?\n\nAtt lyssna med stark volym långa stunder åt gången kan skada hörseln."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vill du använda Aktivera tillgänglighet snabbt?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"När kortkommandot har aktiverats startar du en tillgänglighetsfunktion genom att trycka ned båda volymknapparna i tre sekunder.\n\n Aktuell tillgänglighetsfunktion:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan ändra funktionen i Inställningar > Tillgänglighet."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Töm"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redigera genvägar"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Avbryt"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Inaktivera kortkommandot"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Använd kortkommandot"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverterade färger"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Vill du aktivera jobbprofilen?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Jobbappar, aviseringar, data och andra funktioner i jobbprofilen aktiveras"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivera"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Appen är inte tillgänglig"</string> + <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> är inte tillgängligt just nu."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Appen har utvecklats för en äldre version av Android och kanske inte fungerar som den ska. Testa att söka efter uppdateringar eller kontakta utvecklaren."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Sök efter uppdateringar"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nya meddelanden"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batteriet kan ta slut innan du brukar ladda det"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batterisparläget har aktiverats för att utöka batteritiden"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Batterisparläge"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Batterisparläget aktiveras inte igen förrän batterinivån är låg"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Batteriet har laddats tillräckligt. Batterisparläget aktiveras inte igen förrän batterinivån är låg."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Mobilen är laddad till <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Surfplattan är laddad till <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Enheten är laddad till <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Batterisparläget har inaktiverats. Funktioner begränsas inte längre."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Batterisparläget har inaktiverats. Funktioner begränsas inte längre."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Batterisparläget har inaktiverats"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefonen har laddats tillräckligt. Funktioner begränsas inte längre."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Surfplattan har laddats tillräckligt. Funktioner begränsas inte längre."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Enheten har laddats tillräckligt. Funktioner begränsas inte längre."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Mapp"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android-app"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fil"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 094e324efdc1..f893af3ca2f2 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"ifikie kalenda yako"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"itume na iangalie SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Hifadhi"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"ifikie picha, maudhui na faili kwenye kifaa chako"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Kipokea sauti"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"irekodi sauti"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Unaweza kugusa, kutelezesha kidole, kubana na kutekeleza ishara zingine."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Ishara za alama ya kidole"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Inaweza kurekodi ishara zinazotekelezwa kwenye kitambua alama ya kidole."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"zima au rekebisha mwambaa hali"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa aikoni za mfumo."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"kuwa sehemu ya arifa"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ungependa kupandisha sauti zaidi ya kiwango kinachopendekezwa?\n\nKusikiliza kwa sauti ya juu kwa muda mrefu kunaweza kuharibu uwezo wako wa kusikia."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ungependa kutumia njia ya mkato ya ufikivu?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Unapowasha kipengele cha njia ya mkato, hatua ya kubonyeza vitufe vyote viwili vya sauti kwa dakika 3 itafungua kipengele cha ufikivu.\n\n Kipengele cha ufikivu kilichopo kwa sasa:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Unaweza kubadilisha kipengele hiki katika Mipangilio > Zana za ufikivu."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Tupu"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kubadilisha njia za mkato"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Ghairi"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Zima kipengele cha Njia ya Mkato"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Tumia Njia ya Mkato"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Ugeuzaji rangi"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Ungependa kuwasha wasifu wa kazini?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Hatua hii itawasha data, arifa, programu za kazini, arifa na vipengele vingine vya wasifu wa kazini"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Washa"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Programu hii iliundwa kwa ajili ya toleo la zamani la Android na huenda isifanye kazi vizuri. Jaribu kuangalia masasisho au uwasiliane na msanidi programu."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Angalia masasisho"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Una ujumbe mpya"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Huenda betri itakwisha chaji mapema"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Imewasha Kiokoa Betri ili kurefusha muda wa matumizi ya betri"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Kiokoa betri"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Kiokoa betri hakitawashwa tena hadi chaji ipungue tena"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Betri imejazwa chaji hadi kiwango cha kutosha. Kiokoa betri hakitawashwa tena hadi chaji ya betri ipungue tena."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Simu ina <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ya chaji"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Kompyuta kibao ina <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ya chaji"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Kifaa kina <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ya chaji"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Kiokoa betri kimezimwa. Vipengele havizuiliwi tena."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Kiokoa betri kimezimwa. Vipengele havizuiliwi tena."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Folda"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Programu ya Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Faili"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 08b32b95040f..d3a461303f1d 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"கேலெண்டரை அணுகலாம்"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS அனுப்பலாம், வந்த SMSகளைப் பார்க்கலாம்"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"சேமிப்பிடம்"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"உங்கள் சாதனத்தில் உள்ள படங்கள், மீடியா மற்றும் கோப்புகளை அணுக வேண்டும்"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"மைக்ரோஃபோன்"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ஒலிப் பதிவு செய்யலாம்"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"தட்டலாம், ஸ்வைப் செய்யலாம், பின்ச் செய்யலாம் மற்றும் பிற சைகைகளைச் செயல்படுத்தலாம்."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"கைரேகை சைகைகள்"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"சாதனத்தின் கைரேகை சென்சார்மேல் செய்யப்படும் சைகைகளைக் கேப்ட்சர் செய்ய முடியும்."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற ஆப்ஸை அனுமதிக்கிறது."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"நிலைப் பட்டியில் இருக்கும்"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"பரிந்துரைத்த அளவை விட ஒலியை அதிகரிக்கவா?\n\nநீண்ட நேரத்திற்கு அதிகளவில் ஒலி கேட்பது கேட்கும் திறனைப் பாதிக்கலாம்."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"அணுகல்தன்மை ஷார்ட்கட்டைப் பயன்படுத்தவா?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ஷார்ட்கட் இயக்கத்தில் இருந்தால், இரண்டு ஒலியளவு பொத்தான்களையும் 3 வினாடிகள் அழுத்தி, அணுகல்தன்மை அம்சத்தை இயக்கலாம்.\n\n தற்போதைய அணுகல்தன்மை அம்சம்:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n அமைப்புகள் > அணுகல்தன்மை என்பதற்குச் சென்று, அம்சத்தை மாற்றலாம்."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"காலியானது"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ஷார்ட்கட்களை மாற்று"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ரத்துசெய்"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ஷார்ட்கட்டை முடக்கு"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ஷார்ட்கட்டைப் பயன்படுத்து"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"வண்ணத்தை நேர் எதிராக மாற்றுதல்"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"பணிச் சுயவிவரத்தை ஆன் செய்யவா?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"பணி ஆப்ஸ், அறிவிப்புகள், தரவு மற்றும் பிற பணிச் சுயவிவர அம்சங்கள் ஆன் செய்யப்படும்"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"இயக்கு"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"இந்த ஆப்ஸ் Android இன் பழைய பதிப்புக்காக உருவாக்கப்பட்டதால், சரியாக வேலை செய்யாமல் போகலாம். புதுப்பிப்புகள் ஏதேனும் உள்ளதா எனப் பார்க்கவும் அல்லது டெவெலப்பரைத் தொடர்புகொள்ளவும்."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"புதுப்பிப்பு உள்ளதா எனப் பார்"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"புதிய செய்திகள் வந்துள்ளன"</string> @@ -1855,11 +1867,9 @@ <string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> உடன் இணைக்கப்பட்டது"</string> <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"கோப்புகளைப் பார்க்க, தட்டவும்"</string> <string name="pin_target" msgid="8036028973110156895">"பின் செய்"</string> - <!-- no translation found for pin_specific_target (7824671240625957415) --> - <skip /> + <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> ஐப் பின் செய்"</string> <string name="unpin_target" msgid="3963318576590204447">"பின்னை அகற்று"</string> - <!-- no translation found for unpin_specific_target (3859828252160908146) --> - <skip /> + <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ஐப் பின் நீக்கு"</string> <string name="app_info" msgid="6113278084877079851">"ஆப்ஸ் தகவல்"</string> <string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="demo_starting_message" msgid="6577581216125805905">"டெமோவைத் தொடங்குகிறது…"</string> @@ -1957,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"வழக்கமாகச் சார்ஜ் செய்வதற்கு முன்பே பேட்டரி தீர்ந்துபோகக்கூடும்"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"பேட்டரி நிலையை நீட்டிக்க பேட்டரி சேமிப்பான் இயக்கப்பட்டுள்ளது"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"பேட்டரி சேமிப்பான்"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"பேட்டரி மறுபடியும் குறையும் வரை பேட்டரி சேமிப்பானை இயக்க இயலாது"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"பேட்டரி போதுமான அளவு சார்ஜ் செய்யப்பட்டுள்ளது. பேட்டரி குறையும் வரை பேட்டரி சேமிப்பானை மீண்டும் இயக்க இயலாது."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"மொபைல் <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> சார்ஜ் செய்யப்பட்டது"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"டேப்லெட் <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> சார்ஜ் செய்யப்பட்டது"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"சாதனம் <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> சார்ஜ் செய்யப்பட்டது"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"பேட்டரி சேமிப்பான் ஆஃப் செய்யப்பட்டுள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"பேட்டரி சேமிப்பான் ஆஃப் செய்யப்பட்டுள்ளது. அம்சங்கள் இனி தடையின்றி இயங்கும்."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index e1b88acf665f..04a4d417407d 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"మీ క్యాలెండర్ను యాక్సెస్ చేయడానికి"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS సందేశాలను పంపడం మరియు వీక్షించడం"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"నిల్వ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"మీ పరికరంలోని ఫోటోలు, మీడియా మరియు ఫైల్లను యాక్సెస్ చేయడానికి"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"మైక్రోఫోన్"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ఆడియోను రికార్డ్ చేయడానికి"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"నొక్కగలరు, స్వైప్ చేయగలరు, స్క్రీన్పై రెండు వేళ్లను ఉంచి ఆ వేళ్లను దగ్గరకు లేదా దూరానికి లాగగలరు మరియు ఇతర సంజ్ఞలను చేయగలరు."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"వేలిముద్ర సంజ్ఞలు"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"పరికర వేలిముద్ర సెన్సార్లో ఉపయోగించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"స్థితి బార్ను నిలిపివేయడం లేదా సవరించడం"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"స్థితి బార్ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"స్థితి పట్టీగా ఉండటం"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"వాల్యూమ్ను సిఫార్సు చేయబడిన స్థాయి కంటే ఎక్కువగా పెంచాలా?\n\nసుదీర్ఘ వ్యవధుల పాటు అధిక వాల్యూమ్లో వినడం వలన మీ వినికిడి శక్తి దెబ్బ తినవచ్చు."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"యాక్సెస్ సామర్థ్యం షార్ట్కట్ను ఉపయోగించాలా?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"షార్ట్కట్ ఆన్లో ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్లను 3 సెకన్ల పాటు నొక్కితే యాక్సెస్ సామర్థ్య ఫీచర్ ప్రారంభం అవుతుంది.\n\n ప్రస్తుత యాక్సెస్ సామర్థ్య ఫీచర్:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n సెట్టింగ్లు > యాక్సెస్ సామర్థ్యంలో మీరు ఫీచర్ను మార్చవచ్చు."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ఖాళీ"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"షార్ట్కట్లను ఎడిట్ చేయి"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"రద్దు చేయి"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"సత్వరమార్గాన్ని ఆఫ్ చేయి"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"సత్వరమార్గాన్ని ఉపయోగించు"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"రంగుల మార్పిడి"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"కార్యాలయ ప్రొఫైల్ని ఆన్ చేయాలా?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"మీ కార్యాలయ యాప్లు, నోటిఫికేషన్లు, డేటా మరియు ఇతర కార్యాలయ ప్రొఫైల్ ఫీచర్లు ఆన్ చేయబడతాయి"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"ఆన్ చేయి"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ఈ యాప్ పాత వెర్షన్ Android కోసం రూపొందించబడింది మరియు అది సరిగ్గా పని చేయకపోవచ్చు. అప్డేట్ల కోసం తనిఖీ చేయడానికి ప్రయత్నించండి లేదా డెవలపర్ని సంప్రదించండి."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"అప్డేట్ కోసం తనిఖీ చేయండి"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"మీకు కొత్త సందేశాలు ఉన్నాయి"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"మామూలుగా ఛార్జ్ చేసేలోపు బ్యాటరీ ఖాళీ కావచ్చు"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"బ్యాటరీ జీవితకాలాన్ని పెంచడానికి బ్యాటరీ సేవర్ యాక్టివేట్ చేయబడింది"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"బ్యాటరీ సేవర్"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"బ్యాటరీ మళ్లీ తగ్గిపోయే వరకు బ్యాటరీ సేవర్ తిరిగి యాక్టివేట్ చేయబడదు"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"బ్యాటరీ సరిపడే స్థాయికి ఛార్జ్ చేయబడింది. బ్యాటరీ మళ్లీ తగ్గిపోయే వరకు బ్యాటరీ సేవర్ తిరిగి యాక్టివేట్ చేయబడదు."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"ఫోన్ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ఛార్జ్ అయింది"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"టాబ్లెట్ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ఛార్జ్ అయింది"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"పరికరం <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ఛార్జ్ అయింది"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"బ్యాటరీ సేవర్ ఆఫ్లో ఉంది. ఫీచర్లు ఇప్పటి నుండి పరిమితం చేయబడవు."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"బ్యాటరీ సేవర్ ఆఫ్ చేయబడింది. ఫీచర్లు ఇప్పటి నుండి పరిమితం చేయబడవు."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index bd02a73d07bf..11aa4076eea4 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"เข้าถึงปฏิทิน"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"ส่งและดูข้อความ SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"พื้นที่เก็บข้อมูล"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"เข้าถึงรูปภาพ สื่อ และไฟล์บนอุปกรณ์ของคุณ"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"ไมโครโฟน"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"บันทึกเสียง"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"สามารถแตะ เลื่อน บีบ และทำท่าทางสัมผัสอื่นๆ"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"ท่าทางสัมผัสลายนิ้วมือ"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"สามารถจับท่าทางสัมผัสที่เกิดขึ้นบนเซ็นเซอร์ลายนิ้วมือของอุปกรณ์"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"เป็นแถบสถานะ"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"นี่เป็นการเพิ่มระดับเสียงเกินระดับที่แนะนำ\n\nการฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ใช้ทางลัดการช่วยเหลือพิเศษไหม"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"เมื่อทางลัดเปิดอยู่ การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มเป็นเวลา 3 วินาทีจะเริ่มฟีเจอร์การช่วยเหลือพิเศษ\n\n ฟีเจอร์การช่วยเหลือพิเศษปัจจุบัน:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n คุณสามารถเปลี่ยนฟีเจอร์ในการตั้งค่า > การช่วยเหลือพิเศษ"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"ล้าง"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"แก้ไขทางลัด"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"ยกเลิก"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ปิดทางลัด"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ใช้ทางลัด"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"การกลับสี"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"เปิดโปรไฟล์งานไหม"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"ระบบจะเปิดแอปงาน การแจ้งเตือน ข้อมูล และฟีเจอร์อื่นๆ ในโปรไฟล์งาน"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"เปิด"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"แอปนี้สร้างขึ้นเพื่อ Android เวอร์ชันเก่าและอาจทำงานผิดปกติ โปรดลองตรวจหาการอัปเดตหรือติดต่อนักพัฒนาซอฟต์แวร์"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ตรวจสอบอัปเดต"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"คุณมีข้อความใหม่"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"แบตเตอรี่อาจหมดก่อนการชาร์จปกติ"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"เปิดใช้งานโหมดประหยัดแบตเตอรี่แล้วเพื่อยืดอายุการใช้งานแบตเตอรี่"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"โหมดประหยัดแบตเตอรี่"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"โหมดประหยัดแบตเตอรี่จะไม่เปิดใช้งานอีกจนกว่าแบตเตอรี่จะเหลือน้อยอีกครั้ง"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"ชาร์จแบตเตอรี่จนถึงระดับที่เพียงพอแล้ว โหมดประหยัดแบตเตอรี่จะไม่เปิดใช้งานอีกจนกว่าแบตเตอรี่จะเหลือน้อยอีกครั้ง"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"โทรศัพท์ชาร์จ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"แท็บเล็ตชาร์จ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"อุปกรณ์ชาร์จ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"โหมดประหยัดแบตเตอรี่ปิดอยู่ ไม่มีการจำกัดฟีเจอร์แล้ว"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"ปิดโหมดประหยัดแบตเตอรี่แล้ว ไม่มีการจำกัดฟีเจอร์แล้ว"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index c6fb52db4748..718e170c56ec 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"i-access ang iyong kalendaryo"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"magpadala at tumingin ng mga mensaheng SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Storage"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"i-access ang mga larawan, media at file sa iyong device"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikropono"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"mag-record ng audio"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"May kakayahang mag-tap, mag-swipe, mag-pinch at magsagawa ng iba pang mga galaw."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Mga galaw gamit ang fingerprint"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Makukunan ang mga galaw na ginawa sa sensor para sa fingerprint ng device."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"i-disable o baguhin ang status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Pinapayagan ang app na i-disable ang status bar o magdagdag at mag-alis ng mga icon ng system."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"maging status bar"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lakasan ang volume nang lagpas sa inirerekomendang antas?\n\nMaaaring mapinsala ng pakikinig sa malakas na volume sa loob ng mahahabang panahon ang iyong pandinig."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gagamitin ang Shortcut sa Pagiging Accessible?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kapag naka-on ang shortcut, magsisimula ang isang feature ng pagiging naa-access kapag pinindot ang parehong button ng volume sa loob ng 3 segundo.\n\n Kasalukuyang feature ng pagiging naa-access:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Maaari mong baguhin ang feature sa Mga Setting > Pagiging Accessible."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Bakantehin"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"I-edit ang mga shortcut"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Kanselahin"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"I-off ang Shortcut"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gamitin ang Shortcut"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Pag-invert ng Kulay"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"I-on ang profile sa trabaho?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Mao-on ang iyong mga app sa trabaho, notification, data, at iba pang feature sa profile sa trabaho"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"I-on"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ang app na ito ay ginawa para sa mas lumang bersyon ng Android at maaaring hindi gumana nang maayos. Subukang tingnan kung may mga update, o makipag-ugnayan sa developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tingnan kung may update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Mayroon kang mga bagong mensahe"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Maaaring maubos ang baterya bago ang karaniwang pag-charge"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Na-activate ang Pangtipid sa Baterya para patagalin ang buhay ng baterya"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Pangtipid sa Baterya"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Hindi muling maa-activate ang Pangtipid sa Baterya hangga\'t hindi pa ulit mababa ang baterya"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Na-charge na ang baterya sa sapat na antas. Hindi muling maa-activate ang Pangtipid sa Baterya hangga\'t hindi pa ulit mababa ang baterya."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"<xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ang charge ng telepono"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"<xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ang charge ng tablet"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"<xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> ang charge ng baterya"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Na-off ang Pangtipid sa Baterya. Hindi na pinaghihigpitan ang mga feature."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Na-off ang Pangtipid sa Baterya. Hindi na pinaghihigpitan ang mga feature."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android application"</string> <string name="mime_type_generic" msgid="4606589110116560228">"File"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 25d0674f32ce..93d9af10f570 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"takviminize erişme"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS mesajları gönderme ve görüntüleme"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Depolama"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"cihazınızdaki fotoğraflara, medyaya ve dosyalara erişme"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ses kaydetme"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Dokunabilir, hızlıca kaydırabilir, sıkıştırabilir ve diğer hareketleri yapabilirsiniz."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Parmak izi hareketleri"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazın parmak izi sensörlerinde gerçekleştirilen hareketleri yakalayabilir."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"durum çubuğunu devre dışı bırak veya değiştir"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"durum çubuğunda olma"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ses seviyesi önerilen düzeyin üzerine yükseltilsin mi?\n\nUzun süre yüksek ses seviyesinde dinlemek işitme duyunuza zarar verebilir."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erişilebilirlik Kısayolu Kullanılsın mı?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kısayol açık olduğunda, ses düğmelerinin ikisini birden 3 saniyeliğine basılı tutmanız bir erişilebilirlik özelliğini başlatır.\n\n Geçerli erişilebilirlik özelliği:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Özelliği, Ayarlar > Erişilebilirlik seçeneğinden değiştirebilirsiniz."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Boş"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kısayolları düzenle"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"İptal"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Kısayolu Kapat"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kısayolu Kullan"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Rengi Ters Çevirme"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"İş profili açılsın mı?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"İş uygulamalarınız, bildirimleriniz, verileriniz ve diğer iş profili özellikleriniz açılacak"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Aç"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Bu uygulama Android\'in daha eski bir sürümü için oluşturuldu ve düzgün çalışmayabilir. Güncellemeleri kontrol etmeyi deneyin veya geliştiriciyle iletişime geçin."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Güncellemeleri denetle"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Yeni mesajlarınız var"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Pil normal şarjdan önce bitebilir"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Pilin ömrünü uzatmak için Pil Tasarrufu etkinleştirildi"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Pil Tasarrufu"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Pil seviyesi tekrar azalıncaya kadar Pil Tasarrufu yeniden etkinleştirilmeyecek"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Pil yeterli bir seviyede şarj edildi. Pil seviyesi tekrar azalıncaya kadar Pil Tasarrufu yeniden etkinleştirilmeyecek."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefon <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> şarja sahip"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Tablet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> şarja sahip"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Cihaz <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> şarja sahip"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Pil Tasarrufu kapalı. Özellikler artık kısıtlanmış değil."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Pil Tasarrufu kapalı. Özellikler artık kısıtlanmış değil."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Klasör"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android uygulaması"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Dosya"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index ca0146b7ca79..0f8b3682c12a 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -293,7 +293,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"отримувати доступ до календаря"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"надсилати та переглядати SMS-повідомлення"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Пам’ять"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"отримувати доступ до фотографій, мультимедійного вмісту та файлів на вашому пристрої"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Мікрофон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"записувати аудіо"</string> @@ -319,6 +320,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Можна торкатися, проводити пальцем, стискати пальці та виконувати інші жести."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Жести на сканері відбитків пальців"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може фіксувати жести на сканері відбитків пальців."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"вимикати чи змін. рядок стану"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"відображатися як рядок стану"</string> @@ -1654,6 +1659,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Збільшити гучність понад рекомендований рівень?\n\nЯкщо слухати надто гучну музику тривалий час, можна пошкодити слух."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Використовувати швидке ввімкнення?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Коли ярлик увімкнено, після натискання обох клавіш гучності й утримування їх протягом 3 секунд увімкнеться функція спеціальних можливостей.\n\n Поточна функція спеціальних можливостей:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Цю функцію можна змінити в меню \"Налаштування\" > \"Спеціальні можливості\"."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Очистити"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Редагувати засоби"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Скасувати"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Вимкнути ярлик"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Використовувати ярлик"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Інверсія кольорів"</string> @@ -1909,6 +1917,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Увімкнути робочий профіль?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Додатки, сповіщення, дані й інші функції робочого профілю буде ввімкнено"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Увімкнути"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Цей додаток створений для старішої версії Android і може працювати неналежним чином. Спробуйте знайти оновлення або зв’яжіться з розробником."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Шукати оновлення"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"У вас є нові повідомлення"</string> @@ -2021,13 +2033,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Акумулятор може розрядитися раніше ніж зазвичай"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Режим енергозбереження активовано для збільшення часу роботи акумулятора"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Режим енергозбереження"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Режим енергозбереження не ввімкнеться, доки рівень заряду знову не знизиться"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Акумулятор заряджено достатньо. Режим енергозбереження буде знову ввімкнено, коли рівень заряду знизиться."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Телефон заряджено на <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Планшет заряджено на <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Пристрій заряджено на <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Режим енергозбереження вимкнено. Функції вже не обмежено."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Режим енергозбереження вимкнено. Функції вже не обмежено."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 1d79c6ea6652..5b9571597cba 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"اپنے کیلنڈر تک رسائی حاصل کریں"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS پیغامات بھیجیں اور دیکھیں"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"اسٹوریج"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"آپ کے آلہ پر تصاویر، میڈیا اور فائلوں تک رسائی حاصل کر سکتی ہیں"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"مائکروفون"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"آڈیو ریکارڈ کریں"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"تھپتھپانا، سوائپ کرنا، چٹکی بھرنا اور دیگر اشارے انجام دے سکتی ہے"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"فنگر پرنٹ کے اشارے"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"آلہ کے فنگر پرنٹ سینسر پر کیے گئے اشاروں کو کیپچر کر سکتا ہے۔"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"بطور اسٹیٹس بار کام لیں"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"والیوم کو تجویز کردہ سطح سے زیادہ کریں؟\n\nزیادہ وقت تک اونچی آواز میں سننے سے آپ کی سماعت کو نقصان پہنچ سکتا ہے۔"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ایکسیسبیلٹی شارٹ کٹ استعمال کریں؟"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"شارٹ کٹ آن ہونے پر، 3 سیکنڈ تک دونوں والیوم بٹنز کو دبانے سے ایک ایکسیسبیلٹی خصوصیت شروع ہو جائے گی۔\n\n موجودہ ایکسیسبیلٹی خصوصیت:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n آپ خصوصیت کو ترتیبات > ایکسیسبیلٹی میں جا کر تبدیل کر سکتے ہیں۔"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"خالی"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"شارٹ کٹس میں ترمیم کریں"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"منسوخ کریں"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"شارٹ کٹ آف کریں"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"شارٹ کٹ استعمال کریں"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"رنگوں کی تقلیب"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"دفتری پروفائل آن کریں؟"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"آپ کی دفتری ایپس، اطلاعات، ڈیٹا اور دفتری پروفائل کی دیگر خصوصیات آن کر دی جائیں گی"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"آن کریں"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"یہ ایپ Android کے پرانے ورژن کے لئے بنائی گئی ہے اور ہو سکتا ہے صحیح طور پر کام نہ کرے۔ اپ ڈیٹس چیک کر کے آزمائیں یا ڈیولپر سے رابطہ کریں۔"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"اپ ڈیٹ چیک کریں"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"آپ کے پاس نئے پیغامات ہیں"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"معمول چارج سے پہلے بیٹری ختم ہو سکتی ہے"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"بیٹری لائف کو بڑھانے کے لیے بیٹری سیور کو فعال کر دیا گیا ہے"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"بیٹری سیور"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"بیٹری سیور اس وقت تک دوبارہ فعال نہیں ہوگی جب تک پھر سے بیٹری کم نہیں ہو جاتی ہے"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"بیٹری کافی سطح تک چارج ہو گئی ہے۔ بیٹری سیور اس وقت تک دوبارہ فعال نہیں ہوگی جب تک پھر سے بیٹری کم نہیں ہو جاتی ہے۔"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"فون <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> چارج ہو گیا"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"ٹیبلیٹ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> چارج ہو گیا"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"آلہ <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> چارج ہو گیا"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"بیٹری سیور آف ہے۔ خصوصیات پر اب پابندی نہیں ہے۔"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"بیٹری سیور کو آف کر دیا گیا۔ خصوصیات پر اب پابندی نہیں ہے۔"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 744f54dba133..c83741468833 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"taqvimingizga kirish"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS xabarlarni yuborish va ko‘rish"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Xotira"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Fayllar va media"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"qurilmangizdagi surat, multimedia va fayllarga kirish"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofon"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ovoz yozib olish"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Bosish, surish; jipslashtirish va boshqa imo-ishoralarni amalga oshirish mumkin."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Barmoq izi ishoralari"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Barmoq izi skanerida kiritilgan ishoralarni taniy oladi."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Skrinshot olish"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekrandan skrinshot olishi mumkin."</string> <string name="permlab_statusBar" msgid="8798267849526214017">"holat panelini o‘zgartirish yoki o‘chirish"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"holat qatorida ko‘rinishi"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Tovush balandligi tavsiya etilgan darajadan ham yuqori qilinsinmi?\n\nUzoq vaqt davomida baland ovozda tinglash eshitish qobiliyatingizga salbiy ta’sir ko‘rsatishi mumkin."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Tezkor ishga tushirishdan foydalanilsinmi?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Maxsus imkoniyatlar funksiyasidan foydalanish uchun u yoniqligida ikkala ovoz balandligini boshqarish tugmasini 3 soniya bosib turing.\n\n Joriy maxsus imkoniyatlar funksiyasi:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Bu funksiyani Sozlamalar > Maxsus imkoniyatlar orqali o‘zgartirish mumkin."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Boʻshatish"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Tezkor tugmalarni tahrirlash"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Bekor qilish"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Tezkor ishga tushirishni o‘chirib qo‘yish"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Tezkor ishga tushirishdan foydalanish"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Ranglarni akslantirish"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Ishchi profil yoqilsinmi?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Ishchi ilovalar, bildirishnomalar, ma’lumotlar va boshqa ishchi profil imkoniyatlari yoqiladi"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Yoqish"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Ilova ishlamayapti"</string> + <string name="app_blocked_message" msgid="542972921087873023">"Ayni vaqtda <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi ishlamayapti."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Bu ilova eskiroq Android versiyalariga chiqarilgan va xato ishlashi mumkin. Yangilanishlarini tekshiring yoki dasturchi bilan bog‘laning."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Yangilanish borligini tekshirish"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Sizga yangi SMS keldi"</string> @@ -1955,13 +1962,10 @@ <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="battery_saver_notification_channel_name" msgid="3918243458067916913">"Quvvat tejash"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Quvvat tejash rejimi qatareya quvvati kamaymaguncha qayta yoqilmaydi"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Batareya yetarli darajada quvvatlandi. Quvvat tejash rejimi qatareya quvvati kamaymaguncha qayta yoqilmaydi."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Telefon <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> quvvat oldi"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Planshet <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> quvvat oldi"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Qurilma <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> quvvat oldi"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Quvvat tejash rejimi faolsizlantirildi. Funksiyalar endi cheklovlarsiz ishlaydi."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Quvvat tejash rejimi faolsizlantirildi. Funksiyalar endi cheklovlarsiz ishlaydi."</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> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Planshet yetarli quvvatlandi. Funksiyalar endi cheklovlarsiz ishlaydi."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Qurilma yetarli quvvatlandi. Funksiyalar endi cheklovlarsiz ishlaydi."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Jild"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android ilova"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Fayl"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 7e4e2644fb7f..82662ab8f77f 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"truy cập lịch của bạn"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"Tin nhắn SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"gửi và xem tin nhắn SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Bộ nhớ"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"truy cập ảnh, phương tiện và tệp trên thiết bị của bạn"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Micrô"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ghi âm"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Có thể nhấn, vuốt, chụm và thực hiện các cử chỉ khác."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Cử chỉ vân tay"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Có thể ghi lại các cử chỉ được thực hiện trên cảm biến vân tay của thiết bị."</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"trở thành thanh trạng thái"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bạn tăng âm lượng lên quá mức khuyên dùng?\n\nViệc nghe ở mức âm lượng cao trong thời gian dài có thể gây tổn thương thính giác của bạn."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sử dụng phím tắt Hỗ trợ tiếp cận?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Khi phím tắt được bật, nhấn cả hai nút âm lượng trong 3 giây sẽ bắt đầu một tính năng trợ năng.\n\n Tính năng trợ năng hiện tại:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Bạn có thể thay đổi tính năng trong Cài đặt > Trợ năng."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Xóa sạch"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Chỉnh sửa phím tắt"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Hủy"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Tắt phím tắt"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sử dụng phím tắt"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Đảo màu"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Bạn muốn bật hồ sơ công việc?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Ứng dụng công việc, thông báo, dữ liệu và các tính năng khác của hồ sơ công việc sẽ được bật"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Bật"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ứng dụng này được xây dựng cho một phiên bản Android cũ hơn và có thể hoạt động không bình thường. Hãy thử kiểm tra các bản cập nhật hoặc liên hệ với nhà phát triển."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kiểm tra bản cập nhật"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Bạn có tin nhắn mới"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Pin có thể hết trước khi sạc bình thường"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Trình tiết kiệm pin được kích hoạt để kéo dài thời lượng pin"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Trình tiết kiệm pin"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Trình tiết kiệm pin sẽ chỉ kích hoạt lại khi sắp hết pin"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Pin đã sạc đủ. Trình tiết kiệm pin sẽ chỉ kích hoạt lại khi pin sắp hết."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Điện thoại đã sạc được <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Máy tính bảng đã sạc được <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Thiết bị đã sạc được <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Trình tiết kiệm pin đã tắt. Các tính năng không bị hạn chế nữa."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Trình tiết kiệm pin đã tắt. Các tính năng không bị hạn chế nữa."</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <string name="mime_type_folder" msgid="2203536499348787650">"Thư mục"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Ứng dụng Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Tệp"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 6abfda60a89c..101a2eca8793 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"访问您的日历"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"短信"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"发送和查看短信"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"存储空间"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"访问您设备上的照片、媒体内容和文件"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"麦克风"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"录制音频"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"可执行点按、滑动、双指张合等手势。"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"指纹手势"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以捕获在设备指纹传感器上执行的手势。"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改状态栏"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"允许应用停用状态栏或者增删系统图标。"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"用作状态栏"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要将音量调高到建议的音量以上吗?\n\n长时间保持高音量可能会损伤听力。"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用无障碍快捷方式吗?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"开启快捷方式后,同时按下两个音量按钮 3 秒钟即可启动所设定的无障碍功能。\n\n当前设定的无障碍功能:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n如需更改设定的功能,请依次转到“设置”>“无障碍”。"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"清空"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"修改快捷方式"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"取消"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"关闭快捷方式"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快捷方式"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"颜色反转"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"要开启工作资料吗?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"您的工作应用、通知、数据及其他工作资料功能将会开启"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"开启"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"此应用专为旧版 Android 打造,因此可能无法正常运行。请尝试检查更新或与开发者联系。"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"检查更新"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"您有新消息"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"电池电量可能会在您平时的充电时间之前耗尽"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已启用省电模式以延长电池续航时间"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"省电模式"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"电池电量不足时才会再次启用省电模式"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"电池电量已充足。电池电量不足时才会再次启用省电模式。"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"手机已充电到 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"平板电脑已充电到 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"设备已充电到 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"省电模式已关闭。各项功能不再受限。"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"省电模式已关闭,各项功能不再受限。"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 2cc42d74f862..292986999e22 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"存取您的日曆"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"短訊"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"傳送和查看短訊"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"儲存空間"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"存取裝置上的相片、媒體和檔案"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"麥克風"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"錄音"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"可以輕按、滑動和兩指縮放,並執行其他手勢。"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"指紋手勢"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取在裝置指紋感應器上執行的手勢。"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改狀態列"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"成為狀態列"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量 (比建議的音量更大聲) 嗎?\n\n長時間聆聽高分貝音量可能會導致您的聽力受損。"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙功能快速鍵嗎?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"快速鍵開啟後,同時按住音量按鈕 3 秒,無障礙功能便會啟用。\n\n目前的無障礙功能:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n如要變更功能,請前往「設定」>「無障礙功能」。"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"空白"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"取消"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"關閉快速鍵"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快速鍵"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"色彩反轉"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"要開啟工作設定檔嗎?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"系統將開啟您的工作應用程式、通知、資料和其他工作設定檔功能"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"開啟"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"此應用程式專為舊版 Android 打造,因此可能無法正常運作。請嘗試檢查更新,或與開發人員聯絡。"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"檢查更新"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"您有新的訊息"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"電量可能會在日常充電前耗盡"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"「省電模式」已啟用,以便延長電池壽命"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"省電模式"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"當再次出現低電量時,省電模式才會重新啟用"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"電池已充至足夠電量。當再次出現低電量時,省電模式才會重新啟用。"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"手機已充電至 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"平板電腦已充電至 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"裝置已充電至 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"已關閉省電模式。各項功能已不再受限。"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"已關閉省電模式。各項功能已不再受限。"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 15aaec1e1f27..48ff3f66bc4d 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -287,7 +287,8 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"存取你的日曆"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"簡訊"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"傳送及查看簡訊"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"儲存空間"</string> + <!-- no translation found for permgrouplab_storage (1938416135375282333) --> + <skip /> <string name="permgroupdesc_storage" msgid="6351503740613026600">"存取裝置中的相片、媒體和檔案"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"麥克風"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"錄音"</string> @@ -313,6 +314,10 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"可使用輕觸、滑動和雙指撥動等手勢。"</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"指紋手勢"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取使用者對裝置的指紋感應器執行的手勢。"</string> + <!-- no translation found for capability_title_canTakeScreenshot (3895812893130071930) --> + <skip /> + <!-- no translation found for capability_desc_canTakeScreenshot (7762297374317934052) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"停用或變更狀態列"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"以狀態列顯示"</string> @@ -1610,6 +1615,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量,比建議的音量更大聲嗎?\n\n長時間聆聽高分貝音量可能會使你的聽力受損。"</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙捷徑嗎?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"啟用捷徑功能後,只要同時按下兩個音量鍵 3 秒,就能啟動無障礙功能。\n\n 目前設定的無障礙功能為:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n 如要變更設定的功能,請依序輕觸 [設定] > [無障礙設定]。"</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"空白"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"取消"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"停用捷徑"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用捷徑"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"色彩反轉"</string> @@ -1845,6 +1853,10 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"要開啟工作資料夾嗎?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"系統將開啟你的辦公應用程式、通知、資料和其他工作資料夾功能"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"開啟"</string> + <!-- no translation found for app_blocked_title (7353262160455028160) --> + <skip /> + <!-- no translation found for app_blocked_message (542972921087873023) --> + <skip /> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"這個應用程式是專為舊版 Android 所打造,因此可能無法正常運作。請嘗試檢查更新,或是與開發人員聯絡。"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"檢查更新"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"你有新訊息"</string> @@ -1955,13 +1967,14 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"電池電力可能會在你平常的充電時間前耗盡"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已啟用節約耗電量模式以延長電池續航力"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"節約耗電量"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"電池電量不足時,節約耗電量模式才會再次開啟"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"電池電量已足夠。電池電量不足時,節約耗電量模式才會再次開啟。"</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"手機已充電至 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"平板電腦已充電至 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"裝置已充電至 <xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"節約耗電量模式已關閉,各項功能不再受到限制。"</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"節約耗電量模式已關閉,各項功能不再受到限制。"</string> + <!-- no translation found for battery_saver_off_notification_title (7637255960468032515) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (5544457317418624367) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (4426317048139996888) --> + <skip /> + <!-- no translation found for battery_saver_charged_notification_summary (1031562417867646649) --> + <skip /> <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> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index ddaf38cd40c6..d7365620da4e 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -287,7 +287,7 @@ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"finyelela kukhalenda yakho"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"I-SMS"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"thumela uphinde ubuke imilayezo ye-SMS"</string> - <string name="permgrouplab_storage" msgid="1121695277384787841">"Isitoreji"</string> + <string name="permgrouplab_storage" msgid="1938416135375282333">"Amafayela nemidiya"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"finyelela kuzithombe, imidiya, namafayela kudivayisi yakho"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"I-Microphone"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"rekhoda ividiyo"</string> @@ -313,6 +313,8 @@ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Ingathepha, iswayiphe, incinze, futhi yenze okunye ukuthintwa."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Ukuthinta kwezigxivizo zeminwe"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Ingathatha ukuthinta okwenziwe kunzwa yezigxivizo zeminwe zedivayisi."</string> + <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Thatha isithombe-skrini"</string> + <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ingathatha isithombe-skrini sesiboniso"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"khubaza noma guqula ibha yomumo"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"yiba yibha yesimo"</string> @@ -1610,6 +1612,9 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Khuphukisa ivolumu ngaphezu kweleveli enconyiwe?\n\nUkulalela ngevolumu ephezulu izikhathi ezide kungahle kulimaze ukuzwa kwakho."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sebenzisa isinqamuleli sokufinyelela?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Uma kuvulwe isinqamuleli, ukucindezela zombili izinkinobho zevolumu amasekhondi angu-3 kuzoqala isici sokufinyelela.\n\n Isici samanje sokufinyelela:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Ungashintsha isici kuzilungiselelo > Ukufinyelela."</string> + <string name="accessibility_shortcut_menu_button" msgid="3019329474891857428">"Akunalutho"</string> + <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Hlela izinqamuleli"</string> + <string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Khansela"</string> <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Vala isinqamuleli"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sebenzisa isinqamuleli"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"Ukuguqulwa kombala"</string> @@ -1845,6 +1850,8 @@ <string name="work_mode_off_title" msgid="5503291976647976560">"Vula iphrofayela yomsebenzi?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Izinhlelo zakho zokusebenza zomsebenzi, izaziso, idatha, nezinye izici zephrofayela yomsebenzi kuzovulwa"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Vula"</string> + <string name="app_blocked_title" msgid="7353262160455028160">"Uhlelo lokusebenza alutholakali"</string> + <string name="app_blocked_message" msgid="542972921087873023">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayitholakali khona manje."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Lolu hlelo lokusebenza belakhelwe inguqulo endala ye-Android futhi kungenzeka lungasebenzi kahle. Zama ukuhlolela izibuyekezo, noma uxhumane nonjiniyela."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Hlola izibuyekezo"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Unemilayezo emisha"</string> @@ -1955,13 +1962,10 @@ <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Ibhethri lingaphela ngaphambi kokushaja okuvamile"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Isilondolozi sebhethri siyasebenza ngaphandle kwempilo yebhethri"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Isilondolozi sebhethri"</string> - <string name="battery_saver_sticky_disabled_notification_title" msgid="616803848887159814">"Isilondolozi sebhethri ngeke siphinde senziwe sisebenze lize libe phansi ibhethri futhi"</string> - <string name="battery_saver_sticky_disabled_notification_summary" msgid="9091127514013090563">"Ibhethri lishajwe kufikela kuleveli elanele. Isilondolozi sebhethri ngeke siphinde senziwe sisebenze ibhethri lize liphinde libe phansi futhi."</string> - <string name="battery_saver_charged_notification_title" product="default" msgid="3323003634503470433">"Ifoni engu-<xliff:g id="CHARGE_LEVEL">%1$s</xliff:g> igcwalisiwe"</string> - <string name="battery_saver_charged_notification_title" product="tablet" msgid="7917739170436791596">"Ithebulethi ishajwe ngokungu-<xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_charged_notification_title" product="device" msgid="6316898726189914805">"Idivayisi ishajwe ngokungu-<xliff:g id="CHARGE_LEVEL">%1$s</xliff:g>"</string> - <string name="battery_saver_off_notification_summary" msgid="8489738830261291526">"Isilondolozi sebhethri sivaliwe. Izici azisakhawulelwe."</string> - <string name="battery_saver_off_alternative_notification_summary" msgid="8875240624827898671">"Isilondolozi sebhethri sivaliwe. Izici azisakhawulelwe."</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Isilondolozi sebhethri sivaliwe"</string> + <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Ifoni inokushajwa okwanele. Izici azisakhawulelwe."</string> + <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Ithebulethi inokushajwa okwanele. Izici azisakhawulelwe."</string> + <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Idivayisi inokushajwa okwanele. Izici azisakhawulelwe."</string> <string name="mime_type_folder" msgid="2203536499348787650">"Ifolda"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Uhlelo lokusebenza lwe-Android"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Ifayela"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 44754157c5b5..e0d849223552 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2217,6 +2217,16 @@ Corresponds to <code>LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER</code>. --> <enum name="never" value="2" /> + <!-- <p> + The window is always allowed to extend into the <code>DisplayCutout</code> areas on the + all edges of the screen. + <p> + The window must make sure that no important content overlaps with the + <code>DisplayCutout</code>. + <p> + Corresponds to <code>LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS</code>. + --> + <enum name="always" value="3" /> </attr> </declare-styleable> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 2585197d85ec..85ebbd5fe7a9 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4303,4 +4303,19 @@ <!-- Package name of the required service extension package. --> <string name="config_servicesExtensionPackage" translatable="false">android.ext.services</string> + + <!-- Retention policy: number of records to kept for the historical exit info per package. --> + <integer name="config_app_exit_info_history_list_size">16</integer> + + <!-- Packages that can't be killed even if it's requested to be killed on imperceptible --> + <string-array name="config_defaultImperceptibleKillingExemptionPkgs" translatable="false" /> + + <!-- Proc States that can't be killed even if it's requested to be killed on imperceptible --> + <integer-array name="config_defaultImperceptibleKillingExemptionProcStates"> + <item>0</item> <!-- PROCESS_STATE_PERSISTENT --> + <item>1</item> <!-- PROCESS_STATE_PERSISTENT_UI --> + <item>2</item> <!-- PROCESS_STATE_TOP --> + <item>4</item> <!-- PROCESS_STATE_FOREGROUND_SERVICE --> + <item>12</item> <!-- PROCESS_STATE_TOP_SLEEPING --> + </integer-array> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 379d0aa3da3d..69e8c78d92f0 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3820,4 +3820,10 @@ <java-symbol type="string" name="capability_title_canTakeScreenshot" /> <java-symbol type="string" name="config_servicesExtensionPackage" /> + + <!-- For app process exit info tracking --> + <java-symbol type="integer" name="config_app_exit_info_history_list_size" /> + + <java-symbol type="array" name="config_defaultImperceptibleKillingExemptionPkgs" /> + <java-symbol type="array" name="config_defaultImperceptibleKillingExemptionProcStates" /> </resources> diff --git a/core/tests/coretests/res/values/styles.xml b/core/tests/coretests/res/values/styles.xml index 0bf4b9278446..352b4dceb3cc 100644 --- a/core/tests/coretests/res/values/styles.xml +++ b/core/tests/coretests/res/values/styles.xml @@ -31,6 +31,9 @@ <style name="LayoutInDisplayCutoutModeNever"> <item name="android:windowLayoutInDisplayCutoutMode">never</item> </style> + <style name="LayoutInDisplayCutoutModeAlways"> + <item name="android:windowLayoutInDisplayCutoutMode">always</item> + </style> <style name="WindowBackgroundColorLiteral"> <item name="android:windowBackground">#00FF00</item> </style> diff --git a/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java b/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java index abaeb0a11a8d..ae6d8df26feb 100644 --- a/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java +++ b/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java @@ -17,8 +17,10 @@ package android.accessibilityservice; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import android.content.ComponentName; import android.content.Context; @@ -48,6 +50,7 @@ import java.util.List; public class AccessibilityShortcutInfoTest { private Context mTargetContext; private PackageManager mPackageManager; + private ComponentName mComponentName; private AccessibilityShortcutInfo mShortcutInfo; @Before @@ -55,25 +58,9 @@ public class AccessibilityShortcutInfoTest { mTargetContext = InstrumentationRegistry.getInstrumentation() .getTargetContext(); mPackageManager = mTargetContext.getPackageManager(); - - final ComponentName testShortcutName = new ComponentName(mTargetContext, - AccessibilityTestActivity.class); - final AccessibilityManager accessibilityManager = (AccessibilityManager) mTargetContext - .getSystemService(Context.ACCESSIBILITY_SERVICE); - final List<AccessibilityShortcutInfo> infoList = accessibilityManager - .getInstalledAccessibilityShortcutListAsUser( - mTargetContext, mTargetContext.getUserId()); - for (AccessibilityShortcutInfo info : infoList) { - final ActivityInfo activityInfo = info.getActivityInfo(); - final ComponentName name = new ComponentName( - activityInfo.packageName, activityInfo.name); - if (name.equals(testShortcutName)) { - mShortcutInfo = info; - break; - } - } - - assertNotNull("Can't find " + testShortcutName, mShortcutInfo); + mComponentName = new ComponentName(mTargetContext, AccessibilityTestActivity.class); + mShortcutInfo = getAccessibilityShortcutInfo(mComponentName); + assertNotNull("Can't find " + mComponentName, mShortcutInfo); } @Test @@ -95,4 +82,38 @@ public class AccessibilityShortcutInfoTest { assertThat("Summary is not correct", mShortcutInfo.loadSummary(mPackageManager), is(summary)); } + + @Test + public void testEquals() { + assertTrue(mShortcutInfo.equals(mShortcutInfo)); + assertFalse(mShortcutInfo.equals(null)); + assertFalse(mShortcutInfo.equals(new Object())); + + final AccessibilityShortcutInfo sameCopy = getAccessibilityShortcutInfo( + mComponentName); + assertTrue(mShortcutInfo != sameCopy); + assertTrue(mShortcutInfo.hashCode() == sameCopy.hashCode()); + assertTrue(mShortcutInfo.getComponentName().equals(sameCopy.getComponentName())); + assertTrue(mShortcutInfo.equals(sameCopy)); + } + + @Test + public void testToString() { + assertNotNull(mShortcutInfo.toString()); + } + + private AccessibilityShortcutInfo getAccessibilityShortcutInfo(ComponentName componentName) { + final AccessibilityManager accessibilityManager = (AccessibilityManager) mTargetContext + .getSystemService(Context.ACCESSIBILITY_SERVICE); + final List<AccessibilityShortcutInfo> infoList = accessibilityManager + .getInstalledAccessibilityShortcutListAsUser( + mTargetContext, mTargetContext.getUserId()); + for (AccessibilityShortcutInfo info : infoList) { + final ActivityInfo activityInfo = info.getActivityInfo(); + if (componentName.equals(activityInfo.getComponentName())) { + return info; + } + } + return null; + } } diff --git a/core/tests/coretests/src/android/app/appsearch/AppSearchDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/AppSearchDocumentTest.java index 2091d556394d..abba7fcce6c7 100644 --- a/core/tests/coretests/src/android/app/appsearch/AppSearchDocumentTest.java +++ b/core/tests/coretests/src/android/app/appsearch/AppSearchDocumentTest.java @@ -40,14 +40,14 @@ public class AppSearchDocumentTest { @Test public void testDocumentEquals_Identical() { Document document1 = Document.newBuilder("uri1", "schemaType1") - .setCreationTimestampSecs(0L) + .setCreationTimestampMillis(5L) .setProperty("longKey1", 1L, 2L, 3L) .setProperty("doubleKey1", 1.0, 2.0, 3.0) .setProperty("booleanKey1", true, false, true) .setProperty("stringKey1", "test-value1", "test-value2", "test-value3") .build(); Document document2 = Document.newBuilder("uri1", "schemaType1") - .setCreationTimestampSecs(0L) + .setCreationTimestampMillis(5L) .setProperty("longKey1", 1L, 2L, 3L) .setProperty("doubleKey1", 1.0, 2.0, 3.0) .setProperty("booleanKey1", true, false, true) @@ -60,7 +60,7 @@ public class AppSearchDocumentTest { @Test public void testDocumentEquals_DifferentOrder() { Document document1 = Document.newBuilder("uri1", "schemaType1") - .setCreationTimestampSecs(0L) + .setCreationTimestampMillis(5L) .setProperty("longKey1", 1L, 2L, 3L) .setProperty("doubleKey1", 1.0, 2.0, 3.0) .setProperty("booleanKey1", true, false, true) @@ -69,7 +69,7 @@ public class AppSearchDocumentTest { // Create second document with same parameter but different order. Document document2 = Document.newBuilder("uri1", "schemaType1") - .setCreationTimestampSecs(0L) + .setCreationTimestampMillis(5L) .setProperty("booleanKey1", true, false, true) .setProperty("stringKey1", "test-value1", "test-value2", "test-value3") .setProperty("doubleKey1", 1.0, 2.0, 3.0) @@ -82,11 +82,13 @@ public class AppSearchDocumentTest { @Test public void testDocumentEquals_Failure() { Document document1 = Document.newBuilder("uri1", "schemaType1") + .setCreationTimestampMillis(5L) .setProperty("longKey1", 1L, 2L, 3L) .build(); // Create second document with same order but different value. Document document2 = Document.newBuilder("uri1", "schemaType1") + .setCreationTimestampMillis(5L) .setProperty("longKey1", 1L, 2L, 4L) // Different .build(); assertThat(document1).isNotEqualTo(document2); @@ -96,11 +98,13 @@ public class AppSearchDocumentTest { @Test public void testDocumentEquals_Failure_RepeatedFieldOrder() { Document document1 = Document.newBuilder("uri1", "schemaType1") + .setCreationTimestampMillis(5L) .setProperty("booleanKey1", true, false, true) .build(); // Create second document with same order but different value. Document document2 = Document.newBuilder("uri1", "schemaType1") + .setCreationTimestampMillis(5L) .setProperty("booleanKey1", true, true, false) // Different .build(); assertThat(document1).isNotEqualTo(document2); @@ -110,12 +114,16 @@ public class AppSearchDocumentTest { @Test public void testDocumentGetSingleValue() { Document document = Document.newBuilder("uri1", "schemaType1") + .setCreationTimestampMillis(5L) + .setScore(1) .setProperty("longKey1", 1L) .setProperty("doubleKey1", 1.0) .setProperty("booleanKey1", true) .setProperty("stringKey1", "test-value1").build(); assertThat(document.getUri()).isEqualTo("uri1"); assertThat(document.getSchemaType()).isEqualTo("schemaType1"); + assertThat(document.getCreationTimestampMillis()).isEqualTo(5); + assertThat(document.getScore()).isEqualTo(1); assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L); assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(1.0); assertThat(document.getPropertyBoolean("booleanKey1")).isTrue(); @@ -125,7 +133,7 @@ public class AppSearchDocumentTest { @Test public void testDocumentGetArrayValues() { Document document = Document.newBuilder("uri1", "schemaType1") - .setScore(1) + .setCreationTimestampMillis(5L) .setProperty("longKey1", 1L, 2L, 3L) .setProperty("doubleKey1", 1.0, 2.0, 3.0) .setProperty("booleanKey1", true, false, true) @@ -134,7 +142,6 @@ public class AppSearchDocumentTest { assertThat(document.getUri()).isEqualTo("uri1"); assertThat(document.getSchemaType()).isEqualTo("schemaType1"); - assertThat(document.getScore()).isEqualTo(1); assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L, 2L, 3L); assertThat(document.getPropertyDoubleArray("doubleKey1")).usingExactEquality() .containsExactly(1.0, 2.0, 3.0); @@ -181,8 +188,8 @@ public class AppSearchDocumentTest { @Test public void testDocumentProtoPopulation() { Document document = Document.newBuilder("uri1", "schemaType1") + .setCreationTimestampMillis(5L) .setScore(1) - .setCreationTimestampSecs(0) .setProperty("longKey1", 1L) .setProperty("doubleKey1", 1.0) .setProperty("booleanKey1", true) @@ -191,7 +198,7 @@ public class AppSearchDocumentTest { // Create the Document proto. Need to sort the property order by key. DocumentProto.Builder documentProtoBuilder = DocumentProto.newBuilder() - .setUri("uri1").setSchema("schemaType1").setScore(1).setCreationTimestampSecs(0); + .setUri("uri1").setSchema("schemaType1").setScore(1).setCreationTimestampMs(5L); HashMap<String, PropertyProto.Builder> propertyProtoMap = new HashMap<>(); propertyProtoMap.put("longKey1", PropertyProto.newBuilder().setName("longKey1").addInt64Values(1L)); diff --git a/core/tests/coretests/src/android/app/appsearch/AppSearchSchemaTest.java b/core/tests/coretests/src/android/app/appsearch/AppSearchSchemaTest.java index 0be52c180338..08ec2d0b1067 100644 --- a/core/tests/coretests/src/android/app/appsearch/AppSearchSchemaTest.java +++ b/core/tests/coretests/src/android/app/appsearch/AppSearchSchemaTest.java @@ -21,14 +21,12 @@ import static com.google.common.truth.Truth.assertThat; import static org.testng.Assert.assertThrows; import static org.testng.Assert.expectThrows; -import android.app.appsearch.AppSearchSchema.IndexingConfig; import android.app.appsearch.AppSearchSchema.PropertyConfig; import androidx.test.filters.SmallTest; import com.google.android.icing.proto.IndexingConfig.TokenizerType; import com.google.android.icing.proto.PropertyConfigProto; -import com.google.android.icing.proto.SchemaProto; import com.google.android.icing.proto.SchemaTypeConfigProto; import com.google.android.icing.proto.TermMatchType; @@ -37,94 +35,87 @@ import org.junit.Test; @SmallTest public class AppSearchSchemaTest { @Test - public void testSuccess() { - AppSearchSchema schema = AppSearchSchema.newBuilder() - .addType(AppSearchSchema.newSchemaTypeBuilder("Email") - .addProperty(AppSearchSchema.newPropertyBuilder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingConfig(AppSearchSchema.newIndexingConfigBuilder() - .setTokenizerType(IndexingConfig.TOKENIZER_TYPE_PLAIN) - .setTermMatchType(IndexingConfig.TERM_MATCH_TYPE_PREFIX) - .build() - ).build() - ).addProperty(AppSearchSchema.newPropertyBuilder("body") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingConfig(AppSearchSchema.newIndexingConfigBuilder() - .setTokenizerType(IndexingConfig.TOKENIZER_TYPE_PLAIN) - .setTermMatchType(IndexingConfig.TERM_MATCH_TYPE_PREFIX) - .build() - ).build() - ).build() - - ).addType(AppSearchSchema.newSchemaTypeBuilder("MusicRecording") - .addProperty(AppSearchSchema.newPropertyBuilder("artist") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_REPEATED) - .setIndexingConfig(AppSearchSchema.newIndexingConfigBuilder() - .setTokenizerType(IndexingConfig.TOKENIZER_TYPE_PLAIN) - .setTermMatchType(IndexingConfig.TERM_MATCH_TYPE_PREFIX) - .build() - ).build() - ).addProperty(AppSearchSchema.newPropertyBuilder("pubDate") - .setDataType(PropertyConfig.DATA_TYPE_INT64) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingConfig(AppSearchSchema.newIndexingConfigBuilder() - .setTokenizerType(IndexingConfig.TOKENIZER_TYPE_NONE) - .setTermMatchType(IndexingConfig.TERM_MATCH_TYPE_UNKNOWN) - .build() - ).build() - ).build() + public void testGetProto_Email() { + AppSearchSchema emailSchema = AppSearchSchema.newBuilder("Email") + .addProperty(AppSearchSchema.newPropertyBuilder("subject") + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build() + ).addProperty(AppSearchSchema.newPropertyBuilder("body") + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build() ).build(); - SchemaProto expectedProto = SchemaProto.newBuilder() - .addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("Email") - .addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("subject") - .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setIndexingConfig( - com.google.android.icing.proto.IndexingConfig.newBuilder() - .setTokenizerType(TokenizerType.Code.PLAIN) - .setTermMatchType(TermMatchType.Code.PREFIX) - ) - ).addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("body") - .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setIndexingConfig( - com.google.android.icing.proto.IndexingConfig.newBuilder() - .setTokenizerType(TokenizerType.Code.PLAIN) - .setTermMatchType(TermMatchType.Code.PREFIX) - ) + SchemaTypeConfigProto expectedEmailProto = SchemaTypeConfigProto.newBuilder() + .setSchemaType("Email") + .addProperties(PropertyConfigProto.newBuilder() + .setPropertyName("subject") + .setDataType(PropertyConfigProto.DataType.Code.STRING) + .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) + .setIndexingConfig( + com.google.android.icing.proto.IndexingConfig.newBuilder() + .setTokenizerType(TokenizerType.Code.PLAIN) + .setTermMatchType(TermMatchType.Code.PREFIX) ) + ).addProperties(PropertyConfigProto.newBuilder() + .setPropertyName("body") + .setDataType(PropertyConfigProto.DataType.Code.STRING) + .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) + .setIndexingConfig( + com.google.android.icing.proto.IndexingConfig.newBuilder() + .setTokenizerType(TokenizerType.Code.PLAIN) + .setTermMatchType(TermMatchType.Code.PREFIX) + ) + ).build(); + + assertThat(emailSchema.getProto()).isEqualTo(expectedEmailProto); + } + + @Test + public void testGetProto_MusicRecording() { + AppSearchSchema musicRecordingSchema = AppSearchSchema.newBuilder("MusicRecording") + .addProperty(AppSearchSchema.newPropertyBuilder("artist") + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_REPEATED) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build() + ).addProperty(AppSearchSchema.newPropertyBuilder("pubDate") + .setDataType(PropertyConfig.DATA_TYPE_INT64) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType(PropertyConfig.INDEXING_TYPE_NONE) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_NONE) + .build() + ).build(); - ).addTypes(SchemaTypeConfigProto.newBuilder() - .setSchemaType("MusicRecording") - .addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("artist") - .setDataType(PropertyConfigProto.DataType.Code.STRING) - .setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED) - .setIndexingConfig( - com.google.android.icing.proto.IndexingConfig.newBuilder() - .setTokenizerType(TokenizerType.Code.PLAIN) - .setTermMatchType(TermMatchType.Code.PREFIX) - ) - ).addProperties(PropertyConfigProto.newBuilder() - .setPropertyName("pubDate") - .setDataType(PropertyConfigProto.DataType.Code.INT64) - .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) - .setIndexingConfig( - com.google.android.icing.proto.IndexingConfig.newBuilder() - .setTokenizerType(TokenizerType.Code.NONE) - .setTermMatchType(TermMatchType.Code.UNKNOWN) - ) + SchemaTypeConfigProto expectedMusicRecordingProto = SchemaTypeConfigProto.newBuilder() + .setSchemaType("MusicRecording") + .addProperties(PropertyConfigProto.newBuilder() + .setPropertyName("artist") + .setDataType(PropertyConfigProto.DataType.Code.STRING) + .setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED) + .setIndexingConfig( + com.google.android.icing.proto.IndexingConfig.newBuilder() + .setTokenizerType(TokenizerType.Code.PLAIN) + .setTermMatchType(TermMatchType.Code.PREFIX) + ) + ).addProperties(PropertyConfigProto.newBuilder() + .setPropertyName("pubDate") + .setDataType(PropertyConfigProto.DataType.Code.INT64) + .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) + .setIndexingConfig( + com.google.android.icing.proto.IndexingConfig.newBuilder() + .setTokenizerType(TokenizerType.Code.NONE) + .setTermMatchType(TermMatchType.Code.UNKNOWN) ) ).build(); - assertThat(schema.getProto()).isEqualTo(expectedProto); + assertThat(musicRecordingSchema.getProto()).isEqualTo(expectedMusicRecordingProto); } @Test @@ -151,4 +142,25 @@ public class AppSearchSchemaTest { builder.setCardinality(PropertyConfig.CARDINALITY_REPEATED); builder.build(); } + + @Test + public void testDuplicateProperties() { + AppSearchSchema.Builder builder = AppSearchSchema.newBuilder("Email") + .addProperty(AppSearchSchema.newPropertyBuilder("subject") + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build() + ).addProperty(AppSearchSchema.newPropertyBuilder("subject") + .setDataType(PropertyConfig.DATA_TYPE_STRING) + .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) + .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) + .build() + ); + + Exception e = expectThrows(IllegalSchemaException.class, builder::build); + assertThat(e).hasMessageThat().contains("Property defined more than once: subject"); + } } diff --git a/core/tests/coretests/src/android/app/appsearch/impl/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/impl/CustomerDocumentTest.java index 4ee4aa6d527f..c5986bb2f07b 100644 --- a/core/tests/coretests/src/android/app/appsearch/impl/CustomerDocumentTest.java +++ b/core/tests/coretests/src/android/app/appsearch/impl/CustomerDocumentTest.java @@ -36,7 +36,7 @@ public class CustomerDocumentTest { public void testBuildCustomerDocument() { CustomerDocument customerDocument = CustomerDocument.newBuilder("uri1") .setScore(1) - .setCreationTimestampSecs(0) + .setCreationTimestampMillis(0) .setProperty("longKey1", 1L, 2L, 3L) .setProperty("doubleKey1", 1.0, 2.0, 3.0) .setProperty("booleanKey1", true, false, true) @@ -46,7 +46,7 @@ public class CustomerDocumentTest { assertThat(customerDocument.getUri()).isEqualTo("uri1"); assertThat(customerDocument.getSchemaType()).isEqualTo("customerDocument"); assertThat(customerDocument.getScore()).isEqualTo(1); - assertThat(customerDocument.getCreationTimestampSecs()).isEqualTo(0L); + assertThat(customerDocument.getCreationTimestampMillis()).isEqualTo(0L); assertThat(customerDocument.getPropertyLongArray("longKey1")).asList() .containsExactly(1L, 2L, 3L); assertThat(customerDocument.getPropertyDoubleArray("doubleKey1")).usingExactEquality() diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java index d5a0dfadcbe5..7c2b98f3e167 100644 --- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java +++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java @@ -69,6 +69,8 @@ public class DisplayCutoutTest { null /* boundBottom */); final DisplayCutout mCutoutTop = createCutoutTop(); + final DisplayCutout mCutoutWithWaterfall = createCutoutWithWaterfall(); + final DisplayCutout mWaterfallOnly = createCutoutWaterfallOnly(); @Test public void testExtractBoundsFromList_left() { @@ -126,9 +128,23 @@ public class DisplayCutoutTest { } @Test - public void hasCutout() throws Exception { - assertTrue(NO_CUTOUT.isEmpty()); - assertFalse(mCutoutTop.isEmpty()); + public void testHasCutout_noCutout() throws Exception { + assertTrue(NO_CUTOUT.isBoundsEmpty()); + } + + @Test + public void testHasCutout_cutoutOnly() { + assertFalse(mCutoutTop.isBoundsEmpty()); + } + + @Test + public void testHasCutout_cutoutWithWaterfall() { + assertFalse(mCutoutWithWaterfall.isBoundsEmpty()); + } + + @Test + public void testHasCutout_waterfallOnly() { + assertTrue(mWaterfallOnly.isBoundsEmpty()); } @Test @@ -142,20 +158,27 @@ public class DisplayCutoutTest { } @Test + public void testGetWaterfallInsets() throws Exception { + DisplayCutout cutout = + createCutoutWaterfallOnly(Insets.of(5, 6, 7, 8)); + assertEquals(Insets.of(5, 6, 7, 8), cutout.getWaterfallInsets()); + } + + @Test public void testHashCode() throws Exception { - assertEquals(mCutoutTop.hashCode(), createCutoutTop().hashCode()); - assertNotEquals(mCutoutTop.hashCode(), mCutoutNumbers.hashCode()); + assertEquals(mCutoutWithWaterfall.hashCode(), createCutoutWithWaterfall().hashCode()); + assertNotEquals(mCutoutWithWaterfall.hashCode(), mCutoutNumbers.hashCode()); } @Test public void testEquals() throws Exception { - assertEquals(mCutoutTop, createCutoutTop()); - assertNotEquals(mCutoutTop, mCutoutNumbers); + assertEquals(mCutoutWithWaterfall, createCutoutWithWaterfall()); + assertNotEquals(mCutoutWithWaterfall, mCutoutNumbers); } @Test public void testToString() throws Exception { - assertFalse(mCutoutTop.toString().isEmpty()); + assertFalse(mCutoutWithWaterfall.toString().isEmpty()); assertFalse(mCutoutNumbers.toString().isEmpty()); } @@ -240,12 +263,12 @@ public class DisplayCutoutTest { public void parcel_unparcel_regular() { Parcel p = Parcel.obtain(); - new ParcelableWrapper(mCutoutTop).writeToParcel(p, 0); + new ParcelableWrapper(mCutoutWithWaterfall).writeToParcel(p, 0); int posAfterWrite = p.dataPosition(); p.setDataPosition(0); - assertEquals(mCutoutTop, ParcelableWrapper.CREATOR.createFromParcel(p).get()); + assertEquals(mCutoutWithWaterfall, ParcelableWrapper.CREATOR.createFromParcel(p).get()); assertEquals(posAfterWrite, p.dataPosition()); } @@ -264,44 +287,64 @@ public class DisplayCutoutTest { @Test public void fromSpec_caches() { - DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f); - assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), sameInstance(cached)); + Insets waterfallInsets = Insets.of(0, 20, 0, 20); + DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, waterfallInsets); + assertThat( + fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, waterfallInsets), + sameInstance(cached)); } @Test public void fromSpec_wontCacheIfSpecChanges() { - DisplayCutout cached = fromSpec("L1,0 L1000,1000 L0,1 z", 200, 400, 1f); - assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached))); + DisplayCutout cached = fromSpec("L1,0 L1000,1000 L0,1 z", 200, 400, 1f, Insets.NONE); + assertThat( + fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, Insets.NONE), + not(sameInstance(cached))); } @Test public void fromSpec_wontCacheIfScreenWidthChanges() { - DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 2000, 400, 1f); - assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached))); + DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 2000, 400, 1f, Insets.NONE); + assertThat( + fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, Insets.NONE), + not(sameInstance(cached))); } @Test public void fromSpec_wontCacheIfScreenHeightChanges() { - DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 4000, 1f); - assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached))); + DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 4000, 1f, Insets.NONE); + assertThat( + fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, Insets.NONE), + not(sameInstance(cached))); } @Test public void fromSpec_wontCacheIfDensityChanges() { - DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f); - assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached))); + DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f, Insets.NONE); + assertThat( + fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, Insets.NONE), + not(sameInstance(cached))); + } + + @Test + public void fromSpec_wontCacheIfWaterfallInsetsChange() { + Insets waterfallInsets = Insets.of(0, 20, 0, 20); + DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f, Insets.NONE); + assertThat( + fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f, waterfallInsets), + not(sameInstance(cached))); } @Test public void fromSpec_setsSafeInsets_top() { - DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z", 200, 400, 2f); + DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z", 200, 400, 2f, Insets.NONE); assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 0))); } @Test public void fromSpec_setsSafeInsets_top_and_bottom() { DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z" - + "@bottom M -50,0 v -10,0 h 100 v 20 z", 200, 400, 2f); + + "@bottom M -50,0 v -10,0 h 100 v 20 z", 200, 400, 2f, Insets.NONE); assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 10))); assertThat(cutout.getBoundingRectsAll(), equalTo(new Rect[]{ ZERO_RECT, new Rect(50, 0, 150, 20), @@ -310,6 +353,38 @@ public class DisplayCutoutTest { } @Test + public void fromSpec_setsSafeInsets_waterfallTopBottom() { + DisplayCutout cutout = fromSpec("", 200, 400, 2f, Insets.of(0, 30, 0, 30)); + assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 30, 0, 30))); + } + + @Test + public void fromSpec_setsSafeInsets_waterfallLeftRight() { + DisplayCutout cutout = fromSpec("", 200, 400, 2f, Insets.of(30, 0, 30, 0)); + assertThat(cutout.getSafeInsets(), equalTo(new Rect(30, 0, 30, 0))); + } + + @Test + public void fromSpec_setsSafeInsets_waterfall_allEdges() { + DisplayCutout cutout = fromSpec("", 200, 400, 2f, Insets.of(30, 30, 30, 30)); + assertThat(cutout.getSafeInsets(), equalTo(new Rect(30, 30, 30, 30))); + } + + @Test + public void fromSpec_setsSafeInsets_cutoutTopBottom_waterfallTopBottom() { + DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z" + + "@bottom M -50,0 v -20,0 h 100 v 20 z", 200, 400, 2f, Insets.of(0, 30, 0, 30)); + assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 30, 0, 30))); + } + + @Test + public void fromSpec_setsSafeInsets_cutoutTopBottom_waterfallLeftRight() { + DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z" + + "@bottom M -50,0 v -20,0 h 100 v 20 z", 200, 400, 2f, Insets.of(30, 0, 30, 0)); + assertThat(cutout.getSafeInsets(), equalTo(new Rect(30, 20, 30, 20))); + } + + @Test public void parcel_unparcel_nocutout() { Parcel p = Parcel.obtain(); @@ -326,7 +401,7 @@ public class DisplayCutoutTest { public void parcel_unparcel_inplace() { Parcel p = Parcel.obtain(); - new ParcelableWrapper(mCutoutTop).writeToParcel(p, 0); + new ParcelableWrapper(mCutoutWithWaterfall).writeToParcel(p, 0); int posAfterWrite = p.dataPosition(); p.setDataPosition(0); @@ -334,22 +409,24 @@ public class DisplayCutoutTest { ParcelableWrapper wrapper = new ParcelableWrapper(); wrapper.readFromParcel(p); - assertEquals(mCutoutTop, wrapper.get()); + assertEquals(mCutoutWithWaterfall, wrapper.get()); assertEquals(posAfterWrite, p.dataPosition()); } @Test public void wrapper_hashcode() throws Exception { - assertEquals(new ParcelableWrapper(mCutoutTop).hashCode(), - new ParcelableWrapper(createCutoutTop()).hashCode()); - assertNotEquals(new ParcelableWrapper(mCutoutTop).hashCode(), + assertEquals(new ParcelableWrapper(mCutoutWithWaterfall).hashCode(), + new ParcelableWrapper(createCutoutWithWaterfall()).hashCode()); + assertNotEquals(new ParcelableWrapper(mCutoutWithWaterfall).hashCode(), new ParcelableWrapper(mCutoutNumbers).hashCode()); } @Test public void wrapper_equals() throws Exception { - assertEquals(new ParcelableWrapper(mCutoutTop), new ParcelableWrapper(createCutoutTop())); - assertNotEquals(new ParcelableWrapper(mCutoutTop), new ParcelableWrapper(mCutoutNumbers)); + assertEquals(new ParcelableWrapper(mCutoutWithWaterfall), + new ParcelableWrapper(createCutoutWithWaterfall())); + assertNotEquals(new ParcelableWrapper(mCutoutWithWaterfall), + new ParcelableWrapper(mCutoutNumbers)); } private static DisplayCutout createCutoutTop() { @@ -363,4 +440,28 @@ public class DisplayCutoutTest { safeInset, null /* boundLeft */, boundTop, null /* boundRight */, null /* boundBottom */); } + + private static DisplayCutout createCutoutWithWaterfall() { + return new DisplayCutout( + Insets.of(20, 100, 20, 0), + ZERO_RECT, + new Rect(50, 0, 75, 100), + ZERO_RECT, + ZERO_RECT, + Insets.of(20, 0, 20, 0)); + } + + private static DisplayCutout createCutoutWaterfallOnly() { + return createCutoutWaterfallOnly(Insets.of(20, 0, 20, 0)); + } + + private static DisplayCutout createCutoutWaterfallOnly(Insets waterfallInsets) { + return new DisplayCutout( + Insets.of(20, 0, 20, 0), + ZERO_RECT, + ZERO_RECT, + ZERO_RECT, + ZERO_RECT, + waterfallInsets); + } } diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java index d0fd92a838c9..7c78bce25b1c 100644 --- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java @@ -74,7 +74,7 @@ public class ImeInsetsSourceConsumerTest { false, new DisplayCutout( Insets.of(10, 10, 10, 10), rect, rect, rect, rect), - rect, rect, SOFT_INPUT_ADJUST_RESIZE); + rect, rect, SOFT_INPUT_ADJUST_RESIZE, 0); mImeConsumer = new ImeInsetsSourceConsumer( new InsetsState(), Transaction::new, mController); }); diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index 628f7ecce9f1..838190387c35 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -114,7 +114,7 @@ public class InsetsControllerTest { false, new DisplayCutout( Insets.of(10, 10, 10, 10), rect, rect, rect, rect), - rect, rect, SOFT_INPUT_ADJUST_RESIZE); + rect, rect, SOFT_INPUT_ADJUST_RESIZE, 0); mController.onFrameChanged(new Rect(0, 0, 100, 100)); }); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index 4b76fee00496..9e4b1c55304f 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -23,6 +23,7 @@ import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; +import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE; import static android.view.WindowInsets.Type.ime; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; @@ -72,7 +73,7 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setVisible(true); SparseIntArray typeSideMap = new SparseIntArray(); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, typeSideMap); + DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, typeSideMap); assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all())); assertEquals(ISIDE_TOP, typeSideMap.get(ITYPE_STATUS_BAR)); @@ -91,7 +92,7 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setFrame(new Rect(0, 100, 100, 300)); mState.getSource(ITYPE_IME).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, null); + DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, null); assertEquals(100, insets.getStableInsetBottom()); assertEquals(Insets.of(0, 0, 0, 100), insets.getMaxInsets(Type.systemBars())); assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets()); @@ -110,7 +111,7 @@ public class InsetsStateTest { mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300)); mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, 0, null); + DisplayCutout.NO_CUTOUT, null, null, 0, 0, null); assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars())); assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars())); @@ -126,7 +127,7 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); mState.getSource(ITYPE_IME).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, null); + DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, 0, null); assertEquals(0, insets.getSystemWindowInsetBottom()); assertEquals(100, insets.getInsets(ime()).bottom); assertTrue(insets.isVisible(ime())); @@ -134,6 +135,25 @@ public class InsetsStateTest { } @Test + public void testCalculateInsets_systemUiFlagLayoutStable() { + try (final InsetsModeSession session = + new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) { + mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100)); + mState.getSource(ITYPE_STATUS_BAR).setVisible(false); + mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); + mState.getSource(ITYPE_IME).setVisible(true); + WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, + DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, + SYSTEM_UI_FLAG_LAYOUT_STABLE, null); + assertEquals(100, insets.getSystemWindowInsetTop()); + insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, + DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_NOTHING, + 0 /* legacySystemUiFlags */, null); + assertEquals(0, insets.getSystemWindowInsetTop()); + } + } + + @Test public void testStripForDispatch() { mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100)); mState.getSource(ITYPE_STATUS_BAR).setVisible(true); @@ -141,7 +161,7 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setVisible(true); mState.removeSource(ITYPE_IME); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false, - DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, null); + DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, null); assertEquals(0, insets.getSystemWindowInsetBottom()); } diff --git a/core/tests/coretests/src/android/view/WindowInsetsTest.java b/core/tests/coretests/src/android/view/WindowInsetsTest.java index e5a4f6d5b3be..fce2ebd08888 100644 --- a/core/tests/coretests/src/android/view/WindowInsetsTest.java +++ b/core/tests/coretests/src/android/view/WindowInsetsTest.java @@ -16,10 +16,12 @@ package android.view; +import static android.view.WindowInsets.Type.SIZE; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowInsets.Type.statusBars; +import static android.view.WindowInsets.Type.systemBars; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -28,6 +30,7 @@ import android.graphics.Insets; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.WindowInsets.Builder; +import android.view.WindowInsets.Type; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -56,6 +59,18 @@ public class WindowInsetsTest { assertTrue(new WindowInsets((Rect) null).isConsumed()); } + @Test + public void compatInsets_layoutStable() { + Insets[] insets = new Insets[SIZE]; + Insets[] maxInsets = new Insets[SIZE]; + boolean[] visible = new boolean[SIZE]; + WindowInsets.assignCompatInsets(maxInsets, new Rect(0, 10, 0, 0)); + WindowInsets.assignCompatInsets(insets, new Rect(0, 0, 0, 0)); + WindowInsets windowInsets = new WindowInsets(insets, maxInsets, visible, false, false, null, + systemBars(), true /* compatIgnoreVisibility */); + assertEquals(Insets.of(0, 10, 0, 0), windowInsets.getSystemWindowInsets()); + } + // TODO: Move this to CTS once API made public @Test public void typeMap() { diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java index 6c2d630ac917..916e2b51ea53 100644 --- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java +++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java @@ -16,6 +16,7 @@ package com.android.internal.policy; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; @@ -94,6 +95,15 @@ public final class PhoneWindowTest { } @Test + public void layoutInDisplayCutoutMode_always() throws Exception { + createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeAlways); + installDecor(); + + assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode, + is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS)); + } + + @Test public void testWindowBackground_colorLiteral() { createPhoneWindowWithTheme(R.style.WindowBackgroundColorLiteral); installDecor(); diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java index e4bab7466a70..f89893136804 100644 --- a/media/java/android/media/CamcorderProfile.java +++ b/media/java/android/media/CamcorderProfile.java @@ -99,25 +99,21 @@ public class CamcorderProfile /** * Quality level corresponding to the VGA (640 x 480) resolution. - * @hide */ public static final int QUALITY_VGA = 9; /** * Quality level corresponding to 4k-DCI (4096 x 2160) resolution. - * @hide */ public static final int QUALITY_4KDCI = 10; /** * Quality level corresponding to QHD (2560 x 1440) resolution - * @hide */ public static final int QUALITY_QHD = 11; /** * Quality level corresponding to 2K (2048 x 1080) resolution - * @hide */ public static final int QUALITY_2K = 12; @@ -172,25 +168,21 @@ public class CamcorderProfile /** * Time lapse quality level corresponding to the VGA (640 x 480) resolution. - * @hide */ public static final int QUALITY_TIME_LAPSE_VGA = 1009; /** * Time lapse quality level corresponding to the 4k-DCI (4096 x 2160) resolution. - * @hide */ public static final int QUALITY_TIME_LAPSE_4KDCI = 1010; /** * Time lapse quality level corresponding to the QHD (2560 x 1440) resolution. - * @hide */ public static final int QUALITY_TIME_LAPSE_QHD = 1011; /** * Time lapse quality level corresponding to the 2K (2048 x 1080) resolution. - * @hide */ public static final int QUALITY_TIME_LAPSE_2K = 1012; @@ -255,19 +247,16 @@ public class CamcorderProfile /** * High speed ( >= 100fps) quality level corresponding to the CIF (352 x 288) - * @hide */ public static final int QUALITY_HIGH_SPEED_CIF = 2006; /** * High speed ( >= 100fps) quality level corresponding to the VGA (640 x 480) - * @hide */ public static final int QUALITY_HIGH_SPEED_VGA = 2007; /** * High speed ( >= 100fps) quality level corresponding to the 4K-DCI (4096 x 2160) - * @hide */ public static final int QUALITY_HIGH_SPEED_4KDCI = 2008; diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index 281e7c6b6f68..dac0fba876be 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -46,6 +46,7 @@ interface IMediaRouterService { // Methods for media router 2 List<MediaRoute2Info> getSystemRoutes(); + RoutingSessionInfo getSystemSessionInfo(); void registerClient2(IMediaRouter2Client client, String packageName); void unregisterClient2(IMediaRouter2Client client); void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route, diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 51d08ec96e6f..a6198842abe8 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -76,6 +76,8 @@ public class MediaRouter2 { @GuardedBy("sRouterLock") final Map<String, MediaRoute2Info> mRoutes = new HashMap<>(); + final RoutingController mDefaultController; + @GuardedBy("sRouterLock") private RouteDiscoveryPreference mDiscoveryPreference = RouteDiscoveryPreference.EMPTY; @@ -116,19 +118,26 @@ public class MediaRouter2 { mHandler = new Handler(Looper.getMainLooper()); List<MediaRoute2Info> currentSystemRoutes = null; + RoutingSessionInfo currentSystemSessionInfo = null; try { currentSystemRoutes = mMediaRouterService.getSystemRoutes(); + currentSystemSessionInfo = mMediaRouterService.getSystemSessionInfo(); } catch (RemoteException ex) { - Log.e(TAG, "Unable to get current currentSystemRoutes", ex); + Log.e(TAG, "Unable to get current system's routes / session info", ex); } if (currentSystemRoutes == null || currentSystemRoutes.isEmpty()) { throw new RuntimeException("Null or empty currentSystemRoutes. Something is wrong."); } + if (currentSystemSessionInfo == null) { + throw new RuntimeException("Null currentSystemSessionInfo. Something is wrong."); + } + for (MediaRoute2Info route : currentSystemRoutes) { mRoutes.put(route.getId(), route); } + mDefaultController = new DefaultRoutingController(currentSystemSessionInfo); } /** @@ -341,6 +350,22 @@ public class MediaRouter2 { } /** + * Gets a {@link RoutingController} which can control the routes provided by system. + * e.g. Phone speaker, wired headset, Bluetooth, etc. + * <p> + * Note: The default controller can't be released. Calling {@link RoutingController#release()} + * will be no-op. + * <p> + * This method will always return the same instance. + * + * @hide + */ + @NonNull + public RoutingController getDefaultController() { + return mDefaultController; + } + + /** * Sends a media control request to be performed asynchronously by the route's destination. * * @param route the route that will receive the control request @@ -526,6 +551,15 @@ public class MediaRouter2 { return; } + if (sessionInfo.isSystemSession()) { + // The session info is sent from SystemMediaRoute2Provider. + RoutingController defaultController = getDefaultController(); + RoutingSessionInfo oldInfo = defaultController.getRoutingSessionInfo(); + defaultController.setRoutingSessionInfo(sessionInfo); + notifySessionInfoChanged(defaultController, oldInfo, sessionInfo); + return; + } + RoutingController matchingController; synchronized (sRouterLock) { matchingController = mRoutingControllers.get(sessionInfo.getId()); @@ -766,7 +800,7 @@ public class MediaRouter2 { * * @hide */ - public final class RoutingController { + public class RoutingController { private final Object mControllerLock = new Object(); @GuardedBy("mControllerLock") @@ -1074,7 +1108,6 @@ public class MediaRouter2 { // TODO: This method uses two locks (mLock outside, sLock inside). // Check if there is any possiblity of deadlock. private List<MediaRoute2Info> getRoutesWithIdsLocked(List<String> routeIds) { - List<MediaRoute2Info> routes = new ArrayList<>(); synchronized (sRouterLock) { // TODO: Maybe able to change using Collection.stream()? @@ -1089,6 +1122,23 @@ public class MediaRouter2 { } } + class DefaultRoutingController extends RoutingController { + DefaultRoutingController(@NonNull RoutingSessionInfo sessionInfo) { + super(sessionInfo); + } + + @Override + public void release() { + // Do nothing. DefaultRoutingController will never be released + } + + @Override + public boolean isReleased() { + // DefaultRoutingController will never be released + return false; + } + } + final class RouteCallbackRecord { public final Executor mExecutor; public final RouteCallback mRouteCallback; diff --git a/media/java/android/media/MediaRouter2Utils.java b/media/java/android/media/MediaRouter2Utils.java index 49045828dbe8..c15972dcff2e 100644 --- a/media/java/android/media/MediaRouter2Utils.java +++ b/media/java/android/media/MediaRouter2Utils.java @@ -29,9 +29,6 @@ public class MediaRouter2Utils { static final String TAG = "MR2Utils"; static final String SEPARATOR = ":"; - /** - * @hide - */ @NonNull public static String toUniqueId(@NonNull String providerId, @NonNull String id) { if (TextUtils.isEmpty(providerId)) { @@ -49,8 +46,6 @@ public class MediaRouter2Utils { /** * Gets provider ID from unique ID. * If the corresponding provider ID could not be generated, it will return null. - * - * @hide */ @Nullable public static String getProviderId(@NonNull String uniqueId) { @@ -75,8 +70,6 @@ public class MediaRouter2Utils { /** * Gets the original ID (i.e. non-unique route/session ID) from unique ID. * If the corresponding ID could not be generated, it will return null. - * - * @hide */ @Nullable public static String getOriginalId(@NonNull String uniqueId) { diff --git a/media/java/android/media/RoutingSessionInfo.java b/media/java/android/media/RoutingSessionInfo.java index 228addebe029..cb996f493eb4 100644 --- a/media/java/android/media/RoutingSessionInfo.java +++ b/media/java/android/media/RoutingSessionInfo.java @@ -59,6 +59,7 @@ public final class RoutingSessionInfo implements Parcelable { final List<String> mTransferrableRoutes; @Nullable final Bundle mControlHints; + final boolean mIsSystemSession; RoutingSessionInfo(@NonNull Builder builder) { Objects.requireNonNull(builder, "builder must not be null."); @@ -78,6 +79,7 @@ public final class RoutingSessionInfo implements Parcelable { convertToUniqueRouteIds(builder.mTransferrableRoutes)); mControlHints = builder.mControlHints; + mIsSystemSession = builder.mIsSystemSession; } RoutingSessionInfo(@NonNull Parcel src) { @@ -93,6 +95,7 @@ public final class RoutingSessionInfo implements Parcelable { mTransferrableRoutes = ensureList(src.createStringArrayList()); mControlHints = src.readBundle(); + mIsSystemSession = src.readBoolean(); } private static String ensureString(String str) { @@ -193,6 +196,15 @@ public final class RoutingSessionInfo implements Parcelable { return mControlHints; } + /** + * Gets whether this session is in system media route provider. + * @hide + */ + @Nullable + public boolean isSystemSession() { + return mIsSystemSession; + } + @Override public int describeContents() { return 0; @@ -208,6 +220,7 @@ public final class RoutingSessionInfo implements Parcelable { dest.writeStringList(mDeselectableRoutes); dest.writeStringList(mTransferrableRoutes); dest.writeBundle(mControlHints); + dest.writeBoolean(mIsSystemSession); } @Override @@ -278,6 +291,7 @@ public final class RoutingSessionInfo implements Parcelable { * Builder class for {@link RoutingSessionInfo}. */ public static final class Builder { + // TODO: Reorder these (important ones first) final String mId; final String mClientPackageName; String mProviderId; @@ -286,6 +300,7 @@ public final class RoutingSessionInfo implements Parcelable { final List<String> mDeselectableRoutes; final List<String> mTransferrableRoutes; Bundle mControlHints; + boolean mIsSystemSession; /** * Constructor for builder to create {@link RoutingSessionInfo}. @@ -333,6 +348,7 @@ public final class RoutingSessionInfo implements Parcelable { mTransferrableRoutes = new ArrayList<>(sessionInfo.mTransferrableRoutes); mControlHints = sessionInfo.mControlHints; + mIsSystemSession = sessionInfo.mIsSystemSession; } /** @@ -491,6 +507,16 @@ public final class RoutingSessionInfo implements Parcelable { } /** + * Sets whether this session is in system media route provider. + * @hide + */ + @NonNull + public Builder setSystemSession(boolean isSystemSession) { + mIsSystemSession = isSystemSession; + return this; + } + + /** * Builds a routing session info. * * @throws IllegalArgumentException if no selected routes are added. diff --git a/media/java/android/media/tv/tuner/FrontendSettings.java b/media/java/android/media/tv/tuner/FrontendSettings.java index ad8422caaa02..7f9b9826c94b 100644 --- a/media/java/android/media/tv/tuner/FrontendSettings.java +++ b/media/java/android/media/tv/tuner/FrontendSettings.java @@ -16,33 +16,10 @@ package android.media.tv.tuner; -import android.annotation.SystemApi; - /** * Frontend settings for tune and scan operations. + * TODO: remove * @hide */ -@SystemApi public abstract class FrontendSettings { - private final int mFrequency; - - /** @hide */ - public FrontendSettings(int frequency) { - mFrequency = frequency; - } - - /** - * Returns the frontend type. - */ - public abstract int getType(); - - /** - * Gets the frequency setting. - * - * @return the frequency in Hz. - */ - public final int getFrequency() { - return mFrequency; - } - } diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index b76001facb45..44579540b0ce 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -33,6 +33,7 @@ import android.media.tv.tuner.filter.Filter.Type; import android.media.tv.tuner.filter.FilterEvent; import android.media.tv.tuner.filter.TimeFilter; import android.media.tv.tuner.frontend.FrontendInfo; +import android.media.tv.tuner.frontend.FrontendSettings; import android.media.tv.tuner.frontend.FrontendStatus; import android.media.tv.tuner.frontend.OnTuneEventListener; import android.media.tv.tuner.frontend.ScanCallback; diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java index a30ddc73ac45..614d79ce99c5 100644 --- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java +++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java @@ -18,7 +18,11 @@ package android.media.tv.tuner.frontend; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.content.Context; import android.hardware.tv.tuner.V1_0.Constants; +import android.media.tv.tuner.TunerUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -28,6 +32,7 @@ import java.lang.annotation.RetentionPolicy; * * @hide */ +@SystemApi public class AnalogFrontendSettings extends FrontendSettings { /** @hide */ @IntDef(flag = true, @@ -137,7 +142,7 @@ public class AnalogFrontendSettings extends FrontendSettings { public static final int SIF_L_PRIME = Constants.FrontendAnalogSifStandard.L_PRIME; - private final int mAnalogType; + private final int mSignalType; private final int mSifStandard; @Override @@ -150,8 +155,8 @@ public class AnalogFrontendSettings extends FrontendSettings { * Gets analog signal type. */ @SignalType - public int getAnalogType() { - return mAnalogType; + public int getSignalType() { + return mSignalType; } /** @@ -164,43 +169,37 @@ public class AnalogFrontendSettings extends FrontendSettings { /** * Creates a builder for {@link AnalogFrontendSettings}. + * + * @param the context of the caller. */ + @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) @NonNull - public static Builder newBuilder() { + public static Builder builder(@NonNull Context context) { + TunerUtils.checkTunerPermission(context); return new Builder(); } - private AnalogFrontendSettings(int frequency, int analogType, int sifStandard) { + private AnalogFrontendSettings(int frequency, int signalType, int sifStandard) { super(frequency); - mAnalogType = analogType; + mSignalType = signalType; mSifStandard = sifStandard; } /** * Builder for {@link AnalogFrontendSettings}. */ - public static class Builder { - private int mFrequency; - private int mAnalogType; + public static class Builder extends FrontendSettings.Builder<Builder> { + private int mSignalType; private int mSifStandard; private Builder() {} /** - * Sets frequency in Hz. + * Sets analog signal type. */ @NonNull - public Builder setFrequency(int frequency) { - mFrequency = frequency; - return this; - } - - /** - * Sets analog type. - */ - @NonNull - public Builder setAnalogType(@SignalType int analogType) { - mAnalogType = analogType; + public Builder setASignalType(@SignalType int signalType) { + mSignalType = signalType; return this; } @@ -218,7 +217,12 @@ public class AnalogFrontendSettings extends FrontendSettings { */ @NonNull public AnalogFrontendSettings build() { - return new AnalogFrontendSettings(mFrequency, mAnalogType, mSifStandard); + return new AnalogFrontendSettings(mFrequency, mSignalType, mSifStandard); + } + + @Override + Builder self() { + return this; } } } diff --git a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java index 617d6089a610..b80b7cd5212a 100644 --- a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java +++ b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java @@ -19,6 +19,7 @@ package android.media.tv.tuner.frontend; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.hardware.tv.tuner.V1_0.Constants; import java.lang.annotation.Retention; @@ -29,6 +30,7 @@ import java.lang.annotation.RetentionPolicy; * * @hide */ +@SystemApi public abstract class FrontendSettings { /** @hide */ @IntDef({TYPE_UNDEFINED, TYPE_ANALOG, TYPE_ATSC, TYPE_ATSC3, TYPE_DVBC, TYPE_DVBS, TYPE_DVBT, diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java index 32d03db6f7ee..a9fcf7703cfc 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java @@ -692,6 +692,14 @@ public class MediaRouter2Test { } } + // TODO: Consider adding tests with bluetooth connection/disconnection. + @Test + public void testGetDefaultController() { + final RoutingController defaultController = mRouter2.getDefaultController(); + assertNotNull(defaultController); + assertFalse(defaultController.isReleased()); + } + // Helper for getting routes easily static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) { Map<String, MediaRoute2Info> routeMap = new HashMap<>(); diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java index cba8452fe9c2..39313eec6bf8 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java @@ -227,7 +227,7 @@ public class MediaRouterManagerTest { mManager.selectRoute(mPackageName, routeToSelect); assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - assertEquals(1, mManager.getActiveSessions().size()); + assertEquals(2, mManager.getActiveSessions().size()); } @Test diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp index e663534c7a01..51439672d404 100644 --- a/native/graphics/jni/imagedecoder.cpp +++ b/native/graphics/jni/imagedecoder.cpp @@ -225,13 +225,12 @@ AndroidBitmapFormat AImageDecoderHeaderInfo_getAndroidBitmapFormat( int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) { if (!info) { - // FIXME: Better invalid? - return -1; + return ANDROID_IMAGE_DECODER_BAD_PARAMETER; } switch (toDecoder(info)->mCodec->getInfo().alphaType()) { case kUnknown_SkAlphaType: LOG_ALWAYS_FATAL("Invalid alpha type"); - return -1; + return ANDROID_IMAGE_DECODER_INTERNAL_ERROR; case kUnpremul_SkAlphaType: // fall through. premul is the default. case kPremul_SkAlphaType: diff --git a/packages/CarSystemUI/res/layout/super_notification_shade.xml b/packages/CarSystemUI/res/layout/super_notification_shade.xml new file mode 100644 index 000000000000..3fe1ea331a07 --- /dev/null +++ b/packages/CarSystemUI/res/layout/super_notification_shade.xml @@ -0,0 +1,111 @@ +<?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. +*/ +--> + +<!-- This is the notification shade window. --> +<com.android.systemui.statusbar.phone.NotificationShadeWindowView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:sysui="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:fitsSystemWindows="true"> + + <com.android.systemui.statusbar.BackDropView + android:id="@+id/backdrop" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" + sysui:ignoreRightInset="true" + > + <ImageView android:id="@+id/backdrop_back" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:scaleType="centerCrop"/> + <ImageView android:id="@+id/backdrop_front" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:scaleType="centerCrop" + android:visibility="invisible"/> + </com.android.systemui.statusbar.BackDropView> + + <com.android.systemui.statusbar.ScrimView + android:id="@+id/scrim_for_bubble" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:importantForAccessibility="no" + sysui:ignoreRightInset="true" + /> + + <com.android.systemui.statusbar.ScrimView + android:id="@+id/scrim_behind" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:importantForAccessibility="no" + sysui:ignoreRightInset="true" + /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="@dimen/status_bar_height" + android:orientation="vertical" + > + <FrameLayout + android:id="@+id/status_bar_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" + /> + + <FrameLayout + android:id="@+id/car_top_navigation_bar_container" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + </LinearLayout> + + <include layout="@layout/brightness_mirror"/> + + <ViewStub android:id="@+id/fullscreen_user_switcher_stub" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout="@layout/car_fullscreen_user_switcher"/> + + <include layout="@layout/notification_center_activity" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginBottom="@dimen/navigation_bar_height" + android:visibility="invisible"/> + + <include layout="@layout/headsup_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="invisible"/> + + <include layout="@layout/status_bar_expanded" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="invisible"/> + + <com.android.systemui.statusbar.ScrimView + android:id="@+id/scrim_in_front" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:importantForAccessibility="no" + sysui:ignoreRightInset="true" + /> + +</com.android.systemui.statusbar.phone.NotificationShadeWindowView> diff --git a/packages/CarSystemUI/res/layout/super_status_bar.xml b/packages/CarSystemUI/res/layout/super_status_bar.xml index 0b346260896a..c7b22f823ba4 100644 --- a/packages/CarSystemUI/res/layout/super_status_bar.xml +++ b/packages/CarSystemUI/res/layout/super_status_bar.xml @@ -1,21 +1,23 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ 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 - --> - -<!-- This is the combined status bar / notification panel window. --> +** +** 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. +*/ +--> + +<!-- This is the status bar window. --> <com.android.systemui.statusbar.phone.StatusBarWindowView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:sysui="http://schemas.android.com/apk/res-auto" @@ -23,87 +25,9 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> - <com.android.systemui.statusbar.BackDropView - android:id="@+id/backdrop" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone" - sysui:ignoreRightInset="true" - > - <ImageView android:id="@+id/backdrop_back" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:scaleType="centerCrop"/> - <ImageView android:id="@+id/backdrop_front" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:scaleType="centerCrop" - android:visibility="invisible"/> - </com.android.systemui.statusbar.BackDropView> - - <com.android.systemui.statusbar.ScrimView - android:id="@+id/scrim_for_bubble" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:importantForAccessibility="no" - sysui:ignoreRightInset="true" - /> - - <com.android.systemui.statusbar.ScrimView - android:id="@+id/scrim_behind" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:importantForAccessibility="no" - sysui:ignoreRightInset="true" - /> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="@dimen/status_bar_height" - android:orientation="vertical" - > - <FrameLayout - android:id="@+id/status_bar_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:visibility="gone" - /> - - <FrameLayout - android:id="@+id/car_top_navigation_bar_container" - android:layout_width="match_parent" - android:layout_height="wrap_content"/> - </LinearLayout> - - <include layout="@layout/brightness_mirror"/> - - <ViewStub android:id="@+id/fullscreen_user_switcher_stub" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout="@layout/car_fullscreen_user_switcher"/> - - <include layout="@layout/notification_center_activity" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginBottom="@dimen/navigation_bar_height" - android:visibility="invisible"/> - - <include layout="@layout/headsup_container" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="invisible"/> - - <include layout="@layout/status_bar_expanded" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="invisible"/> - - <com.android.systemui.statusbar.ScrimView - android:id="@+id/scrim_in_front" + <FrameLayout + android:id="@+id/status_bar_container" android:layout_width="match_parent" - android:layout_height="match_parent" - android:importantForAccessibility="no" - sysui:ignoreRightInset="true" - /> + android:layout_height="wrap_content" /> </com.android.systemui.statusbar.phone.StatusBarWindowView> diff --git a/packages/CarSystemUI/res/xml/overlayable.xml b/packages/CarSystemUI/res/xml/overlayable.xml new file mode 100644 index 000000000000..2b6e66e28b5f --- /dev/null +++ b/packages/CarSystemUI/res/xml/overlayable.xml @@ -0,0 +1,23 @@ +<?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. +--> + +<resources> + <overlayable name="SystemBarsLayouts"> + <policy type="product|signature"> + <item type="layout" name="car_navigation_bar" /> + </policy> + </overlayable> +</resources>
\ No newline at end of file diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java index d8c9d17e7179..78764dd19741 100644 --- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java @@ -235,7 +235,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks private void buildNavBarWindows() { mTopNavigationBarWindow = mSuperStatusBarViewFactory - .getStatusBarWindowView() + .getNotificationShadeWindowView() .findViewById(R.id.car_top_navigation_bar_container); mBottomNavigationBarWindow = mCarNavigationBarController.getBottomWindow(); mLeftNavigationBarWindow = mCarNavigationBarController.getLeftWindow(); diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarShadeControllerImpl.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarShadeControllerImpl.java index d1d352a08908..755ed25d64e2 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarShadeControllerImpl.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarShadeControllerImpl.java @@ -24,10 +24,10 @@ import com.android.systemui.assist.AssistManager; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeControllerImpl; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import javax.inject.Inject; import javax.inject.Singleton; @@ -41,13 +41,13 @@ public class CarShadeControllerImpl extends ShadeControllerImpl { @Inject public CarShadeControllerImpl(CommandQueue commandQueue, StatusBarStateController statusBarStateController, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, WindowManager windowManager, Lazy<StatusBar> statusBarLazy, Lazy<AssistManager> assistManagerLazy, Lazy<BubbleController> bubbleControllerLazy) { - super(commandQueue, statusBarStateController, statusBarWindowController, + super(commandQueue, statusBarStateController, notificationShadeWindowController, statusBarKeyguardViewManager, windowManager, statusBarLazy, assistManagerLazy, bubbleControllerLazy); } @@ -61,14 +61,14 @@ public class CarShadeControllerImpl extends ShadeControllerImpl { return; } - mStatusBarWindowController.setStatusBarFocusable(false); - getCarStatusBar().getStatusBarWindowViewController().cancelExpandHelper(); + mNotificationShadeWindowController.setNotificationShadeFocusable(false); + getCarStatusBar().getNotificationShadeWindowViewController().cancelExpandHelper(); getStatusBarView().collapsePanel(true /* animate */, delayed, speedUpFactor); getCarStatusBar().animateNotificationPanel(getCarStatusBar().getClosingVelocity(), true); if (!getCarStatusBar().isTracking()) { - mStatusBarWindowController.setPanelVisible(false); + mNotificationShadeWindowController.setPanelVisible(false); getCarNotificationView().setVisibility(View.INVISIBLE); } diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index 18485dc283f0..76e9ec64e2f2 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -126,13 +126,13 @@ import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper; import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -303,7 +303,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt Lazy<AssistManager> assistManagerLazy, NotificationListener notificationListener, ConfigurationController configurationController, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, LockscreenLockIconController lockscreenLockIconController, DozeParameters dozeParameters, ScrimController scrimController, @@ -391,7 +391,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt assistManagerLazy, notificationListener, configurationController, - statusBarWindowController, + notificationShadeWindowController, lockscreenLockIconController, dozeParameters, scrimController, @@ -545,7 +545,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt mNotificationPanelBackground = getDefaultWallpaper(); mScrimController.setScrimBehindDrawable(mNotificationPanelBackground); - FragmentHostManager manager = FragmentHostManager.get(mStatusBarWindow); + FragmentHostManager manager = FragmentHostManager.get(mPhoneStatusBarWindow); manager.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> { mBatteryMeterView = fragment.getView().findViewById(R.id.battery); @@ -646,9 +646,9 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt carNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper, carHeadsUpNotificationManager, mNotificationDataManager); - mNotificationView = mStatusBarWindow.findViewById(R.id.notification_view); - View glassPane = mStatusBarWindow.findViewById(R.id.glass_pane); - mHandleBar = mStatusBarWindow.findViewById(R.id.handle_bar); + final View glassPane = mNotificationShadeWindowView.findViewById(R.id.glass_pane); + mNotificationView = mNotificationShadeWindowView.findViewById(R.id.notification_view); + mHandleBar = mNotificationShadeWindowView.findViewById(R.id.handle_bar); mNotificationView.setClickHandlerFactory(mNotificationClickHandlerFactory); mNotificationView.setNotificationDataManager(mNotificationDataManager); @@ -779,7 +779,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt } // scroll to top mNotificationList.scrollToPosition(0); - mStatusBarWindowController.setPanelVisible(true); + mNotificationShadeWindowController.setPanelVisible(true); mNotificationView.setVisibility(View.VISIBLE); animateNotificationPanel(mOpeningVelocity, false); @@ -863,7 +863,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt mOpeningVelocity = DEFAULT_FLING_VELOCITY; mClosingVelocity = DEFAULT_FLING_VELOCITY; if (isClosing) { - mStatusBarWindowController.setPanelVisible(false); + mNotificationShadeWindowController.setPanelVisible(false); mNotificationView.setVisibility(View.INVISIBLE); mNotificationView.setClipBounds(null); mNotificationViewController.onVisibilityChanged(false); @@ -1128,7 +1128,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt // when the on-scroll is called for the first time to open. mNotificationList.scrollToPosition(0); } - mStatusBarWindowController.setPanelVisible(true); + mNotificationShadeWindowController.setPanelVisible(true); mNotificationView.setVisibility(View.VISIBLE); // clips the view for the notification shade when the user scrolls to open. @@ -1294,7 +1294,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt @Override protected View createHeadsUpPanel() { // In SystemUi the view is already in the window so just return a reference. - return mStatusBarWindow.findViewById(R.id.notification_headsup); + return mNotificationShadeWindowView.findViewById(R.id.notification_headsup); } @Override @@ -1320,7 +1320,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt super.setHeadsUpVisible(); if (mHeadsUpPanel.getVisibility() == View.VISIBLE) { - mStatusBarWindowController.setHeadsUpShowing(true); + mNotificationShadeWindowController.setHeadsUpShowing(true); mStatusBarWindowController.setForceStatusBarVisible(true); } } @@ -1330,7 +1330,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt super.removeNotificationFromPanel(currentHeadsUpNotification); // If the panel ended up empty and hidden we can remove it from SystemUi if (mHeadsUpPanel.getVisibility() != View.VISIBLE) { - mStatusBarWindowController.setHeadsUpShowing(false); + mNotificationShadeWindowController.setHeadsUpShowing(false); mStatusBarWindowController.setForceStatusBarVisible(false); } } diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java index 2a2eb6976653..59f9f94c4d05 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java @@ -28,8 +28,8 @@ import com.android.systemui.navigationbar.car.CarNavigationBarController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.NavigationModeController; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -53,14 +53,14 @@ public class CarStatusBarKeyguardViewManager extends StatusBarKeyguardViewManage KeyguardUpdateMonitor keyguardUpdateMonitor, NavigationModeController navigationModeController, DockManager dockManager, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, NotificationMediaManager notificationMediaManager, CarNavigationBarController carNavigationBarController, FullscreenUserSwitcher fullscreenUserSwitcher) { super(context, callback, lockPatternUtils, sysuiStatusBarStateController, configurationController, keyguardUpdateMonitor, navigationModeController, - dockManager, statusBarWindowController, keyguardStateController, + dockManager, notificationShadeWindowController, keyguardStateController, notificationMediaManager); mShouldHideNavBar = context.getResources() .getBoolean(R.bool.config_hideNavWhenKeyguardBouncerShown); diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java index 3abbe32df2da..45da8223943b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java @@ -85,12 +85,12 @@ import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper; import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -173,7 +173,7 @@ public class CarStatusBarModule { Lazy<AssistManager> assistManagerLazy, NotificationListener notificationListener, ConfigurationController configurationController, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, LockscreenLockIconController lockscreenLockIconController, DozeParameters dozeParameters, ScrimController scrimController, @@ -260,7 +260,7 @@ public class CarStatusBarModule { assistManagerLazy, notificationListener, configurationController, - statusBarWindowController, + notificationShadeWindowController, lockscreenLockIconController, dozeParameters, scrimController, diff --git a/packages/PackageInstaller/res/values-bs/strings.xml b/packages/PackageInstaller/res/values-bs/strings.xml index 421526b0f669..a099147072bc 100644 --- a/packages/PackageInstaller/res/values-bs/strings.xml +++ b/packages/PackageInstaller/res/values-bs/strings.xml @@ -62,7 +62,7 @@ <string name="uninstalling_notification_channel" msgid="840153394325714653">"Tekuća deinstaliranja"</string> <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Neuspjela deinstaliranja"</string> <string name="uninstalling" msgid="8709566347688966845">"Deinstaliranje..."</string> - <string name="uninstalling_app" msgid="8866082646836981397">"Deinstaliranje paketa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string> + <string name="uninstalling_app" msgid="8866082646836981397">"Deinstaliranje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string> <string name="uninstall_done" msgid="439354138387969269">"Deinstaliranje je završeno."</string> <string name="uninstall_done_app" msgid="4588850984473605768">"Deinstaliran je paket <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string> <string name="uninstall_failed" msgid="1847750968168364332">"Deinstaliranje nije uspjelo."</string> diff --git a/packages/PackageInstaller/res/values-ky/strings.xml b/packages/PackageInstaller/res/values-ky/strings.xml index 61ff87f09690..822c548bc139 100644 --- a/packages/PackageInstaller/res/values-ky/strings.xml +++ b/packages/PackageInstaller/res/values-ky/strings.xml @@ -24,8 +24,8 @@ <string name="installing_app" msgid="1165095864863849422">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> орнотулууда…"</string> <string name="install_done" msgid="5987363587661783896">"Колдонмо орнотулду."</string> <string name="install_confirm_question" msgid="8176284075816604590">"Бул колдонмону орнотоюн деп жатасызбы?"</string> - <string name="install_confirm_question_update" msgid="7942235418781274635">"Учурдагы колдонмону жаңыртканы жатасызбы? Буга чейин сакталган дайындарыңыз өчүрүлбөйт."</string> - <string name="install_confirm_question_update_system" msgid="4713001702777910263">"Учурдагы алдын ала орнотулган колдонмону жаңыртканы жатасызбы? Буга чейин сакталган дайындарыңыз өчүрүлбөйт."</string> + <string name="install_confirm_question_update" msgid="7942235418781274635">"Учурдагы колдонмону жаңыртканы жатасызбы? Буга чейин сакталган дайын-даректериңиз өчүрүлбөйт."</string> + <string name="install_confirm_question_update_system" msgid="4713001702777910263">"Учурдагы алдын ала орнотулган колдонмону жаңыртканы жатасызбы? Буга чейин сакталган дайын-даректериңиз өчүрүлбөйт."</string> <string name="install_failed" msgid="5777824004474125469">"Колдонмо орнотулган жок."</string> <string name="install_failed_blocked" msgid="8512284352994752094">"Топтомду орнотууга болбойт."</string> <string name="install_failed_conflict" msgid="3493184212162521426">"Башка топтом менен дал келбегендиктен колдонмо орнотулган жок."</string> @@ -83,9 +83,9 @@ <string name="untrusted_external_source_warning" product="tablet" msgid="6539403649459942547">"Коопсуздукту сактоо максатында, планшетиңизге бул булактан колдонмолорду орнотууга уруксат жок."</string> <string name="untrusted_external_source_warning" product="tv" msgid="1206648674551321364">"Коопсуздукту сактоо максатында, сыналгыңызга бул булактан колдонмолорду орнотууга уруксат жок."</string> <string name="untrusted_external_source_warning" product="default" msgid="7279739265754475165">"Коопсуздукту сактоо максатында, телефонуңузга бул булактан колдонмолорду орнотууга уруксат жок."</string> - <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Телефонуңуз жана жеке дайындарыңыз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам телефонуңузга кандайдыр бир зыян келтирилсе же дайындарыңызды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string> - <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Планшетиңиз жана жеке дайындарыңыз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам планшетиңизге кандайдыр бир зыян келтирилсе же дайындарыңызды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string> - <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Сыналгыңыз жана жеке дайындарыңыз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам сыналгыңызга кандайдыр бир зыян келтирилсе же дайындарыңызды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string> + <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Телефонуңуз жана жеке дайын-даректериңиз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам телефонуңузга кандайдыр бир зыян келтирилсе же дайын-даректериңизды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string> + <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Планшетиңиз жана жеке дайын-даректериңиз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам планшетиңизге кандайдыр бир зыян келтирилсе же дайын-даректериңизды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string> + <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Сыналгыңыз жана жеке дайын-даректериңиз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам сыналгыңызга кандайдыр бир зыян келтирилсе же дайын-даректериңизды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string> <string name="anonymous_source_continue" msgid="4375745439457209366">"Улантуу"</string> <string name="external_sources_settings" msgid="4046964413071713807">"Жөндөөлөр"</string> <string name="wear_app_channel" msgid="1960809674709107850">"Тагынма колдонмолорду орнотуу/чыгаруу"</string> diff --git a/packages/PackageInstaller/res/values-pl/strings.xml b/packages/PackageInstaller/res/values-pl/strings.xml index 7b50547eac69..5ce30c29638f 100644 --- a/packages/PackageInstaller/res/values-pl/strings.xml +++ b/packages/PackageInstaller/res/values-pl/strings.xml @@ -62,7 +62,7 @@ <string name="uninstalling_notification_channel" msgid="840153394325714653">"Aktywne odinstalowania"</string> <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Nieudane odinstalowania"</string> <string name="uninstalling" msgid="8709566347688966845">"Odinstalowuję…"</string> - <string name="uninstalling_app" msgid="8866082646836981397">"Odinstalowuję pakiet <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string> + <string name="uninstalling_app" msgid="8866082646836981397">"Odinstalowuję <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string> <string name="uninstall_done" msgid="439354138387969269">"Odinstalowywanie zakończone."</string> <string name="uninstall_done_app" msgid="4588850984473605768">"Odinstalowano pakiet <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string> <string name="uninstall_failed" msgid="1847750968168364332">"Nie udało się odinstalować."</string> diff --git a/packages/PackageInstaller/res/values-sl/strings.xml b/packages/PackageInstaller/res/values-sl/strings.xml index a0702d6d62cb..c123d69c4dd5 100644 --- a/packages/PackageInstaller/res/values-sl/strings.xml +++ b/packages/PackageInstaller/res/values-sl/strings.xml @@ -53,7 +53,7 @@ <string name="uninstall_application_title" msgid="4045420072401428123">"Odstrani aplikacijo"</string> <string name="uninstall_update_title" msgid="824411791011583031">"Odstrani posodobitev"</string> <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je del te aplikacije:"</string> - <string name="uninstall_application_text" msgid="3816830743706143980">"Ali želite odstraniti to aplikacijo?"</string> + <string name="uninstall_application_text" msgid="3816830743706143980">"Ali želite odmestiti to aplikacijo?"</string> <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Ali želite odstraniti aplikacijo za "<b>"vse"</b>" uporabnike? Aplikacija in njeni podatki bodo odstranjeni iz "<b>"vseh"</b>" uporabnikov v napravi."</string> <string name="uninstall_application_text_user" msgid="498072714173920526">"Ali želite to aplikacijo odstraniti za uporabnika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string> <string name="uninstall_update_text" msgid="863648314632448705">"Želite to aplikacijo nadomestiti s tovarniško različico? Odstranjeni bodo vsi podatki."</string> @@ -62,11 +62,11 @@ <string name="uninstalling_notification_channel" msgid="840153394325714653">"Odstranitve v teku"</string> <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Neuspele odstranitve"</string> <string name="uninstalling" msgid="8709566347688966845">"Odstranjevanje …"</string> - <string name="uninstalling_app" msgid="8866082646836981397">"Odstranjevanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string> + <string name="uninstalling_app" msgid="8866082646836981397">"Odmeščanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string> <string name="uninstall_done" msgid="439354138387969269">"Odstranitev je končana."</string> <string name="uninstall_done_app" msgid="4588850984473605768">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je bila odstranjena"</string> <string name="uninstall_failed" msgid="1847750968168364332">"Odstranitev ni uspela."</string> - <string name="uninstall_failed_app" msgid="5506028705017601412">"Odstranjevanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ni uspelo."</string> + <string name="uninstall_failed_app" msgid="5506028705017601412">"Odmeščanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ni uspelo."</string> <string name="uninstall_failed_device_policy_manager" msgid="785293813665540305">"Aktivne skrbniške aplikacije naprave ni mogoče odstraniti"</string> <string name="uninstall_failed_device_policy_manager_of_user" msgid="4813104025494168064">"Aktivne skrbniške aplikacije za uporabnika <xliff:g id="USERNAME">%1$s</xliff:g> ni mogoče odstraniti"</string> <string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"Aplikacija je obvezna za nekatere uporabnike/profile in je odstranjena za druge."</string> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 449a135fa1c7..f6e5062039d2 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1999,6 +1999,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.DOZE_TAP_SCREEN_GESTURE, SecureSettingsProto.Doze.PULSE_ON_TAP); + dumpSetting(s, p, + Settings.Secure.SUPPRESS_DOZE, + SecureSettingsProto.Doze.SUPPRESS); p.end(dozeToken); dumpSetting(s, p, diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index a337570829e4..b896a2a8d9a4 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -726,7 +726,8 @@ public class SettingsBackupTest { Settings.Secure.FACE_UNLOCK_RE_ENROLL, Settings.Secure.TAP_GESTURE, Settings.Secure.WINDOW_MAGNIFICATION, - Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER); + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER, + Settings.Secure.SUPPRESS_DOZE); @Test public void systemSettingsBackedUpOrBlacklisted() { diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml new file mode 100644 index 000000000000..dc070cbaae26 --- /dev/null +++ b/packages/SystemUI/res/layout/super_notification_shade.xml @@ -0,0 +1,104 @@ +<?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. +*/ +--> + +<!-- This is the notification shade window. --> +<com.android.systemui.statusbar.phone.NotificationShadeWindowView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:sysui="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:fitsSystemWindows="true"> + + <com.android.systemui.statusbar.BackDropView + android:id="@+id/backdrop" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" + sysui:ignoreRightInset="true" + > + <ImageView android:id="@+id/backdrop_back" + android:layout_width="match_parent" + android:scaleType="centerCrop" + android:layout_height="match_parent" /> + <ImageView android:id="@+id/backdrop_front" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:scaleType="centerCrop" + android:visibility="invisible" /> + </com.android.systemui.statusbar.BackDropView> + + <com.android.systemui.statusbar.ScrimView + android:id="@+id/scrim_for_bubble" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:importantForAccessibility="no" + sysui:ignoreRightInset="true" + /> + + <com.android.systemui.statusbar.ScrimView + android:id="@+id/scrim_behind" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:importantForAccessibility="no" + sysui:ignoreRightInset="true" + /> + + <include layout="@layout/status_bar_expanded" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="invisible" /> + + <include layout="@layout/brightness_mirror" /> + + <com.android.systemui.statusbar.ScrimView + android:id="@+id/scrim_in_front" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:importantForAccessibility="no" + sysui:ignoreRightInset="true" + /> + + <LinearLayout + android:id="@+id/lock_icon_container" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/status_bar_height" + android:layout_gravity="top|center_horizontal"> + <com.android.systemui.statusbar.phone.LockIcon + android:id="@+id/lock_icon" + android:layout_width="@dimen/keyguard_lock_width" + android:layout_height="@dimen/keyguard_lock_height" + android:layout_gravity="center_horizontal" + android:layout_marginTop="@dimen/keyguard_lock_padding" + android:contentDescription="@string/accessibility_unlock_button" + android:src="@*android:drawable/ic_lock" + android:scaleType="center" /> + <com.android.keyguard.KeyguardMessageArea + android:id="@+id/keyguard_message_area" + style="@style/Keyguard.TextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/keyguard_lock_padding" + android:gravity="center" + android:singleLine="true" + android:ellipsize="marquee" + android:focusable="true" /> + </LinearLayout> +</com.android.systemui.statusbar.phone.NotificationShadeWindowView> diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index 9716a00a7f72..8fee2cf9597e 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- ** -** Copyright 2012, The Android Open Source Project +** Copyright 2020, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ */ --> -<!-- This is the combined status bar / notification panel window. --> +<!-- This is the status bar window. --> <com.android.systemui.statusbar.phone.StatusBarWindowView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:sysui="http://schemas.android.com/apk/res-auto" @@ -25,85 +25,8 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> - <com.android.systemui.statusbar.BackDropView - android:id="@+id/backdrop" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone" - sysui:ignoreRightInset="true" - > - <ImageView android:id="@+id/backdrop_back" - android:layout_width="match_parent" - android:scaleType="centerCrop" - android:layout_height="match_parent" /> - <ImageView android:id="@+id/backdrop_front" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:scaleType="centerCrop" - android:visibility="invisible" /> - </com.android.systemui.statusbar.BackDropView> - - <com.android.systemui.statusbar.ScrimView - android:id="@+id/scrim_for_bubble" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:importantForAccessibility="no" - sysui:ignoreRightInset="true" - /> - <FrameLayout android:id="@+id/status_bar_container" android:layout_width="match_parent" android:layout_height="wrap_content" /> - - <com.android.systemui.statusbar.ScrimView - android:id="@+id/scrim_behind" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:importantForAccessibility="no" - sysui:ignoreRightInset="true" - /> - - <include layout="@layout/status_bar_expanded" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="invisible" /> - - <include layout="@layout/brightness_mirror" /> - - <com.android.systemui.statusbar.ScrimView - android:id="@+id/scrim_in_front" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:importantForAccessibility="no" - sysui:ignoreRightInset="true" - /> - - <LinearLayout - android:id="@+id/lock_icon_container" - android:orientation="vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/status_bar_height" - android:layout_gravity="top|center_horizontal"> - <com.android.systemui.statusbar.phone.LockIcon - android:id="@+id/lock_icon" - android:layout_width="@dimen/keyguard_lock_width" - android:layout_height="@dimen/keyguard_lock_height" - android:layout_gravity="center_horizontal" - android:layout_marginTop="@dimen/keyguard_lock_padding" - android:contentDescription="@string/accessibility_unlock_button" - android:src="@*android:drawable/ic_lock" - android:scaleType="center" /> - <com.android.keyguard.KeyguardMessageArea - android:id="@+id/keyguard_message_area" - style="@style/Keyguard.TextView" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/keyguard_lock_padding" - android:gravity="center" - android:singleLine="true" - android:ellipsize="marquee" - android:focusable="true" /> - </LinearLayout> </com.android.systemui.statusbar.phone.StatusBarWindowView> diff --git a/packages/SystemUI/scripts/update_shared_lib.sh b/packages/SystemUI/scripts/update_shared_lib.sh new file mode 100755 index 000000000000..05374934be2a --- /dev/null +++ b/packages/SystemUI/scripts/update_shared_lib.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +NUM_ARGS=$# + +has_croot() { + declare -F croot > /dev/null + return $? +} + +check_environment() { + if ! has_croot; then + echo "Run script in a shell that has had envsetup run. Run '. update_shared_lib.sh' from scripts directory" + return 1 + fi + + if [ $NUM_ARGS -ne 1 ]; then + echo "Usage: . update_shared_lib PATH_TO_UNBUNDLED_LAUNCER e.g. . update_shared_lib ~/src/ub-launcher3-master" + return 1 + fi + return 0 +} + +main() { + if check_environment ; then + pushd . + croot + mma -j16 SystemUISharedLib + JAR_DESTINATION="$1/prebuilts/framework_intermediates/quickstep/libs/sysui_shared.jar" + cp out/target/product/$TARGET_PRODUCT/obj/JAVA_LIBRARIES/SystemUISharedLib_intermediates/javalib.jar $JAR_DESTINATION + popd + fi +} + +main + diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/UniversalSmartspaceUtils.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/UniversalSmartspaceUtils.java new file mode 100644 index 000000000000..70a464dd254c --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/UniversalSmartspaceUtils.java @@ -0,0 +1,67 @@ +/* + * 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.shared.system; + +import android.content.Intent; +import android.os.Bundle; +import android.os.IBinder; +import android.view.SurfaceControl; +import android.view.SurfaceView; + +/** Utility class that is shared between SysUI and Launcher for Universal Smartspace features. */ +public final class UniversalSmartspaceUtils { + public static final String ACTION_REQUEST_SMARTSPACE_VIEW = + "com.android.systemui.REQUEST_SMARTSPACE_VIEW"; + + private static final String SYSUI_PACKAGE = "com.android.systemui"; + private static final String INTENT_KEY_INPUT_BUNDLE = "input_bundle"; + private static final String BUNDLE_KEY_INPUT_TOKEN = "input_token"; + private static final String INTENT_KEY_SURFACE_CONTROL = "surface_control"; + + /** Creates an intent to request that sysui draws the Smartspace to the SurfaceView. */ + public static Intent createRequestSmartspaceIntent(SurfaceView surfaceView) { + Intent intent = new Intent(ACTION_REQUEST_SMARTSPACE_VIEW); + + Bundle inputBundle = new Bundle(); + inputBundle.putBinder(BUNDLE_KEY_INPUT_TOKEN, surfaceView.getInputToken()); + return intent + .putExtra(INTENT_KEY_SURFACE_CONTROL, surfaceView.getSurfaceControl()) + .putExtra(INTENT_KEY_INPUT_BUNDLE, inputBundle) + .setPackage(SYSUI_PACKAGE) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY + | Intent.FLAG_RECEIVER_FOREGROUND); + } + + /** + * Retrieves the SurfaceControl from an Intent created by + * {@link #createRequestSmartspaceIntent(SurfaceView)}. + **/ + public static SurfaceControl getSurfaceControl(Intent intent) { + return intent.getParcelableExtra(INTENT_KEY_SURFACE_CONTROL); + } + + /** + * Retrieves the input token from an Intent created by + * {@link #createRequestSmartspaceIntent(SurfaceView)}. + **/ + public static IBinder getInputToken(Intent intent) { + Bundle inputBundle = intent.getBundleExtra(INTENT_KEY_INPUT_BUNDLE); + return inputBundle == null ? null : inputBundle.getBinder(BUNDLE_KEY_INPUT_TOKEN); + } + + private UniversalSmartspaceUtils() {} +} diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index d1495913d95f..aacc2c4f614b 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -89,6 +89,7 @@ import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.phone.NavigationModeController; import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper; import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -238,7 +239,8 @@ public class Dependency { @Inject Lazy<LeakReporter> mLeakReporter; @Inject Lazy<GarbageMonitor> mGarbageMonitor; @Inject Lazy<TunerService> mTunerService; - @Inject Lazy<StatusBarWindowController> mStatusBarWindowController; + @Inject Lazy<NotificationShadeWindowController> mNotificationShadeWindowController; + @Inject Lazy<StatusBarWindowController> mTempStatusBarWindowController; @Inject Lazy<DarkIconDispatcher> mDarkIconDispatcher; @Inject Lazy<ConfigurationController> mConfigurationController; @Inject Lazy<StatusBarIconController> mStatusBarIconController; @@ -400,7 +402,10 @@ public class Dependency { mProviders.put(TunerService.class, mTunerService::get); - mProviders.put(StatusBarWindowController.class, mStatusBarWindowController::get); + mProviders.put(NotificationShadeWindowController.class, + mNotificationShadeWindowController::get); + + mProviders.put(StatusBarWindowController.class, mTempStatusBarWindowController::get); mProviders.put(DarkIconDispatcher.class, mDarkIconDispatcher::get); diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index c533755c76da..db8b5831faf1 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -455,17 +455,25 @@ public class ScreenDecorations extends SystemUI implements Tunable { private void setupStatusBarPadding(int padding) { // Add some padding to all the content near the edge of the screen. StatusBar statusBar = mStatusBarLazy.get(); - View statusBarWindow = statusBar.getStatusBarWindow(); - if (statusBarWindow != null) { - TunablePadding.addTunablePadding(statusBarWindow.findViewById(R.id.keyguard_header), + final View notificationShadeWindowView = statusBar.getNotificationShadeWindowView(); + if (notificationShadeWindowView != null) { + TunablePadding.addTunablePadding( + notificationShadeWindowView.findViewById(R.id.keyguard_header), PADDING, padding, FLAG_END); - FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBarWindow); - fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG, - new TunablePaddingTagListener(padding, R.id.status_bar)); + final FragmentHostManager fragmentHostManager = + FragmentHostManager.get(notificationShadeWindowView); fragmentHostManager.addTagListener(QS.TAG, new TunablePaddingTagListener(padding, R.id.header)); } + + final View statusBarWindow = statusBar.getStatusBarWindow(); + if (statusBarWindow != null) { + final FragmentHostManager fragmentHostManager = + FragmentHostManager.get(statusBarWindow); + fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG, + new TunablePaddingTagListener(padding, R.id.status_bar)); + } } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index 84a592d68627..7b4816f5262c 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -28,6 +28,7 @@ import android.hardware.biometrics.BiometricPrompt; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.os.UserManager; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -162,6 +163,7 @@ public abstract class AuthBiometricView extends LinearLayout { private Bundle mBiometricPromptBundle; private boolean mRequireConfirmation; private int mUserId; + private int mEffectiveUserId; @AuthDialog.DialogSize int mSize = AuthDialog.SIZE_UNKNOWN; private TextView mTitleView; @@ -280,6 +282,10 @@ public abstract class AuthBiometricView extends LinearLayout { mUserId = userId; } + public void setEffectiveUserId(int effectiveUserId) { + mEffectiveUserId = effectiveUserId; + } + public void setRequireConfirmation(boolean requireConfirmation) { mRequireConfirmation = requireConfirmation; } @@ -650,8 +656,9 @@ public abstract class AuthBiometricView extends LinearLayout { if (isDeviceCredentialAllowed()) { final @Utils.CredentialType int credentialType = - Utils.getCredentialType(mContext, mUserId); - switch(credentialType) { + Utils.getCredentialType(mContext, mEffectiveUserId); + + switch (credentialType) { case Utils.CREDENTIAL_PIN: negativeText = getResources().getString(R.string.biometric_dialog_use_pin); break; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index 36c89fdb2441..4312a5201b08 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -30,6 +30,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.os.UserManager; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -75,6 +76,7 @@ public class AuthContainerView extends LinearLayout @interface ContainerState {} final Config mConfig; + final int mEffectiveUserId; private final Handler mHandler; private final Injector mInjector; private final IBinder mWindowToken = new Binder(); @@ -182,6 +184,14 @@ public class AuthContainerView extends LinearLayout int getAnimateCredentialStartDelayMs() { return AuthDialog.ANIMATE_CREDENTIAL_START_DELAY_MS; } + + UserManager getUserManager(Context context) { + return UserManager.get(context); + } + + int getCredentialType(Context context, int effectiveUserId) { + return Utils.getCredentialType(context, effectiveUserId); + } } @VisibleForTesting @@ -230,6 +240,9 @@ public class AuthContainerView extends LinearLayout mConfig = config; mInjector = injector; + mEffectiveUserId = mInjector.getUserManager(mContext) + .getCredentialOwnerProfile(mConfig.mUserId); + mHandler = new Handler(Looper.getMainLooper()); mWindowManager = mContext.getSystemService(WindowManager.class); mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class); @@ -268,7 +281,6 @@ public class AuthContainerView extends LinearLayout mBiometricScrollView = mInjector.getBiometricScrollView(mFrameLayout); mBackgroundView = mInjector.getBackgroundView(mFrameLayout); - if (isManagedProfile) { final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background, mContext.getTheme()); @@ -307,6 +319,7 @@ public class AuthContainerView extends LinearLayout mBiometricView.setCallback(mBiometricCallback); mBiometricView.setBackgroundView(mBackgroundView); mBiometricView.setUserId(mConfig.mUserId); + mBiometricView.setEffectiveUserId(mEffectiveUserId); mBiometricScrollView.addView(mBiometricView); } @@ -318,7 +331,10 @@ public class AuthContainerView extends LinearLayout */ private void addCredentialView(boolean animatePanel, boolean animateContents) { final LayoutInflater factory = LayoutInflater.from(mContext); - final int credentialType = Utils.getCredentialType(mContext, mConfig.mUserId); + + final @Utils.CredentialType int credentialType = mInjector.getCredentialType( + mContext, mEffectiveUserId); + switch (credentialType) { case Utils.CREDENTIAL_PATTERN: mCredentialView = (AuthCredentialView) factory.inflate( @@ -334,7 +350,8 @@ public class AuthContainerView extends LinearLayout } mCredentialView.setContainerView(this); - mCredentialView.setUser(mConfig.mUserId); + mCredentialView.setEffectiveUserId(mEffectiveUserId); + mCredentialView.setCredentialType(credentialType); mCredentialView.setCallback(mCredentialCallback); mCredentialView.setBiometricPromptBundle(mConfig.mBiometricPromptBundle); mCredentialView.setPanelController(mPanelController, animatePanel); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index e0ca1ace2ac4..875619a71a18 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -338,7 +338,13 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, @Override public void hideAuthenticationDialog() { - if (DEBUG) Log.d(TAG, "hideAuthenticationDialog"); + if (DEBUG) Log.d(TAG, "hideAuthenticationDialog: " + mCurrentDialog); + + if (mCurrentDialog == null) { + // Could be possible if the caller canceled authentication after credential success + // but before the client was notified. + return; + } mCurrentDialog.dismissFromSystemServer(); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java index bebaa4b688db..ccfd3a57811c 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java @@ -96,7 +96,7 @@ public class AuthCredentialPasswordView extends AuthCredentialView } private void checkPasswordAndUnlock() { - try (LockscreenCredential password = mCredentialType == Utils.CREDENTIAL_PIN + try (LockscreenCredential password = mCredentialType == Utils.CREDENTIAL_PIN ? LockscreenCredential.createPinOrNone(mPasswordField.getText()) : LockscreenCredential.createPasswordOrNone(mPasswordField.getText())) { if (password.isNone()) { @@ -104,7 +104,7 @@ public class AuthCredentialPasswordView extends AuthCredentialView } mPendingLockCheck = LockPatternChecker.checkCredential(mLockPatternUtils, - password, mUserId, this::onCredentialChecked); + password, mEffectiveUserId, this::onCredentialChecked); } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java index 14414a4225de..1cb532bf0e40 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java @@ -69,7 +69,7 @@ public class AuthCredentialPatternView extends AuthCredentialView { mPendingLockCheck = LockPatternChecker.checkCredential( mLockPatternUtils, credential, - mUserId, + mEffectiveUserId, this::onPatternChecked); } } @@ -99,7 +99,8 @@ public class AuthCredentialPatternView extends AuthCredentialView { super.onFinishInflate(); mLockPatternView = findViewById(R.id.lockPattern); mLockPatternView.setOnPatternListener(new UnlockPatternListener()); - mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(mUserId)); + mLockPatternView.setInStealthMode( + !mLockPatternUtils.isVisiblePatternEnabled(mEffectiveUserId)); mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled()); } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java index 8c8611e49dfb..8f2cf70a8184 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java @@ -63,7 +63,7 @@ public abstract class AuthCredentialView extends LinearLayout { protected AuthContainerView mContainerView; protected Callback mCallback; protected AsyncTask<?, ?, ?> mPendingLockCheck; - protected int mUserId; + protected int mEffectiveUserId; protected ErrorTimer mErrorTimer; interface Callback { @@ -137,8 +137,12 @@ public abstract class AuthCredentialView extends LinearLayout { view.setText(string); } - void setUser(int user) { - mUserId = user; + void setEffectiveUserId(int effectiveUserId) { + mEffectiveUserId = effectiveUserId; + } + + void setCredentialType(@Utils.CredentialType int credentialType) { + mCredentialType = credentialType; } void setCallback(Callback callback) { @@ -166,8 +170,6 @@ public abstract class AuthCredentialView extends LinearLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); - mCredentialType = Utils.getCredentialType(mContext, mUserId); - setText(mTitleView, mBiometricPromptBundle.getString(BiometricPrompt.KEY_TITLE)); setTextOrHide(mSubtitleView, mBiometricPromptBundle.getString(BiometricPrompt.KEY_SUBTITLE)); @@ -230,7 +232,8 @@ public abstract class AuthCredentialView extends LinearLayout { } else { if (timeoutMs > 0) { mHandler.removeCallbacks(mClearErrorRunnable); - long deadline = mLockPatternUtils.setLockoutAttemptDeadline(mUserId, timeoutMs); + long deadline = mLockPatternUtils.setLockoutAttemptDeadline( + mEffectiveUserId, timeoutMs); mErrorTimer = new ErrorTimer(mContext, deadline - SystemClock.elapsedRealtime(), LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS, diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index d835ee1865bf..644d8c48c63c 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -89,9 +89,9 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.RemoteInputUriController; import com.android.systemui.statusbar.policy.ZenModeController; @@ -166,7 +166,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private final HashSet<String> mUserBlockedBubbles; // Bubbles get added to the status bar view - private final StatusBarWindowController mStatusBarWindowController; + private final NotificationShadeWindowController mNotificationShadeWindowController; private final ZenModeController mZenModeController; private StatusBarStateListener mStatusBarStateListener; private final ScreenshotHelper mScreenshotHelper; @@ -245,7 +245,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Inject public BubbleController(Context context, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, StatusBarStateController statusBarStateController, ShadeController shadeController, BubbleData data, @@ -256,14 +256,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi NotificationGroupManager groupManager, NotificationEntryManager entryManager, RemoteInputUriController remoteInputUriController) { - this(context, statusBarWindowController, statusBarStateController, shadeController, + this(context, notificationShadeWindowController, statusBarStateController, shadeController, data, null /* synchronizer */, configurationController, interruptionStateProvider, zenModeController, notifUserManager, groupManager, entryManager, remoteInputUriController); } public BubbleController(Context context, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, StatusBarStateController statusBarStateController, ShadeController shadeController, BubbleData data, @@ -324,7 +324,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } }); - mStatusBarWindowController = statusBarWindowController; + mNotificationShadeWindowController = notificationShadeWindowController; mStatusBarStateListener = new StatusBarStateListener(); statusBarStateController.addCallback(mStatusBarStateListener); @@ -377,10 +377,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private void ensureStackViewCreated() { if (mStackView == null) { mStackView = new BubbleStackView(mContext, mBubbleData, mSurfaceSynchronizer); - ViewGroup sbv = mStatusBarWindowController.getStatusBarView(); - int bubbleScrimIndex = sbv.indexOfChild(sbv.findViewById(R.id.scrim_for_bubble)); + ViewGroup nsv = mNotificationShadeWindowController.getNotificationShadeView(); + int bubbleScrimIndex = nsv.indexOfChild(nsv.findViewById(R.id.scrim_for_bubble)); int stackIndex = bubbleScrimIndex + 1; // Show stack above bubble scrim. - sbv.addView(mStackView, stackIndex, + nsv.addView(mStackView, stackIndex, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); if (mExpandListener != null) { mStackView.setExpandListener(mExpandListener); @@ -473,7 +473,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (listener != null) { listener.onBubbleExpandChanged(isExpanding, key); } - mStatusBarWindowController.setBubbleExpanded(isExpanding); + mNotificationShadeWindowController.setBubbleExpanded(isExpanding); }); if (mStackView != null) { mStackView.setExpandListener(mExpandListener); @@ -944,9 +944,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } // Let listeners know if bubble state changed. - boolean hadBubbles = mStatusBarWindowController.getBubblesShowing(); + boolean hadBubbles = mNotificationShadeWindowController.getBubblesShowing(); boolean hasBubblesShowing = hasBubbles() && mStackView.getVisibility() == VISIBLE; - mStatusBarWindowController.setBubblesShowing(hasBubblesShowing); + mNotificationShadeWindowController.setBubblesShowing(hasBubblesShowing); if (mStateChangeListener != null && hadBubbles != hasBubblesShowing) { mStateChangeListener.onHasBubblesChanged(hasBubblesShowing); } @@ -983,7 +983,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi && context.getDisplay().getDisplayId() == DEFAULT_DISPLAY; final Bubble expandedBubble = mStackView.getExpandedBubble(); if (defaultDisplay && expandedBubble != null && isStackExpanded() - && !mStatusBarWindowController.getPanelExpanded()) { + && !mNotificationShadeWindowController.getPanelExpanded()) { return expandedBubble; } return null; diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index c138462d06c4..36a4a10b8a3f 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -97,8 +97,8 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.GlobalActions.GlobalActionsManager; import com.android.systemui.plugins.GlobalActionsPanelPlugin; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ScrimController; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.EmergencyDialerConstants; @@ -1528,7 +1528,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, private float mScrimAlpha; private ResetOrientationData mResetOrientationData; private boolean mHadTopUi; - private final StatusBarWindowController mStatusBarWindowController; + private final NotificationShadeWindowController mNotificationShadeWindowController; private boolean mControlsEnabled; ActionsDialog(Context context, MyAdapter adapter, @@ -1539,7 +1539,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mAdapter = adapter; mColorExtractor = Dependency.get(SysuiColorExtractor.class); mStatusBarService = Dependency.get(IStatusBarService.class); - mStatusBarWindowController = Dependency.get(StatusBarWindowController.class); + mNotificationShadeWindowController = + Dependency.get(NotificationShadeWindowController.class); mControlsEnabled = controlsEnabled; // Window initialization @@ -1721,8 +1722,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, public void show() { super.show(); mShowing = true; - mHadTopUi = mStatusBarWindowController.getForceHasTopUi(); - mStatusBarWindowController.setForceHasTopUi(true); + mHadTopUi = mNotificationShadeWindowController.getForceHasTopUi(); + mNotificationShadeWindowController.setForceHasTopUi(true); mBackgroundDrawable.setAlpha(0); mGlobalActionsLayout.setTranslationX(mGlobalActionsLayout.getAnimationOffsetX()); mGlobalActionsLayout.setTranslationY(mGlobalActionsLayout.getAnimationOffsetY()); @@ -1775,7 +1776,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, } private void completeDismiss() { - mStatusBarWindowController.setForceHasTopUi(mHadTopUi); + mNotificationShadeWindowController.setForceHasTopUi(mHadTopUi); super.dismiss(); } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index e13c3e087893..2fc7a9cf2434 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -88,9 +88,9 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.util.InjectionInflationController; import java.io.FileDescriptor; @@ -212,7 +212,7 @@ public class KeyguardViewMediator extends SystemUI { private AlarmManager mAlarmManager; private AudioManager mAudioManager; private StatusBarManager mStatusBarManager; - private final StatusBarWindowController mStatusBarWindowController; + private final NotificationShadeWindowController mNotificationShadeWindowController; private final Executor mUiBgExecutor; private boolean mSystemReady; @@ -691,7 +691,7 @@ public class KeyguardViewMediator extends SystemUI { FalsingManager falsingManager, LockPatternUtils lockPatternUtils, BroadcastDispatcher broadcastDispatcher, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManagerLazy, DismissCallbackRegistry dismissCallbackRegistry, @UiBackground Executor uiBgExecutor) { @@ -699,7 +699,7 @@ public class KeyguardViewMediator extends SystemUI { mFalsingManager = falsingManager; mLockPatternUtils = lockPatternUtils; mBroadcastDispatcher = broadcastDispatcher; - mStatusBarWindowController = statusBarWindowController; + mNotificationShadeWindowController = notificationShadeWindowController; mStatusBarKeyguardViewManagerLazy = statusBarKeyguardViewManagerLazy; mDismissCallbackRegistry = dismissCallbackRegistry; mUiBgExecutor = uiBgExecutor; @@ -1819,7 +1819,7 @@ public class KeyguardViewMediator extends SystemUI { adjustStatusBarLocked(); userActivity(); mUpdateMonitor.setKeyguardGoingAway(false); - mStatusBarWindowController.setKeyguardGoingAway(false); + mNotificationShadeWindowController.setKeyguardGoingAway(false); mShowKeyguardWakeLock.release(); } mKeyguardDisplayManager.show(); @@ -1852,7 +1852,7 @@ public class KeyguardViewMediator extends SystemUI { } mUpdateMonitor.setKeyguardGoingAway(true); - mStatusBarWindowController.setKeyguardGoingAway(true); + mNotificationShadeWindowController.setKeyguardGoingAway(true); // Don't actually hide the Keyguard at the moment, wait for window // manager until it tells us it's safe to do so with diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index ae48db2f4200..569f660d1797 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -68,9 +68,9 @@ import com.android.systemui.statusbar.NavigationBarController; import com.android.systemui.statusbar.phone.NavigationBarFragment; import com.android.systemui.statusbar.phone.NavigationBarView; import com.android.systemui.statusbar.phone.NavigationModeController; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.CallbackController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; @@ -109,7 +109,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis private SysUiState mSysUiState; private final Handler mHandler; private final NavigationBarController mNavBarController; - private final StatusBarWindowController mStatusBarWinController; + private final NotificationShadeWindowController mStatusBarWinController; private final Runnable mConnectionRunnable = this::internalConnectToCurrentUser; private final ComponentName mRecentsComponentName; private final DeviceProvisionedController mDeviceProvisionedController; @@ -476,8 +476,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis @Inject public OverviewProxyService(Context context, DeviceProvisionedController provisionController, NavigationBarController navBarController, NavigationModeController navModeController, - StatusBarWindowController statusBarWinController, SysUiState sysUiState, PipUI pipUI, - Optional<Divider> dividerOptional, Optional<Lazy<StatusBar>> statusBarOptionalLazy) { + NotificationShadeWindowController statusBarWinController, SysUiState sysUiState, + PipUI pipUI, Optional<Divider> dividerOptional, + Optional<Lazy<StatusBar>> statusBarOptionalLazy) { mContext = context; mPipUI = pipUI; mStatusBarOptionalLazy = statusBarOptionalLazy; diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 325af2424b2f..9fe6e844e0d2 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -332,6 +332,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, insets = state.calculateInsets(state.getDisplayFrame(), insets.isRound(), insets.shouldAlwaysConsumeSystemBars(), insets.getDisplayCutout(), null /* legacyContentInsets */, null /* legacyStableInsets */, + 0 /* legacySystemUiFlags */, SOFT_INPUT_ADJUST_NOTHING, null /* typeSideMap */); } if (mStableInsets.left != insets.getStableInsetLeft() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index 246b0f0e19ff..a4572665ebf1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -59,10 +59,10 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ScrimState; import com.android.systemui.statusbar.phone.StatusBar; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.KeyguardStateController; import java.io.FileDescriptor; @@ -105,7 +105,7 @@ public class NotificationMediaManager implements Dumpable { private final NotificationEntryManager mEntryManager; @Nullable - private Lazy<StatusBarWindowController> mStatusBarWindowController; + private Lazy<NotificationShadeWindowController> mStatusBarWindowController; @Nullable private BiometricUnlockController mBiometricUnlockController; @@ -180,7 +180,7 @@ public class NotificationMediaManager implements Dumpable { public NotificationMediaManager( Context context, Lazy<StatusBar> statusBarLazy, - Lazy<StatusBarWindowController> statusBarWindowController, + Lazy<NotificationShadeWindowController> statusBarWindowController, NotificationEntryManager notificationEntryManager, MediaArtworkProcessor mediaArtworkProcessor, KeyguardBypassController keyguardBypassController) { @@ -525,7 +525,7 @@ public class NotificationMediaManager implements Dumpable { } } - StatusBarWindowController windowController = mStatusBarWindowController.get(); + NotificationShadeWindowController windowController = mStatusBarWindowController.get(); boolean hideBecauseOccluded = mStatusBarLazy.get().isOccluded(); final boolean hasArtwork = artworkDrawable != null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java index 9398e6f689f6..0ab5afaab696 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java @@ -23,6 +23,7 @@ import android.view.ViewGroup; import com.android.systemui.R; import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.NotificationPanelView; +import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.StatusBarWindowView; import com.android.systemui.util.InjectionInflationController; @@ -30,8 +31,8 @@ import javax.inject.Inject; import javax.inject.Singleton; /** - * Creates a single instance of super_status_bar that can be shared across various system ui - * objects. + * Creates a single instance of super_status_bar and super_notification_shade that can be shared + * across various system ui objects. */ @Singleton public class SuperStatusBarViewFactory { @@ -39,6 +40,7 @@ public class SuperStatusBarViewFactory { private final Context mContext; private final InjectionInflationController mInjectionInflationController; + private NotificationShadeWindowView mNotificationShadeWindowView; private StatusBarWindowView mStatusBarWindowView; private NotificationShelf mNotificationShelf; @@ -50,15 +52,42 @@ public class SuperStatusBarViewFactory { } /** - * Gets the inflated {@link StatusBarWindowView} from {@link R.layout#super_status_bar}. Returns - * a cached instance, if it has already been inflated. + * Gets the inflated {@link NotificationShadeWindowView} from + * {@link R.layout#super_notification_shade}. + * Returns a cached instance, if it has already been inflated. + */ + public NotificationShadeWindowView getNotificationShadeWindowView() { + if (mNotificationShadeWindowView != null) { + return mNotificationShadeWindowView; + } + + mNotificationShadeWindowView = (NotificationShadeWindowView) + mInjectionInflationController.injectable( + LayoutInflater.from(mContext)).inflate(R.layout.super_notification_shade, + /* root= */ null); + if (mNotificationShadeWindowView == null) { + throw new IllegalStateException( + "R.layout.super_notification_shade could not be properly inflated"); + } + return mNotificationShadeWindowView; + } + + /** Gets the {@link LockIcon} inside of {@link R.layout#super_status_bar}. */ + public LockIcon getLockIcon() { + return getNotificationShadeWindowView().findViewById(R.id.lock_icon); + } + + /** + * Gets the inflated {@link StatusBarWindowView} from {@link R.layout#super_status_bar}. + * Returns a cached instance, if it has already been inflated. */ public StatusBarWindowView getStatusBarWindowView() { if (mStatusBarWindowView != null) { return mStatusBarWindowView; } - mStatusBarWindowView = (StatusBarWindowView) mInjectionInflationController.injectable( + mStatusBarWindowView = + (StatusBarWindowView) mInjectionInflationController.injectable( LayoutInflater.from(mContext)).inflate(R.layout.super_status_bar, /* root= */ null); if (mStatusBarWindowView == null) { @@ -68,11 +97,6 @@ public class SuperStatusBarViewFactory { return mStatusBarWindowView; } - /** Gets the {@link LockIcon} inside of {@link R.layout#super_status_bar}. */ - public LockIcon getLockIcon() { - return getStatusBarWindowView().findViewById(R.id.lock_icon); - } - /** * Gets the inflated {@link NotificationShelf} from * {@link R.layout#status_bar_notification_shelf}. @@ -98,11 +122,11 @@ public class SuperStatusBarViewFactory { } public NotificationPanelView getNotificationPanelView() { - StatusBarWindowView statusBarWindowView = getStatusBarWindowView(); - if (statusBarWindowView == null) { + NotificationShadeWindowView notificationShadeWindowView = getNotificationShadeWindowView(); + if (notificationShadeWindowView == null) { return null; } - return mStatusBarWindowView.findViewById(R.id.notification_panel); + return mNotificationShadeWindowView.findViewById(R.id.notification_panel); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java index 66605690b106..5fc043ada22d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java @@ -38,7 +38,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; import com.android.systemui.statusbar.phone.NotificationPanelViewController; -import com.android.systemui.statusbar.phone.StatusBarWindowViewController; +import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController; /** * A class that allows activities to be launched in a seamless way where the notification @@ -56,7 +56,7 @@ public class ActivityLaunchAnimator { private final NotificationPanelViewController mNotificationPanel; private final NotificationListContainer mNotificationContainer; private final float mWindowCornerRadius; - private final StatusBarWindowViewController mStatusBarWindowViewController; + private final NotificationShadeWindowViewController mNotificationShadeWindowViewController; private Callback mCallback; private final Runnable mTimeoutRunnable = () -> { setAnimationPending(false); @@ -67,21 +67,23 @@ public class ActivityLaunchAnimator { private boolean mIsLaunchForActivity; public ActivityLaunchAnimator( - StatusBarWindowViewController statusBarWindowViewController, + NotificationShadeWindowViewController notificationShadeWindowViewController, Callback callback, NotificationPanelViewController notificationPanel, NotificationListContainer container) { mNotificationPanel = notificationPanel; mNotificationContainer = container; - mStatusBarWindowViewController = statusBarWindowViewController; + mNotificationShadeWindowViewController = notificationShadeWindowViewController; mCallback = callback; mWindowCornerRadius = ScreenDecorationsUtils - .getWindowCornerRadius(mStatusBarWindowViewController.getView().getResources()); + .getWindowCornerRadius(mNotificationShadeWindowViewController.getView() + .getResources()); } public RemoteAnimationAdapter getLaunchAnimation( View sourceView, boolean occluded) { - if (!(sourceView instanceof ExpandableNotificationRow) || !mCallback.areLaunchAnimationsEnabled() || occluded) { + if (!(sourceView instanceof ExpandableNotificationRow) + || !mCallback.areLaunchAnimationsEnabled() || occluded) { return null; } AnimationRunner animationRunner = new AnimationRunner( @@ -113,11 +115,12 @@ public class ActivityLaunchAnimator { private void setAnimationPending(boolean pending) { mAnimationPending = pending; - mStatusBarWindowViewController.setExpandAnimationPending(pending); + mNotificationShadeWindowViewController.setExpandAnimationPending(pending); if (pending) { - mStatusBarWindowViewController.getView().postDelayed(mTimeoutRunnable, LAUNCH_TIMEOUT); + mNotificationShadeWindowViewController.getView().postDelayed(mTimeoutRunnable, + LAUNCH_TIMEOUT); } else { - mStatusBarWindowViewController.getView().removeCallbacks(mTimeoutRunnable); + mNotificationShadeWindowViewController.getView().removeCallbacks(mTimeoutRunnable); } } @@ -247,7 +250,7 @@ public class ActivityLaunchAnimator { private void setExpandAnimationRunning(boolean running) { mNotificationPanel.setLaunchingNotification(running); mSourceNotification.setExpandAnimationRunning(running); - mStatusBarWindowViewController.setExpandAnimationRunning(running); + mNotificationShadeWindowViewController.setExpandAnimationRunning(running); mNotificationContainer.setExpandingNotification(running ? mSourceNotification : null); mAnimationRunning = running; if (!running) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java index 76fdfc6fbabc..874d81db0bd2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java @@ -47,7 +47,7 @@ import com.android.systemui.qs.QuickQSPanel; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.TransformableView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; -import com.android.systemui.statusbar.phone.StatusBarWindowController; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.util.Utils; import java.util.Timer; @@ -181,8 +181,9 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi final int[] compactActions = mRow.getEntry().getSbn().getNotification().extras .getIntArray(Notification.EXTRA_COMPACT_ACTIONS); int tintColor = getNotificationHeader().getOriginalIconColor(); - StatusBarWindowController ctrl = Dependency.get(StatusBarWindowController.class); - QuickQSPanel panel = ctrl.getStatusBarView().findViewById( + NotificationShadeWindowController ctrl = Dependency.get( + NotificationShadeWindowController.class); + QuickQSPanel panel = ctrl.getNotificationShadeView().findViewById( com.android.systemui.R.id.quick_qs_panel); StatusBarNotification sbn = mRow.getEntry().getSbn(); Notification notif = sbn.getNotification(); @@ -193,7 +194,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi mActions, compactActions, notif.contentIntent); - QSPanel bigPanel = ctrl.getStatusBarView().findViewById( + QSPanel bigPanel = ctrl.getNotificationShadeView().findViewById( com.android.systemui.R.id.quick_settings_panel); bigPanel.addMediaSession(token, notif.getSmallIcon(), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 48805204160f..691e1c422bfe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -141,7 +141,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private final KeyguardUpdateMonitor mUpdateMonitor; private final DozeParameters mDozeParameters; private final KeyguardStateController mKeyguardStateController; - private final StatusBarWindowController mStatusBarWindowController; + private final NotificationShadeWindowController mNotificationShadeWindowController; private final Context mContext; private final int mWakeUpDelay; private int mMode; @@ -162,7 +162,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp public BiometricUnlockController(Context context, DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, ScrimController scrimController, StatusBar statusBar, ShadeController shadeController, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, @Main Resources resources, @@ -177,7 +177,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mMediaManager = Dependency.get(NotificationMediaManager.class); Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver); Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver); - mStatusBarWindowController = statusBarWindowController; + + mNotificationShadeWindowController = notificationShadeWindowController; mDozeScrimController = dozeScrimController; mKeyguardViewMediator = keyguardViewMediator; mScrimController = scrimController; @@ -284,7 +285,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp // notifications would light up first, creating an unpleasant animation. // Defer changing the screen brightness by forcing doze brightness on our window // until the clock and the notifications are faded out. - mStatusBarWindowController.setForceDozeBrightness(true); + mNotificationShadeWindowController.setForceDozeBrightness(true); } // During wake and unlock, we need to draw black before waking up to avoid abrupt // brightness changes due to display state transitions. @@ -340,7 +341,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM"); mUpdateMonitor.awakenFromDream(); } - mStatusBarWindowController.setStatusBarFocusable(false); + mNotificationShadeWindowController.setNotificationShadeFocusable(false); if (delayWakeUp) { mHandler.postDelayed(wakeUp, mWakeUpDelay); } else { @@ -508,7 +509,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mHandler.postDelayed(new Runnable() { @Override public void run() { - mStatusBarWindowController.setForceDozeBrightness(false); + mNotificationShadeWindowController.setForceDozeBrightness(false); } }, StatusBar.FADE_KEYGUARD_DURATION_PULSING); } @@ -522,7 +523,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private void resetMode() { mMode = MODE_NONE; - mStatusBarWindowController.setForceDozeBrightness(false); + mNotificationShadeWindowController.setForceDozeBrightness(false); if (mStatusBar.getNavigationBarView() != null) { mStatusBar.getNavigationBarView().setWakeAndUnlocking(false); } 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 accd2a4fcc0d..04efc2d7558d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -85,9 +85,9 @@ public final class DozeServiceHost implements DozeHost { private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final VisualStabilityManager mVisualStabilityManager; private final PulseExpansionHandler mPulseExpansionHandler; - private final StatusBarWindowController mStatusBarWindowController; + private final NotificationShadeWindowController mNotificationShadeWindowController; private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; - private StatusBarWindowViewController mStatusBarWindowViewController; + private NotificationShadeWindowViewController mNotificationShadeWindowViewController; private final LockscreenLockIconController mLockscreenLockIconController; private NotificationIconAreaController mNotificationIconAreaController; private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @@ -108,7 +108,7 @@ public final class DozeServiceHost implements DozeHost { DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor, VisualStabilityManager visualStabilityManager, PulseExpansionHandler pulseExpansionHandler, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, NotificationWakeUpCoordinator notificationWakeUpCoordinator, LockscreenLockIconController lockscreenLockIconController) { super(); @@ -127,7 +127,7 @@ public final class DozeServiceHost implements DozeHost { mKeyguardUpdateMonitor = keyguardUpdateMonitor; mVisualStabilityManager = visualStabilityManager; mPulseExpansionHandler = pulseExpansionHandler; - mStatusBarWindowController = statusBarWindowController; + mNotificationShadeWindowController = notificationShadeWindowController; mNotificationWakeUpCoordinator = notificationWakeUpCoordinator; mLockscreenLockIconController = lockscreenLockIconController; } @@ -140,13 +140,13 @@ public final class DozeServiceHost implements DozeHost { public void initialize(StatusBar statusBar, NotificationIconAreaController notificationIconAreaController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, - StatusBarWindowViewController statusBarWindowViewController, + NotificationShadeWindowViewController notificationShadeWindowViewController, NotificationPanelViewController notificationPanel, View ambientIndicationContainer) { mStatusBar = statusBar; mNotificationIconAreaController = notificationIconAreaController; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mNotificationPanel = notificationPanel; - mStatusBarWindowViewController = statusBarWindowViewController; + mNotificationShadeWindowViewController = notificationShadeWindowViewController; mAmbientIndicationContainer = ambientIndicationContainer; mBiometricUnlockController = mBiometricUnlockControllerLazy.get(); } @@ -292,7 +292,7 @@ public final class DozeServiceHost implements DozeHost { } mIgnoreTouchWhilePulsing = ignore; if (mStatusBarStateController.isDozing() && ignore) { - mStatusBarWindowViewController.cancelCurrentTouch(); + mNotificationShadeWindowViewController.cancelCurrentTouch(); } } @@ -391,7 +391,7 @@ public final class DozeServiceHost implements DozeHost { @Override public void setDozeScreenBrightness(int value) { - mStatusBarWindowController.setDozeScreenBrightness(value); + mNotificationShadeWindowController.setDozeScreenBrightness(value); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java index 7b20a7b7037c..c39ee3a90230 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java @@ -92,21 +92,22 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, public HeadsUpAppearanceController( NotificationIconAreaController notificationIconAreaController, - HeadsUpManagerPhone headsUpManager, View statusbarView, + HeadsUpManagerPhone headsUpManager, + View notificationShadeView, SysuiStatusBarStateController statusBarStateController, KeyguardBypassController keyguardBypassController, KeyguardStateController keyguardStateController, NotificationWakeUpCoordinator wakeUpCoordinator, CommandQueue commandQueue, - NotificationPanelViewController notificationPanelViewController) { + NotificationPanelViewController notificationPanelViewController, View statusBarView) { this(notificationIconAreaController, headsUpManager, statusBarStateController, keyguardBypassController, wakeUpCoordinator, keyguardStateController, commandQueue, - statusbarView.findViewById(R.id.heads_up_status_bar_view), - statusbarView.findViewById(R.id.notification_stack_scroller), + statusBarView.findViewById(R.id.heads_up_status_bar_view), + notificationShadeView.findViewById(R.id.notification_stack_scroller), notificationPanelViewController, - statusbarView.findViewById(R.id.clock), - statusbarView.findViewById(R.id.operator_name_frame), - statusbarView.findViewById(R.id.centered_icon_area)); + statusBarView.findViewById(R.id.clock), + statusBarView.findViewById(R.id.operator_name_frame), + statusBarView.findViewById(R.id.centered_icon_area)); } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index 6ac6d354cfff..c6e3fdefe701 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -65,7 +65,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, private final StatusBarStateController mStatusBarStateController; private final KeyguardBypassController mBypassController; private final int mAutoHeadsUpNotificationDecay; - private View mStatusBarWindowView; + private View mNotificationShadeWindowView; private NotificationGroupManager mGroupManager; private VisualStabilityManager mVisualStabilityManager; private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; @@ -124,14 +124,13 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, initResources(); } - - public void setUp(@NonNull View statusBarWindowView, + public void setUp(@NonNull View notificationShadeWindowView, @NonNull NotificationGroupManager groupManager, @NonNull StatusBar bar, @NonNull VisualStabilityManager visualStabilityManager) { - mStatusBarWindowView = statusBarWindowView; - mStatusBarTouchableRegionManager = new StatusBarTouchableRegionManager(mContext, this, bar, - statusBarWindowView); + mNotificationShadeWindowView = notificationShadeWindowView; + mStatusBarTouchableRegionManager = new StatusBarTouchableRegionManager(this, bar, + notificationShadeWindowView); mGroupManager = groupManager; mVisualStabilityManager = visualStabilityManager; @@ -364,7 +363,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, // updated yet, but callbacks leading out of the headsUp manager, querying it. Let's // therefore also check if the topEntry is null. if (!hasPinnedHeadsUp() || topEntry == null) { - mTouchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight); + mTouchableRegion.set(0, 0, mNotificationShadeWindowView.getWidth(), mStatusBarHeight); updateRegionForNotch(mTouchableRegion); } else { @@ -386,7 +385,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, } private void updateRegionForNotch(Region region) { - WindowInsets windowInsets = mStatusBarWindowView.getRootWindowInsets(); + WindowInsets windowInsets = mNotificationShadeWindowView.getRootWindowInsets(); if (windowInsets == null) { Log.w(TAG, "StatusBarWindowView is not attached."); return; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java index 3554b54db99b..707138ee8dc0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java @@ -128,7 +128,7 @@ public class NotificationIconAreaController implements DarkReceiver, mAodIcons.setAnimationsEnabled(false); mAodIcons.removeAllViews(); } - mAodIcons = mStatusBar.getStatusBarWindow().findViewById( + mAodIcons = mStatusBar.getNotificationShadeWindowView().findViewById( R.id.clock_notification_icon_container); mAodIcons.setOnLockScreen(true); updateAodIconsVisibility(false /* animate */); 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 90ec2a076e87..6112ae88f634 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -1367,14 +1367,7 @@ public class NotificationPanelViewController extends PanelViewController { if (mExpectingSynthesizedDown) { mExpectingSynthesizedDown = false; maybeVibrateOnOpening(); - Runnable runnable = () -> fling(velocity > 1f ? 1000f * velocity : 0, - true /* expand */); - if (mStatusBar.getStatusBarWindow().getHeight() != mStatusBar.getStatusBarHeight()) { - // The panel is already expanded to its full size, let's expand directly - runnable.run(); - } else { - mExpandAfterLayoutRunnable = runnable; - } + fling(velocity > 1f ? 1000f * velocity : 0, true /* expand */); onTrackingStopped(false); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java new file mode 100644 index 000000000000..d346d395e444 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java @@ -0,0 +1,714 @@ +/* + * 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.statusbar.phone; + +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + +import static com.android.systemui.DejankUtils.whitelistIpcs; +import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; + +import android.app.IActivityManager; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.res.Resources; +import android.graphics.PixelFormat; +import android.os.Binder; +import android.os.RemoteException; +import android.os.SystemProperties; +import android.os.Trace; +import android.util.Log; +import android.view.Display; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; + +import com.android.systemui.Dumpable; +import com.android.systemui.R; +import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.keyguard.KeyguardViewMediator; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; +import com.android.systemui.statusbar.RemoteInputController.Callback; +import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.SuperStatusBarViewFactory; +import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; + +import com.google.android.collect.Lists; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; + +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Encapsulates all logic for the notification shade window state management. + */ +@Singleton +public class NotificationShadeWindowController implements Callback, Dumpable, + ConfigurationListener { + + private static final String TAG = "NotificationShadeWindowController"; + private static final boolean DEBUG = false; + + private final Context mContext; + private final WindowManager mWindowManager; + private final IActivityManager mActivityManager; + private final DozeParameters mDozeParameters; + private final LayoutParams mLpChanged; + private final boolean mKeyguardScreenRotation; + private final long mLockScreenDisplayTimeout; + private final Display.Mode mKeyguardDisplayMode; + private final KeyguardBypassController mKeyguardBypassController; + private ViewGroup mNotificationShadeView; + private LayoutParams mLp; + private boolean mHasTopUi; + private boolean mHasTopUiChanged; + private float mScreenBrightnessDoze; + private final State mCurrentState = new State(); + private OtherwisedCollapsedListener mListener; + private ForcePluginOpenListener mForcePluginOpenListener; + private final ArrayList<WeakReference<StatusBarWindowCallback>> + mCallbacks = Lists.newArrayList(); + + private final SysuiColorExtractor mColorExtractor; + private final SuperStatusBarViewFactory mSuperStatusBarViewFactory; + + @Inject + public NotificationShadeWindowController(Context context, WindowManager windowManager, + IActivityManager activityManager, DozeParameters dozeParameters, + StatusBarStateController statusBarStateController, + ConfigurationController configurationController, + KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor, + SuperStatusBarViewFactory superStatusBarViewFactory) { + mContext = context; + mWindowManager = windowManager; + mActivityManager = activityManager; + mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation(); + mDozeParameters = dozeParameters; + mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze(); + mLpChanged = new LayoutParams(); + mKeyguardBypassController = keyguardBypassController; + mColorExtractor = colorExtractor; + mSuperStatusBarViewFactory = superStatusBarViewFactory; + mNotificationShadeView = mSuperStatusBarViewFactory.getNotificationShadeWindowView(); + + mLockScreenDisplayTimeout = context.getResources() + .getInteger(R.integer.config_lockScreenDisplayTimeout); + ((SysuiStatusBarStateController) statusBarStateController) + .addCallback(mStateListener, + SysuiStatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER); + configurationController.addCallback(this); + + Display.Mode[] supportedModes = context.getDisplay().getSupportedModes(); + Display.Mode currentMode = context.getDisplay().getMode(); + // Running on the highest frame rate available can be expensive. + // Let's specify a preferred refresh rate, and allow higher FPS only when we + // know that we're not falsing (because we unlocked.) + int keyguardRefreshRate = context.getResources() + .getInteger(R.integer.config_keyguardRefreshRate); + // Find supported display mode with the same resolution and requested refresh rate. + mKeyguardDisplayMode = Arrays.stream(supportedModes).filter(mode -> + (int) mode.getRefreshRate() == keyguardRefreshRate + && mode.getPhysicalWidth() == currentMode.getPhysicalWidth() + && mode.getPhysicalHeight() == currentMode.getPhysicalHeight()) + .findFirst().orElse(null); + } + + /** + * Register to receive notifications about status bar window state changes. + */ + public void registerCallback(StatusBarWindowCallback callback) { + // Prevent adding duplicate callbacks + for (int i = 0; i < mCallbacks.size(); i++) { + if (mCallbacks.get(i).get() == callback) { + return; + } + } + mCallbacks.add(new WeakReference<StatusBarWindowCallback>(callback)); + } + + private boolean shouldEnableKeyguardScreenRotation() { + Resources res = mContext.getResources(); + return SystemProperties.getBoolean("lockscreen.rot_override", false) + || res.getBoolean(R.bool.config_enableLockScreenRotation); + } + + /** + * Adds the notification shade view to the window manager. + */ + public void attach() { + // Now that the notification shade encompasses the sliding panel and its + // translucent backdrop, the entire thing is made TRANSLUCENT and is + // hardware-accelerated. + mLp = new LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, + LayoutParams.TYPE_NOTIFICATION_SHADE, + LayoutParams.FLAG_NOT_FOCUSABLE + | LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING + | LayoutParams.FLAG_SPLIT_TOUCH + | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, + PixelFormat.TRANSLUCENT); + mLp.token = new Binder(); + mLp.gravity = Gravity.TOP; + mLp.setFitWindowInsetsTypes(0 /* types */); + mLp.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE; + mLp.setTitle("NotificationShade"); + mLp.packageName = mContext.getPackageName(); + mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + mWindowManager.addView(mNotificationShadeView, mLp); + mLpChanged.copyFrom(mLp); + onThemeChanged(); + } + + public ViewGroup getNotificationShadeView() { + return mNotificationShadeView; + } + + public void setDozeScreenBrightness(int value) { + mScreenBrightnessDoze = value / 255f; + } + + private void setKeyguardDark(boolean dark) { + int vis = mNotificationShadeView.getSystemUiVisibility(); + if (dark) { + vis = vis | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; + vis = vis | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } else { + vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; + vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } + mNotificationShadeView.setSystemUiVisibility(vis); + } + + private void applyKeyguardFlags(State state) { + final boolean scrimsOccludingWallpaper = + state.mScrimsVisibility == ScrimController.OPAQUE; + final boolean keyguardOrAod = state.mKeyguardShowing + || (state.mDozing && mDozeParameters.getAlwaysOn()); + if (keyguardOrAod && !state.mBackdropShowing && !scrimsOccludingWallpaper) { + mLpChanged.flags |= LayoutParams.FLAG_SHOW_WALLPAPER; + } else { + mLpChanged.flags &= ~LayoutParams.FLAG_SHOW_WALLPAPER; + } + + if (state.mDozing) { + mLpChanged.privateFlags |= LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + } else { + mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + } + + if (mKeyguardDisplayMode != null) { + boolean bypassOnKeyguard = mKeyguardBypassController.getBypassEnabled() + && state.mStatusBarState == StatusBarState.KEYGUARD + && !state.mKeyguardFadingAway && !state.mKeyguardGoingAway; + if (state.mDozing || bypassOnKeyguard) { + mLpChanged.preferredDisplayModeId = mKeyguardDisplayMode.getModeId(); + } else { + mLpChanged.preferredDisplayModeId = 0; + } + Trace.setCounter("display_mode_id", mLpChanged.preferredDisplayModeId); + } + } + + private void adjustScreenOrientation(State state) { + if (state.isKeyguardShowingAndNotOccluded() || state.mDozing) { + if (mKeyguardScreenRotation) { + mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER; + } else { + mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; + } + } else { + mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + } + } + + private void applyFocusableFlag(State state) { + boolean panelFocusable = state.mNotificationShadeFocusable && state.mPanelExpanded; + if (state.mBouncerShowing && (state.mKeyguardOccluded || state.mKeyguardNeedsInput) + || ENABLE_REMOTE_INPUT && state.mRemoteInputActive + || state.mBubbleExpanded) { + mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE; + mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) { + mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE; + mLpChanged.flags |= LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } else { + mLpChanged.flags |= LayoutParams.FLAG_NOT_FOCUSABLE; + mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } + + mLpChanged.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE; + } + + private void applyForceShowNavigationFlag(State state) { + if (state.mPanelExpanded || state.mBouncerShowing + || ENABLE_REMOTE_INPUT && state.mRemoteInputActive) { + mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; + } else { + mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; + } + } + + private void applyVisibility(State state) { + boolean visible = isExpanded(state); + if (state.mForcePluginOpen) { + if (mListener != null) { + mListener.setWouldOtherwiseCollapse(visible); + } + visible = true; + } + if (visible) { + mNotificationShadeView.setVisibility(View.VISIBLE); + } else { + mNotificationShadeView.setVisibility(View.INVISIBLE); + } + } + + private boolean isExpanded(State state) { + return !state.mForceCollapsed && (state.isKeyguardShowingAndNotOccluded() + || state.mPanelVisible || state.mKeyguardFadingAway || state.mBouncerShowing + || state.mHeadsUpShowing || state.mBubblesShowing + || state.mScrimsVisibility != ScrimController.TRANSPARENT); + } + + private void applyFitsSystemWindows(State state) { + boolean fitsSystemWindows = !state.isKeyguardShowingAndNotOccluded(); + if (mNotificationShadeView != null + && mNotificationShadeView.getFitsSystemWindows() != fitsSystemWindows) { + mNotificationShadeView.setFitsSystemWindows(fitsSystemWindows); + mNotificationShadeView.requestApplyInsets(); + } + } + + private void applyUserActivityTimeout(State state) { + if (state.isKeyguardShowingAndNotOccluded() + && state.mStatusBarState == StatusBarState.KEYGUARD + && !state.mQsExpanded) { + mLpChanged.userActivityTimeout = state.mBouncerShowing + ? KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS : mLockScreenDisplayTimeout; + } else { + mLpChanged.userActivityTimeout = -1; + } + } + + private void applyInputFeatures(State state) { + if (state.isKeyguardShowingAndNotOccluded() + && state.mStatusBarState == StatusBarState.KEYGUARD + && !state.mQsExpanded && !state.mForceUserActivity) { + mLpChanged.inputFeatures |= + LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; + } else { + mLpChanged.inputFeatures &= + ~LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; + } + } + + private void applyStatusBarColorSpaceAgnosticFlag(State state) { + if (!isExpanded(state)) { + mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC; + } else { + mLpChanged.privateFlags &= + ~LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC; + } + } + + private void apply(State state) { + applyKeyguardFlags(state); + applyFocusableFlag(state); + applyForceShowNavigationFlag(state); + adjustScreenOrientation(state); + applyVisibility(state); + applyUserActivityTimeout(state); + applyInputFeatures(state); + applyFitsSystemWindows(state); + applyModalFlag(state); + applyBrightness(state); + applyHasTopUi(state); + applyNotTouchable(state); + applyStatusBarColorSpaceAgnosticFlag(state); + if (mLp != null && mLp.copyFrom(mLpChanged) != 0) { + mWindowManager.updateViewLayout(mNotificationShadeView, mLp); + } + if (mHasTopUi != mHasTopUiChanged) { + whitelistIpcs(() -> { + try { + mActivityManager.setHasTopUi(mHasTopUiChanged); + } catch (RemoteException e) { + Log.e(TAG, "Failed to call setHasTopUi", e); + } + mHasTopUi = mHasTopUiChanged; + }); + } + notifyStateChangedCallbacks(); + } + + public void notifyStateChangedCallbacks() { + for (int i = 0; i < mCallbacks.size(); i++) { + StatusBarWindowCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onStateChanged(mCurrentState.mKeyguardShowing, + mCurrentState.mKeyguardOccluded, + mCurrentState.mBouncerShowing); + } + } + } + + private void applyModalFlag(State state) { + if (state.mHeadsUpShowing) { + mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCH_MODAL; + } else { + mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCH_MODAL; + } + } + + private void applyBrightness(State state) { + if (state.mForceDozeBrightness) { + mLpChanged.screenBrightness = mScreenBrightnessDoze; + } else { + mLpChanged.screenBrightness = LayoutParams.BRIGHTNESS_OVERRIDE_NONE; + } + } + + private void applyHasTopUi(State state) { + mHasTopUiChanged = state.mForceHasTopUi || isExpanded(state); + } + + private void applyNotTouchable(State state) { + if (state.mNotTouchable) { + mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCHABLE; + } else { + mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCHABLE; + } + } + + public void setKeyguardShowing(boolean showing) { + mCurrentState.mKeyguardShowing = showing; + apply(mCurrentState); + } + + public void setKeyguardOccluded(boolean occluded) { + mCurrentState.mKeyguardOccluded = occluded; + apply(mCurrentState); + } + + public void setKeyguardNeedsInput(boolean needsInput) { + mCurrentState.mKeyguardNeedsInput = needsInput; + apply(mCurrentState); + } + + public void setPanelVisible(boolean visible) { + mCurrentState.mPanelVisible = visible; + mCurrentState.mNotificationShadeFocusable = visible; + apply(mCurrentState); + } + + public void setNotificationShadeFocusable(boolean focusable) { + mCurrentState.mNotificationShadeFocusable = focusable; + apply(mCurrentState); + } + + public void setBouncerShowing(boolean showing) { + mCurrentState.mBouncerShowing = showing; + apply(mCurrentState); + } + + public void setBackdropShowing(boolean showing) { + mCurrentState.mBackdropShowing = showing; + apply(mCurrentState); + } + + public void setKeyguardFadingAway(boolean keyguardFadingAway) { + mCurrentState.mKeyguardFadingAway = keyguardFadingAway; + apply(mCurrentState); + } + + public void setQsExpanded(boolean expanded) { + mCurrentState.mQsExpanded = expanded; + apply(mCurrentState); + } + + public void setForceUserActivity(boolean forceUserActivity) { + mCurrentState.mForceUserActivity = forceUserActivity; + apply(mCurrentState); + } + + public void setScrimsVisibility(int scrimsVisibility) { + mCurrentState.mScrimsVisibility = scrimsVisibility; + apply(mCurrentState); + } + + public void setHeadsUpShowing(boolean showing) { + mCurrentState.mHeadsUpShowing = showing; + apply(mCurrentState); + } + + public void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) { + mCurrentState.mWallpaperSupportsAmbientMode = supportsAmbientMode; + apply(mCurrentState); + } + + /** + * @param state The {@link StatusBarStateController} of the status bar. + */ + private void setStatusBarState(int state) { + mCurrentState.mStatusBarState = state; + apply(mCurrentState); + } + + /** + * Force the window to be collapsed, even if it should theoretically be expanded. + * Used for when a heads-up comes in but we still need to wait for the touchable regions to + * be computed. + */ + public void setForceWindowCollapsed(boolean force) { + mCurrentState.mForceCollapsed = force; + apply(mCurrentState); + } + + public void setPanelExpanded(boolean isExpanded) { + mCurrentState.mPanelExpanded = isExpanded; + apply(mCurrentState); + } + + @Override + public void onRemoteInputActive(boolean remoteInputActive) { + mCurrentState.mRemoteInputActive = remoteInputActive; + apply(mCurrentState); + } + + /** + * Set whether the screen brightness is forced to the value we use for doze mode by the status + * bar window. + */ + public void setForceDozeBrightness(boolean forceDozeBrightness) { + mCurrentState.mForceDozeBrightness = forceDozeBrightness; + apply(mCurrentState); + } + + public void setDozing(boolean dozing) { + mCurrentState.mDozing = dozing; + apply(mCurrentState); + } + + public void setForcePluginOpen(boolean forcePluginOpen) { + mCurrentState.mForcePluginOpen = forcePluginOpen; + apply(mCurrentState); + if (mForcePluginOpenListener != null) { + mForcePluginOpenListener.onChange(forcePluginOpen); + } + } + + /** + * The forcePluginOpen state for the status bar. + */ + public boolean getForcePluginOpen() { + return mCurrentState.mForcePluginOpen; + } + + public void setNotTouchable(boolean notTouchable) { + mCurrentState.mNotTouchable = notTouchable; + apply(mCurrentState); + } + + /** + * Sets whether there are bubbles showing on the screen. + */ + public void setBubblesShowing(boolean bubblesShowing) { + mCurrentState.mBubblesShowing = bubblesShowing; + apply(mCurrentState); + } + + /** + * The bubbles showing state for the status bar. + */ + public boolean getBubblesShowing() { + return mCurrentState.mBubblesShowing; + } + + /** + * Sets if there is a bubble being expanded on the screen. + */ + public void setBubbleExpanded(boolean bubbleExpanded) { + mCurrentState.mBubbleExpanded = bubbleExpanded; + apply(mCurrentState); + } + + /** + * Whether the bubble is shown in expanded state for the status bar. + */ + public boolean getBubbleExpanded() { + return mCurrentState.mBubbleExpanded; + } + + /** + * Whether the status bar panel is expanded or not. + */ + public boolean getPanelExpanded() { + return mCurrentState.mPanelExpanded; + } + + public void setStateListener(OtherwisedCollapsedListener listener) { + mListener = listener; + } + + public void setForcePluginOpenListener(ForcePluginOpenListener listener) { + mForcePluginOpenListener = listener; + } + + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("StatusBarWindowController:"); + pw.println(" mKeyguardDisplayMode=" + mKeyguardDisplayMode); + pw.println(mCurrentState); + } + + public boolean isShowingWallpaper() { + return !mCurrentState.mBackdropShowing; + } + + @Override + public void onThemeChanged() { + if (mNotificationShadeView == null) { + return; + } + + final boolean useDarkText = mColorExtractor.getNeutralColors().supportsDarkText(); + // Make sure we have the correct navbar/statusbar colors. + setKeyguardDark(useDarkText); + } + + /** + * When keyguard will be dismissed but didn't start animation yet. + */ + public void setKeyguardGoingAway(boolean goingAway) { + mCurrentState.mKeyguardGoingAway = goingAway; + apply(mCurrentState); + } + + public boolean getForceHasTopUi() { + return mCurrentState.mForceHasTopUi; + } + + public void setForceHasTopUi(boolean forceHasTopUi) { + mCurrentState.mForceHasTopUi = forceHasTopUi; + apply(mCurrentState); + } + + private static class State { + boolean mKeyguardShowing; + boolean mKeyguardOccluded; + boolean mKeyguardNeedsInput; + boolean mPanelVisible; + boolean mPanelExpanded; + boolean mNotificationShadeFocusable; + boolean mBouncerShowing; + boolean mKeyguardFadingAway; + boolean mKeyguardGoingAway; + boolean mQsExpanded; + boolean mHeadsUpShowing; + boolean mForceCollapsed; + boolean mForceDozeBrightness; + boolean mForceUserActivity; + boolean mBackdropShowing; + boolean mWallpaperSupportsAmbientMode; + boolean mNotTouchable; + boolean mBubblesShowing; + boolean mBubbleExpanded; + boolean mForceHasTopUi; + + /** + * The {@link StatusBar} state from the status bar. + */ + int mStatusBarState; + + boolean mRemoteInputActive; + boolean mForcePluginOpen; + boolean mDozing; + int mScrimsVisibility; + + private boolean isKeyguardShowingAndNotOccluded() { + return mKeyguardShowing && !mKeyguardOccluded; + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + String newLine = "\n"; + result.append("Window State {"); + result.append(newLine); + + Field[] fields = this.getClass().getDeclaredFields(); + + // Print field names paired with their values + for (Field field : fields) { + result.append(" "); + try { + result.append(field.getName()); + result.append(": "); + //requires access to private field: + result.append(field.get(this)); + } catch (IllegalAccessException ex) { + } + result.append(newLine); + } + result.append("}"); + + return result.toString(); + } + } + + private final StateListener mStateListener = new StateListener() { + @Override + public void onStateChanged(int newState) { + setStatusBarState(newState); + } + + @Override + public void onDozingChanged(boolean isDozing) { + setDozing(isDozing); + } + }; + + /** + * Custom listener to pipe data back to plugins about whether or not the status bar would be + * collapsed if not for the plugin. + * TODO: Find cleaner way to do this. + */ + public interface OtherwisedCollapsedListener { + void setWouldOtherwiseCollapse(boolean otherwiseCollapse); + } + + /** + * Listener to indicate forcePluginOpen has changed + */ + public interface ForcePluginOpenListener { + /** + * Called when mState.forcePluginOpen is changed + */ + void onChange(boolean forceOpen); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java new file mode 100644 index 000000000000..6979554303b3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java @@ -0,0 +1,614 @@ +/* + * 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.statusbar.phone; + +import android.annotation.ColorInt; +import android.annotation.DrawableRes; +import android.annotation.LayoutRes; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Insets; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.util.AttributeSet; +import android.view.ActionMode; +import android.view.DisplayCutout; +import android.view.InputQueue; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowInsetsController; +import android.widget.FrameLayout; + +import com.android.internal.view.FloatingActionMode; +import com.android.internal.widget.FloatingToolbar; +import com.android.systemui.R; + +/** + * Combined keyguard and notification panel view. Also holding backdrop and scrims. + */ +public class NotificationShadeWindowView extends FrameLayout { + public static final String TAG = "NotificationShadeWindowView"; + public static final boolean DEBUG = StatusBar.DEBUG; + + private int mRightInset = 0; + private int mLeftInset = 0; + + // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by + // DecorView, but since this is a special window we have to roll our own. + private View mFloatingActionModeOriginatingView; + private ActionMode mFloatingActionMode; + private FloatingToolbar mFloatingToolbar; + private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener; + + private InteractionEventHandler mInteractionEventHandler; + + public NotificationShadeWindowView(Context context, AttributeSet attrs) { + super(context, attrs); + setMotionEventSplittingEnabled(false); + } + + public NotificationPanelView getNotificationPanelView() { + return findViewById(R.id.notification_panel); + } + + @Override + public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) { + final Insets insets = windowInsets.getMaxInsets(WindowInsets.Type.systemBars()); + if (getFitsSystemWindows()) { + boolean paddingChanged = insets.top != getPaddingTop() + || insets.bottom != getPaddingBottom(); + + int rightCutout = 0; + int leftCutout = 0; + DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout(); + if (displayCutout != null) { + leftCutout = displayCutout.getSafeInsetLeft(); + rightCutout = displayCutout.getSafeInsetRight(); + } + + int targetLeft = Math.max(insets.left, leftCutout); + int targetRight = Math.max(insets.right, rightCutout); + + // Super-special right inset handling, because scrims and backdrop need to ignore it. + if (targetRight != mRightInset || targetLeft != mLeftInset) { + mRightInset = targetRight; + mLeftInset = targetLeft; + applyMargins(); + } + // Drop top inset, and pass through bottom inset. + if (paddingChanged) { + setPadding(0, 0, 0, 0); + } + } else { + if (mRightInset != 0 || mLeftInset != 0) { + mRightInset = 0; + mLeftInset = 0; + applyMargins(); + } + boolean changed = getPaddingLeft() != 0 + || getPaddingRight() != 0 + || getPaddingTop() != 0 + || getPaddingBottom() != 0; + if (changed) { + setPadding(0, 0, 0, 0); + } + } + return windowInsets; + } + + private void applyMargins() { + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + if (child.getLayoutParams() instanceof LayoutParams) { + LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.ignoreRightInset + && (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset)) { + lp.rightMargin = mRightInset; + lp.leftMargin = mLeftInset; + child.requestLayout(); + } + } + } + } + + @Override + public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + @Override + protected FrameLayout.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + setWillNotDraw(!DEBUG); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (mInteractionEventHandler.interceptMediaKey(event)) { + return true; + } + + if (super.dispatchKeyEvent(event)) { + return true; + } + + return mInteractionEventHandler.dispatchKeyEvent(event); + } + + protected void setInteractionEventHandler(InteractionEventHandler listener) { + mInteractionEventHandler = listener; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + Boolean result = mInteractionEventHandler.handleDispatchTouchEvent(ev); + + return result != null ? result : super.dispatchTouchEvent(ev); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + boolean intercept = mInteractionEventHandler.shouldInterceptTouchEvent(ev); + if (!intercept) { + intercept = super.onInterceptTouchEvent(ev); + } + if (intercept) { + mInteractionEventHandler.didIntercept(ev); + } + + return intercept; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + boolean handled = mInteractionEventHandler.handleTouchEvent(ev); + + if (!handled) { + handled = super.onTouchEvent(ev); + } + + if (!handled) { + mInteractionEventHandler.didNotHandleTouchEvent(ev); + } + + return handled; + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (DEBUG) { + Paint pt = new Paint(); + pt.setColor(0x80FFFF00); + pt.setStrokeWidth(12.0f); + pt.setStyle(Paint.Style.STROKE); + canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt); + } + } + + class LayoutParams extends FrameLayout.LayoutParams { + + public boolean ignoreRightInset; + + LayoutParams(int width, int height) { + super(width, height); + } + + LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + + TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout); + ignoreRightInset = a.getBoolean( + R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false); + a.recycle(); + } + } + + @Override + public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback, + int type) { + if (type == ActionMode.TYPE_FLOATING) { + return startActionMode(originalView, callback, type); + } + return super.startActionModeForChild(originalView, callback, type); + } + + private ActionMode createFloatingActionMode( + View originatingView, ActionMode.Callback2 callback) { + if (mFloatingActionMode != null) { + mFloatingActionMode.finish(); + } + cleanupFloatingActionModeViews(); + mFloatingToolbar = new FloatingToolbar(mFakeWindow); + final FloatingActionMode mode = + new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar); + mFloatingActionModeOriginatingView = originatingView; + mFloatingToolbarPreDrawListener = + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + mode.updateViewLocationInWindow(); + return true; + } + }; + return mode; + } + + private void setHandledFloatingActionMode(ActionMode mode) { + mFloatingActionMode = mode; + mFloatingActionMode.invalidate(); // Will show the floating toolbar if necessary. + mFloatingActionModeOriginatingView.getViewTreeObserver() + .addOnPreDrawListener(mFloatingToolbarPreDrawListener); + } + + private void cleanupFloatingActionModeViews() { + if (mFloatingToolbar != null) { + mFloatingToolbar.dismiss(); + mFloatingToolbar = null; + } + if (mFloatingActionModeOriginatingView != null) { + if (mFloatingToolbarPreDrawListener != null) { + mFloatingActionModeOriginatingView.getViewTreeObserver() + .removeOnPreDrawListener(mFloatingToolbarPreDrawListener); + mFloatingToolbarPreDrawListener = null; + } + mFloatingActionModeOriginatingView = null; + } + } + + private ActionMode startActionMode( + View originatingView, ActionMode.Callback callback, int type) { + ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback); + ActionMode mode = createFloatingActionMode(originatingView, wrappedCallback); + if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) { + setHandledFloatingActionMode(mode); + } else { + mode = null; + } + return mode; + } + + private class ActionModeCallback2Wrapper extends ActionMode.Callback2 { + private final ActionMode.Callback mWrapped; + + ActionModeCallback2Wrapper(ActionMode.Callback wrapped) { + mWrapped = wrapped; + } + + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + return mWrapped.onCreateActionMode(mode, menu); + } + + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + requestFitSystemWindows(); + return mWrapped.onPrepareActionMode(mode, menu); + } + + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + return mWrapped.onActionItemClicked(mode, item); + } + + public void onDestroyActionMode(ActionMode mode) { + mWrapped.onDestroyActionMode(mode); + if (mode == mFloatingActionMode) { + cleanupFloatingActionModeViews(); + mFloatingActionMode = null; + } + requestFitSystemWindows(); + } + + @Override + public void onGetContentRect(ActionMode mode, View view, Rect outRect) { + if (mWrapped instanceof ActionMode.Callback2) { + ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect); + } else { + super.onGetContentRect(mode, view, outRect); + } + } + } + + interface InteractionEventHandler { + /** + * Returns a result for {@link ViewGroup#dispatchTouchEvent(MotionEvent)} or null to defer + * to the super method. + */ + Boolean handleDispatchTouchEvent(MotionEvent ev); + + /** + * Returns if the view should intercept the touch event. + * + * The touch event may still be interecepted if + * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)} decides to do so. + */ + boolean shouldInterceptTouchEvent(MotionEvent ev); + + /** + * Called when the view decides to intercept the touch event. + */ + void didIntercept(MotionEvent ev); + + boolean handleTouchEvent(MotionEvent ev); + + void didNotHandleTouchEvent(MotionEvent ev); + + boolean interceptMediaKey(KeyEvent event); + + boolean dispatchKeyEvent(KeyEvent event); + } + + /** + * Minimal window to satisfy FloatingToolbar. + */ + private Window mFakeWindow = new Window(mContext) { + @Override + public void takeSurface(SurfaceHolder.Callback2 callback) { + } + + @Override + public void takeInputQueue(InputQueue.Callback callback) { + } + + @Override + public boolean isFloating() { + return false; + } + + @Override + public void alwaysReadCloseOnTouchAttr() { + } + + @Override + public void setContentView(@LayoutRes int layoutResID) { + } + + @Override + public void setContentView(View view) { + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + } + + @Override + public void addContentView(View view, ViewGroup.LayoutParams params) { + } + + @Override + public void clearContentView() { + } + + @Override + public View getCurrentFocus() { + return null; + } + + @Override + public LayoutInflater getLayoutInflater() { + return null; + } + + @Override + public void setTitle(CharSequence title) { + } + + @Override + public void setTitleColor(@ColorInt int textColor) { + } + + @Override + public void openPanel(int featureId, KeyEvent event) { + } + + @Override + public void closePanel(int featureId) { + } + + @Override + public void togglePanel(int featureId, KeyEvent event) { + } + + @Override + public void invalidatePanelMenu(int featureId) { + } + + @Override + public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) { + return false; + } + + @Override + public boolean performPanelIdentifierAction(int featureId, int id, int flags) { + return false; + } + + @Override + public void closeAllPanels() { + } + + @Override + public boolean performContextMenuIdentifierAction(int id, int flags) { + return false; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + } + + @Override + public void setBackgroundDrawable(Drawable drawable) { + } + + @Override + public void setFeatureDrawableResource(int featureId, @DrawableRes int resId) { + } + + @Override + public void setFeatureDrawableUri(int featureId, Uri uri) { + } + + @Override + public void setFeatureDrawable(int featureId, Drawable drawable) { + } + + @Override + public void setFeatureDrawableAlpha(int featureId, int alpha) { + } + + @Override + public void setFeatureInt(int featureId, int value) { + } + + @Override + public void takeKeyEvents(boolean get) { + } + + @Override + public boolean superDispatchKeyEvent(KeyEvent event) { + return false; + } + + @Override + public boolean superDispatchKeyShortcutEvent(KeyEvent event) { + return false; + } + + @Override + public boolean superDispatchTouchEvent(MotionEvent event) { + return false; + } + + @Override + public boolean superDispatchTrackballEvent(MotionEvent event) { + return false; + } + + @Override + public boolean superDispatchGenericMotionEvent(MotionEvent event) { + return false; + } + + @Override + public View getDecorView() { + return NotificationShadeWindowView.this; + } + + @Override + public View peekDecorView() { + return null; + } + + @Override + public Bundle saveHierarchyState() { + return null; + } + + @Override + public void restoreHierarchyState(Bundle savedInstanceState) { + } + + @Override + protected void onActive() { + } + + @Override + public void setChildDrawable(int featureId, Drawable drawable) { + } + + @Override + public void setChildInt(int featureId, int value) { + } + + @Override + public boolean isShortcutKey(int keyCode, KeyEvent event) { + return false; + } + + @Override + public void setVolumeControlStream(int streamType) { + } + + @Override + public int getVolumeControlStream() { + return 0; + } + + @Override + public int getStatusBarColor() { + return 0; + } + + @Override + public void setStatusBarColor(@ColorInt int color) { + } + + @Override + public int getNavigationBarColor() { + return 0; + } + + @Override + public void setNavigationBarColor(@ColorInt int color) { + } + + @Override + public void setDecorCaptionShade(int decorCaptionShade) { + } + + @Override + public void setResizingCaptionDrawable(Drawable drawable) { + } + + @Override + public void onMultiWindowModeChanged() { + } + + @Override + public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { + } + + @Override + public void reportActivityRelaunched() { + } + + @Override + public WindowInsetsController getInsetsController() { + return null; + } + }; + +} + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index 4935f0e8dd83..c691a35b566a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -16,7 +16,10 @@ package com.android.systemui.statusbar.phone; +import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; + import android.app.StatusBarManager; +import android.graphics.RectF; import android.hardware.display.AmbientDisplayConfiguration; import android.media.AudioManager; import android.media.session.MediaSessionLegacyHelper; @@ -56,9 +59,9 @@ import java.io.PrintWriter; import javax.inject.Inject; /** - * Controller for {@link StatusBarWindowView}. + * Controller for {@link NotificationShadeWindowView}. */ -public class StatusBarWindowViewController { +public class NotificationShadeWindowViewController { private final InjectionInflationController mInjectionInflationController; private final NotificationWakeUpCoordinator mCoordinator; private final PulseExpansionHandler mPulseExpansionHandler; @@ -74,7 +77,7 @@ public class StatusBarWindowViewController { private final DozeLog mDozeLog; private final DozeParameters mDozeParameters; private final CommandQueue mCommandQueue; - private final StatusBarWindowView mView; + private final NotificationShadeWindowView mView; private final ShadeController mShadeController; private GestureDetector mGestureDetector; @@ -93,8 +96,13 @@ public class StatusBarWindowViewController { private final DockManager mDockManager; private final NotificationPanelViewController mNotificationPanelViewController; + // Used for determining view / touch intersection + private int[] mTempLocation = new int[2]; + private RectF mTempRect = new RectF(); + private boolean mIsTrackingBarGesture = false; + @Inject - public StatusBarWindowViewController( + public NotificationShadeWindowViewController( InjectionInflationController injectionInflationController, NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler, @@ -112,7 +120,7 @@ public class StatusBarWindowViewController { CommandQueue commandQueue, ShadeController shadeController, DockManager dockManager, - StatusBarWindowView statusBarWindowView, + NotificationShadeWindowView statusBarWindowView, NotificationPanelViewController notificationPanelViewController) { mInjectionInflationController = injectionInflationController; mCoordinator = coordinator; @@ -182,7 +190,7 @@ public class StatusBarWindowViewController { }; mGestureDetector = new GestureDetector(mView.getContext(), gestureListener); - mView.setInteractionEventHandler(new StatusBarWindowView.InteractionEventHandler() { + mView.setInteractionEventHandler(new NotificationShadeWindowView.InteractionEventHandler() { @Override public Boolean handleDispatchTouchEvent(MotionEvent ev) { boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN; @@ -244,6 +252,26 @@ public class StatusBarWindowViewController { return mStatusBarView.dispatchTouchEvent(ev); } + if (!mIsTrackingBarGesture && isDown + && mNotificationPanelViewController.isFullyCollapsed()) { + float x = ev.getRawX(); + float y = ev.getRawY(); + if (isIntersecting(mStatusBarView, x, y)) { + if (mService.isSameStatusBarState(WINDOW_STATE_SHOWING)) { + mIsTrackingBarGesture = true; + return mStatusBarView.dispatchTouchEvent(ev); + } else { // it's hidden or hiding, don't send to notification shade. + return true; + } + } + } else if (mIsTrackingBarGesture) { + final boolean sendToNotification = mStatusBarView.dispatchTouchEvent(ev); + if (isUp || isCancel) { + mIsTrackingBarGesture = false; + } + return sendToNotification; + } + return null; } @@ -357,7 +385,7 @@ public class StatusBarWindowViewController { dragDownCallback, mFalsingManager)); } - public StatusBarWindowView getView() { + public NotificationShadeWindowView getView() { return mView; } @@ -414,4 +442,11 @@ public class StatusBarWindowViewController { void setDragDownHelper(DragDownHelper dragDownHelper) { mDragDownHelper = dragDownHelper; } + + private boolean isIntersecting(View view, float x, float y) { + mTempLocation = view.getLocationOnScreen(); + mTempRect.set(mTempLocation[0], mTempLocation[1], mTempLocation[0] + view.getWidth(), + mTempLocation[1] + view.getHeight()); + return mTempRect.contains(x, y); + } } 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 3d8e09afea4d..af46f7bfa82d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -783,8 +783,7 @@ public abstract class PanelViewController { mView.getViewTreeObserver().removeOnGlobalLayoutListener(this); return; } - if (mStatusBar.getStatusBarWindow().getHeight() - != mStatusBar.getStatusBarHeight()) { + if (mStatusBar.getNotificationShadeWindowView().isVisibleToUser()) { mView.getViewTreeObserver().removeOnGlobalLayoutListener(this); if (mAnimateAfterExpanding) { notifyExpandingStarted(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 45f3bf986141..ffbbffc0d8d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -323,8 +323,7 @@ public class PhoneStatusBarView extends PanelBar { R.dimen.display_cutout_margin_consumption); ViewGroup.LayoutParams layoutParams = getLayoutParams(); - layoutParams.height = getResources().getDimensionPixelSize( - R.dimen.status_bar_height); + layoutParams.height = getResources().getDimensionPixelSize(R.dimen.status_bar_height); setLayoutParams(layoutParams); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java index 866dc2d51241..333061547d7e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java @@ -44,7 +44,7 @@ public class ShadeControllerImpl implements ShadeController { private final CommandQueue mCommandQueue; private final StatusBarStateController mStatusBarStateController; - protected final StatusBarWindowController mStatusBarWindowController; + protected final NotificationShadeWindowController mNotificationShadeWindowController; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private final int mDisplayId; protected final Lazy<StatusBar> mStatusBarLazy; @@ -57,7 +57,7 @@ public class ShadeControllerImpl implements ShadeController { public ShadeControllerImpl( CommandQueue commandQueue, StatusBarStateController statusBarStateController, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, WindowManager windowManager, Lazy<StatusBar> statusBarLazy, @@ -66,7 +66,7 @@ public class ShadeControllerImpl implements ShadeController { ) { mCommandQueue = commandQueue; mStatusBarStateController = statusBarStateController; - mStatusBarWindowController = statusBarWindowController; + mNotificationShadeWindowController = notificationShadeWindowController; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mDisplayId = windowManager.getDefaultDisplay().getDisplayId(); // TODO: Remove circular reference to StatusBar when possible. @@ -122,14 +122,15 @@ public class ShadeControllerImpl implements ShadeController { } // TODO(b/62444020): remove when this bug is fixed - Log.v(TAG, "mStatusBarWindow: " + getStatusBarWindowView() + " canPanelBeCollapsed(): " + Log.v(TAG, "NotificationShadeWindow: " + getNotificationShadeWindowView() + + " canPanelBeCollapsed(): " + getNotificationPanelViewController().canPanelBeCollapsed()); - if (getStatusBarWindowView() != null + if (getNotificationShadeWindowView() != null && getNotificationPanelViewController().canPanelBeCollapsed()) { // release focus immediately to kick off focus change transition - mStatusBarWindowController.setStatusBarFocusable(false); + mNotificationShadeWindowController.setNotificationShadeFocusable(false); - getStatusBar().getStatusBarWindowViewController().cancelExpandHelper(); + getStatusBar().getNotificationShadeWindowViewController().cancelExpandHelper(); getStatusBarView().collapsePanel(true /* animate */, delayed, speedUpFactor); } else { mBubbleControllerLazy.get().collapseStack(); @@ -154,8 +155,7 @@ public class ShadeControllerImpl implements ShadeController { new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { - if (getStatusBar().getStatusBarWindow().getHeight() - != getStatusBar().getStatusBarHeight()) { + if (getStatusBar().getNotificationShadeWindowView().isVisibleToUser()) { getNotificationPanelViewController().removeOnGlobalLayoutListener(this); getNotificationPanelViewController().getView().post(executable); } @@ -222,8 +222,8 @@ public class ShadeControllerImpl implements ShadeController { return getStatusBar().getPresenter(); } - protected StatusBarWindowView getStatusBarWindowView() { - return getStatusBar().getStatusBarWindow(); + protected NotificationShadeWindowView getNotificationShadeWindowView() { + return getStatusBar().getNotificationShadeWindowView(); } protected PhoneStatusBarView getStatusBarView() { 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 dc9cf7714e7e..4e8442f14dba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -342,9 +342,11 @@ public class StatusBar extends SystemUI implements DemoMode, private final Point mCurrentDisplaySize = new Point(); - protected StatusBarWindowView mStatusBarWindow; + protected NotificationShadeWindowView mNotificationShadeWindowView; + protected StatusBarWindowView mPhoneStatusBarWindow; protected PhoneStatusBarView mStatusBarView; private int mStatusBarWindowState = WINDOW_STATE_SHOWING; + protected NotificationShadeWindowController mNotificationShadeWindowController; protected StatusBarWindowController mStatusBarWindowController; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final LockscreenLockIconController mLockscreenLockIconController; @@ -368,7 +370,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final FalsingManager mFalsingManager; private final BroadcastDispatcher mBroadcastDispatcher; private final ConfigurationController mConfigurationController; - protected StatusBarWindowViewController mStatusBarWindowViewController; + protected NotificationShadeWindowViewController mNotificationShadeWindowViewController; private final DozeParameters mDozeParameters; private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy; private final Provider<StatusBarComponent.Builder> mStatusBarComponentBuilder; @@ -503,7 +505,7 @@ public class StatusBar extends SystemUI implements DemoMode, && ((info == null && imageWallpaperInAmbient) || (info != null && info.supportsAmbientMode())); - mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode); + mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode); mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode); } }; @@ -659,7 +661,7 @@ public class StatusBar extends SystemUI implements DemoMode, Lazy<AssistManager> assistManagerLazy, NotificationListener notificationListener, ConfigurationController configurationController, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, LockscreenLockIconController lockscreenLockIconController, DozeParameters dozeParameters, ScrimController scrimController, @@ -740,7 +742,7 @@ public class StatusBar extends SystemUI implements DemoMode, mAssistManagerLazy = assistManagerLazy; mNotificationListener = notificationListener; mConfigurationController = configurationController; - mStatusBarWindowController = statusBarWindowController; + mNotificationShadeWindowController = notificationShadeWindowController; mLockscreenLockIconController = lockscreenLockIconController; mDozeServiceHost = dozeServiceHost; mPowerManager = powerManager; @@ -912,7 +914,7 @@ public class StatusBar extends SystemUI implements DemoMode, mKeyguardUpdateMonitor.registerCallback(mUpdateCallback); mDozeServiceHost.initialize(this, mNotificationIconAreaController, - mStatusBarKeyguardViewManager, mStatusBarWindowViewController, + mStatusBarKeyguardViewManager, mNotificationShadeWindowViewController, mNotificationPanelViewController, mAmbientIndicationContainer); mConfigurationController.addCallback(this); @@ -930,7 +932,8 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) { mMainThreadHandler.post( - () -> plugin.setup(getStatusBarWindow(), getNavigationBarView(), + () -> plugin.setup(getNotificationShadeWindowView(), + getNavigationBarView(), new Callback(plugin), mDozeParameters)); } @@ -938,7 +941,8 @@ public class StatusBar extends SystemUI implements DemoMode, public void onPluginDisconnected(OverlayPlugin plugin) { mMainThreadHandler.post(() -> { mOverlays.remove(plugin); - mStatusBarWindowController.setForcePluginOpen(mOverlays.size() != 0); + mNotificationShadeWindowController + .setForcePluginOpen(mOverlays.size() != 0); }); } @@ -957,10 +961,10 @@ public class StatusBar extends SystemUI implements DemoMode, mOverlays.remove(mPlugin); } mMainThreadHandler.post(() -> { - mStatusBarWindowController + mNotificationShadeWindowController .setStateListener(b -> mOverlays.forEach( o -> o.setCollapseDesired(b))); - mStatusBarWindowController + mNotificationShadeWindowController .setForcePluginOpen(mOverlays.size() != 0); }); } @@ -978,12 +982,13 @@ public class StatusBar extends SystemUI implements DemoMode, updateTheme(); inflateStatusBarWindow(); - mStatusBarWindowViewController.setService(this); - mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener()); + mNotificationShadeWindowViewController.setService(this); + mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener()); // TODO: Deal with the ugliness that comes from having some of the statusbar broken out // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot. - mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller); + mStackScroller = mNotificationShadeWindowView.findViewById( + R.id.notification_stack_scroller); NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller; mNotificationLogger.setUpWithContainer(notifListContainer); @@ -1004,17 +1009,18 @@ public class StatusBar extends SystemUI implements DemoMode, // Allow plugins to reference DarkIconDispatcher and StatusBarStateController mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class); mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class); - FragmentHostManager.get(mStatusBarWindow) + FragmentHostManager.get(mPhoneStatusBarWindow) .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> { CollapsedStatusBarFragment statusBarFragment = (CollapsedStatusBarFragment) fragment; - statusBarFragment.initNotificationIconArea(mNotificationIconAreaController); + PhoneStatusBarView oldStatusBarView = mStatusBarView; - mStatusBarView = (PhoneStatusBarView) fragment.getView(); + mStatusBarView = (PhoneStatusBarView) statusBarFragment.getView(); mStatusBarView.setBar(this); mStatusBarView.setPanel(mNotificationPanelViewController); mStatusBarView.setScrimController(mScrimController); + statusBarFragment.initNotificationIconArea(mNotificationIconAreaController); // CollapsedStatusBarFragment re-inflated PhoneStatusBarView and both of // mStatusBarView.mExpanded and mStatusBarView.mBouncerShowing are false. // PhoneStatusBarView's new instance will set to be gone in @@ -1038,16 +1044,18 @@ public class StatusBar extends SystemUI implements DemoMode, mHeadsUpAppearanceController.destroy(); } // TODO: this should probably be scoped to the StatusBarComponent + // TODO (b/136993073) Separate notification shade and status bar mHeadsUpAppearanceController = new HeadsUpAppearanceController( - mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow, + mNotificationIconAreaController, mHeadsUpManager, + mNotificationShadeWindowView, mStatusBarStateController, mKeyguardBypassController, mKeyguardStateController, mWakeUpCoordinator, mCommandQueue, - mNotificationPanelViewController); + mNotificationPanelViewController, mStatusBarView); mHeadsUpAppearanceController.readFrom(oldController); mLightsOutNotifController.setLightsOutNotifView( mStatusBarView.findViewById(R.id.notification_lights_out)); - mStatusBarWindowViewController.setStatusBarView(mStatusBarView); + mNotificationShadeWindowViewController.setStatusBarView(mStatusBarView); checkBarModes(); }).getFragmentManager() .beginTransaction() @@ -1055,7 +1063,8 @@ public class StatusBar extends SystemUI implements DemoMode, CollapsedStatusBarFragment.TAG) .commit(); - mHeadsUpManager.setUp(mStatusBarWindow, mGroupManager, this, mVisualStabilityManager); + mHeadsUpManager.setUp(mNotificationShadeWindowView, mGroupManager, this, + mVisualStabilityManager); mConfigurationController.addCallback(mHeadsUpManager); mHeadsUpManager.addListener(this); mHeadsUpManager.addListener(mNotificationPanelViewController.getOnHeadsUpChangedListener()); @@ -1075,12 +1084,12 @@ public class StatusBar extends SystemUI implements DemoMode, mKeyguardIndicationController = SystemUIFactory.getInstance().createKeyguardIndicationController(mContext, - mStatusBarWindow.findViewById(R.id.keyguard_indication_area), - mStatusBarWindow.findViewById(R.id.lock_icon)); + mNotificationShadeWindowView.findViewById(R.id.keyguard_indication_area), + mNotificationShadeWindowView.findViewById(R.id.lock_icon)); mNotificationPanelViewController.setKeyguardIndicationController( mKeyguardIndicationController); - mAmbientIndicationContainer = mStatusBarWindow.findViewById( + mAmbientIndicationContainer = mNotificationShadeWindowView.findViewById( R.id.ambient_indication_container); // TODO: Find better place for this callback. @@ -1101,13 +1110,13 @@ public class StatusBar extends SystemUI implements DemoMode, mAutoHideController.setStatusBar(this); - ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind); - ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front); - ScrimView scrimForBubble = mStatusBarWindow.findViewById(R.id.scrim_for_bubble); + ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind); + ScrimView scrimInFront = mNotificationShadeWindowView.findViewById(R.id.scrim_in_front); + ScrimView scrimForBubble = mNotificationShadeWindowView.findViewById(R.id.scrim_for_bubble); mScrimController.setScrimVisibleListener(scrimsVisible -> { - mStatusBarWindowController.setScrimsVisibility(scrimsVisible); - if (mStatusBarWindow != null) { + mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible); + if (mNotificationShadeWindowView != null) { mLockscreenLockIconController.onScrimVisibilityChanged(scrimsVisible); } }); @@ -1116,7 +1125,7 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationPanelViewController.initDependencies(this, mGroupManager, mNotificationShelf, mNotificationIconAreaController, mScrimController); - BackDropView backdrop = mStatusBarWindow.findViewById(R.id.backdrop); + BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop); mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front), backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper); @@ -1129,7 +1138,7 @@ public class StatusBar extends SystemUI implements DemoMode, mLockscreenLockIconController::onShowingLaunchAffordanceChanged); // Set up the quick settings tile panel - View container = mStatusBarWindow.findViewById(R.id.qs_frame); + final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame); if (container != null) { FragmentHostManager fragmentHostManager = FragmentHostManager.get(container); ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame, @@ -1138,7 +1147,8 @@ public class StatusBar extends SystemUI implements DemoMode, .withPlugin(QS.class) .withDefault(this::createDefaultQSFragment) .build()); - mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow, + mBrightnessMirrorController = new BrightnessMirrorController( + mNotificationShadeWindowView, mNotificationPanelViewController, (visible) -> { mBrightnessMirrorVisible = visible; @@ -1153,7 +1163,8 @@ public class StatusBar extends SystemUI implements DemoMode, }); } - mReportRejectedTouch = mStatusBarWindow.findViewById(R.id.report_rejected_touch); + mReportRejectedTouch = mNotificationShadeWindowView + .findViewById(R.id.report_rejected_touch); if (mReportRejectedTouch != null) { updateReportRejectedTouchVisibility(); mReportRejectedTouch.setOnClickListener(v -> { @@ -1227,18 +1238,18 @@ public class StatusBar extends SystemUI implements DemoMode, } protected QS createDefaultQSFragment() { - return FragmentHostManager.get(mStatusBarWindow).create(QSFragment.class); + return FragmentHostManager.get(mNotificationShadeWindowView).create(QSFragment.class); } private void setUpPresenter() { // Set up the initial notification state. mActivityLaunchAnimator = new ActivityLaunchAnimator( - mStatusBarWindowViewController, this, mNotificationPanelViewController, + mNotificationShadeWindowViewController, this, mNotificationPanelViewController, (NotificationListContainer) mStackScroller); // TODO: inject this. mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanelViewController, - mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController, + mHeadsUpManager, mNotificationShadeWindowView, mStackScroller, mDozeScrimController, mScrimController, mActivityLaunchAnimator, mDynamicPrivacyController, mNotificationAlertingManager, mNotificationRowBinder, mKeyguardStateController, mKeyguardIndicationController, @@ -1251,7 +1262,7 @@ public class StatusBar extends SystemUI implements DemoMode, mDeviceProvisionedController); mNotificationShelf.setOnActivatedListener(mPresenter); - mRemoteInputManager.getController().addCallback(mStatusBarWindowController); + mRemoteInputManager.getController().addCallback(mNotificationShadeWindowController); mNotificationActivityStarter = mStatusBarNotificationActivityStarterBuilder @@ -1328,7 +1339,7 @@ public class StatusBar extends SystemUI implements DemoMode, mShadeController.animateCollapsePanels(); } } - return mStatusBarWindow.onTouchEvent(event); + return mNotificationShadeWindowView.onTouchEvent(event); }; } @@ -1384,17 +1395,20 @@ public class StatusBar extends SystemUI implements DemoMode, protected void createUserSwitcher() { mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext, - mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), - mStatusBarWindow.findViewById(R.id.keyguard_header), + mNotificationShadeWindowView.findViewById(R.id.keyguard_user_switcher), + mNotificationShadeWindowView.findViewById(R.id.keyguard_header), mNotificationPanelViewController); } private void inflateStatusBarWindow() { - mStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView(); + mNotificationShadeWindowView = mSuperStatusBarViewFactory.getNotificationShadeWindowView(); StatusBarComponent statusBarComponent = mStatusBarComponentBuilder.get() - .statusBarWindowView(mStatusBarWindow).build(); - mStatusBarWindowViewController = statusBarComponent.getStatusBarWindowViewController(); - mStatusBarWindowViewController.setupExpandedStatusBar(); + .statusBarWindowView(mNotificationShadeWindowView).build(); + mNotificationShadeWindowViewController = statusBarComponent + .getNotificationShadeWindowViewController(); + mNotificationShadeWindowViewController.setupExpandedStatusBar(); + mStatusBarWindowController = statusBarComponent.getStatusBarWindowController(); + mPhoneStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView(); mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController(); } @@ -1404,7 +1418,8 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarKeyguardViewManager.registerStatusBar( /* statusBar= */ this, getBouncerContainer(), mNotificationPanelViewController, mBiometricUnlockController, - mDismissCallbackRegistry, mStatusBarWindow.findViewById(R.id.lock_icon_container), + mDismissCallbackRegistry, + mNotificationShadeWindowView.findViewById(R.id.lock_icon_container), mStackScroller, mKeyguardBypassController, mFalsingManager); mKeyguardIndicationController .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); @@ -1422,16 +1437,20 @@ public class StatusBar extends SystemUI implements DemoMode, return mStatusBarView; } + public NotificationShadeWindowView getNotificationShadeWindowView() { + return mNotificationShadeWindowView; + } + public StatusBarWindowView getStatusBarWindow() { - return mStatusBarWindow; + return mPhoneStatusBarWindow; } - public StatusBarWindowViewController getStatusBarWindowViewController() { - return mStatusBarWindowViewController; + public NotificationShadeWindowViewController getNotificationShadeWindowViewController() { + return mNotificationShadeWindowViewController; } protected ViewGroup getBouncerContainer() { - return mStatusBarWindow; + return mNotificationShadeWindowView; } public int getStatusBarHeight() { @@ -1641,7 +1660,7 @@ public class StatusBar extends SystemUI implements DemoMode, } public void setQsExpanded(boolean expanded) { - mStatusBarWindowController.setQsExpanded(expanded); + mNotificationShadeWindowController.setQsExpanded(expanded); mNotificationPanelViewController.setStatusAccessibilityImportance(expanded ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); @@ -1674,7 +1693,7 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) { if (inPinnedMode) { - mStatusBarWindowController.setHeadsUpShowing(true); + mNotificationShadeWindowController.setHeadsUpShowing(true); mStatusBarWindowController.setForceStatusBarVisible(true); if (mNotificationPanelViewController.isFullyCollapsed()) { // We need to ensure that the touchable region is updated before the window will be @@ -1682,9 +1701,9 @@ public class StatusBar extends SystemUI implements DemoMode, // onComputeInternalInsets will be called and after that we can resize the layout. Let's // make sure that the window stays small for one frame until the touchableRegion is set. mNotificationPanelViewController.getView().requestLayout(); - mStatusBarWindowController.setForceWindowCollapsed(true); + mNotificationShadeWindowController.setForceWindowCollapsed(true); mNotificationPanelViewController.getView().post(() -> { - mStatusBarWindowController.setForceWindowCollapsed(false); + mNotificationShadeWindowController.setForceWindowCollapsed(false); }); } } else { @@ -1694,7 +1713,7 @@ public class StatusBar extends SystemUI implements DemoMode, || mNotificationPanelViewController.isTracking() || bypassKeyguard) { // We are currently tracking or is open and the shade doesn't need to be kept // open artificially. - mStatusBarWindowController.setHeadsUpShowing(false); + mNotificationShadeWindowController.setHeadsUpShowing(false); if (bypassKeyguard) { mStatusBarWindowController.setForceStatusBarVisible(false); } @@ -1704,7 +1723,7 @@ public class StatusBar extends SystemUI implements DemoMode, mHeadsUpManager.setHeadsUpGoingAway(true); mNotificationPanelViewController.runAfterAnimationFinished(() -> { if (!mHeadsUpManager.hasPinnedHeadsUp()) { - mStatusBarWindowController.setHeadsUpShowing(false); + mNotificationShadeWindowController.setHeadsUpShowing(false); mHeadsUpManager.setHeadsUpGoingAway(false); } mRemoteInputManager.onPanelCollapsed(); @@ -1732,7 +1751,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void setPanelExpanded(boolean isExpanded) { mPanelExpanded = isExpanded; updateHideIconsForBouncer(false /* animate */); - mStatusBarWindowController.setPanelExpanded(isExpanded); + mNotificationShadeWindowController.setPanelExpanded(isExpanded); mVisualStabilityManager.setPanelExpanded(isExpanded); if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) { if (DEBUG) { @@ -1991,7 +2010,7 @@ public class StatusBar extends SystemUI implements DemoMode, // Expand the window to encompass the full screen in anticipation of the drag. // This is only possible to do atomically because the status bar is at the top of the screen! - mStatusBarWindowController.setPanelVisible(true); + mNotificationShadeWindowController.setPanelVisible(true); visibilityChanged(true); mCommandQueue.recomputeDisableFlags(mDisplayId, !force /* animate */); @@ -2100,7 +2119,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible + " mExpandedVisible=" + mExpandedVisible); - if (!mExpandedVisible || mStatusBarWindow == null) { + if (!mExpandedVisible || mNotificationShadeWindowView == null) { return; } @@ -2113,8 +2132,8 @@ public class StatusBar extends SystemUI implements DemoMode, mExpandedVisible = false; visibilityChanged(false); - // Shrink the window to the size of the status bar only - mStatusBarWindowController.setPanelVisible(false); + // Update the visibility of notification shade and status bar window. + mNotificationShadeWindowController.setPanelVisible(false); mStatusBarWindowController.setForceStatusBarVisible(false); // Close any guts that might be visible @@ -2178,6 +2197,10 @@ public class StatusBar extends SystemUI implements DemoMode, return false; } + boolean isSameStatusBarState(int state) { + return mStatusBarWindowState == state; + } + public GestureRecorder getGestureRecorder() { return mGestureRec; } @@ -2193,7 +2216,7 @@ public class StatusBar extends SystemUI implements DemoMode, return; } boolean showing = state == WINDOW_STATE_SHOWING; - if (mStatusBarWindow != null + if (mNotificationShadeWindowView != null && window == StatusBarManager.WINDOW_STATUS_BAR && mStatusBarWindowState != state) { mStatusBarWindowState = state; @@ -2427,8 +2450,8 @@ public class StatusBar extends SystemUI implements DemoMode, dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions()); } pw.println(" StatusBarWindowView: "); - if (mStatusBarWindowViewController != null) { - mStatusBarWindowViewController.dump(fd, pw, args); + if (mNotificationShadeWindowViewController != null) { + mNotificationShadeWindowViewController.dump(fd, pw, args); } pw.println(" mMediaManager: "); @@ -2527,6 +2550,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void createAndAddWindows(@Nullable RegisterStatusBarResult result) { makeStatusBarView(result); + mNotificationShadeWindowController.attach(); mStatusBarWindowController.attach(); } @@ -2690,8 +2714,8 @@ public class StatusBar extends SystemUI implements DemoMode, } } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { - if (mStatusBarWindowController != null) { - mStatusBarWindowController.setNotTouchable(false); + if (mNotificationShadeWindowController != null) { + mNotificationShadeWindowController.setNotTouchable(false); } if (mBubbleController.isStackExpanded()) { mBubbleController.collapseStack(); @@ -2808,7 +2832,9 @@ public class StatusBar extends SystemUI implements DemoMode, mQSPanel.updateResources(); } - mStatusBarWindowController.refreshStatusBarHeight(); + if (mStatusBarWindowController != null) { + mStatusBarWindowController.refreshStatusBarHeight(); + } if (mStatusBarView != null) { mStatusBarView.updateResources(); @@ -3518,7 +3544,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (!mPresenter.isPresenterFullyCollapsed()) { // if we set it not to be focusable when collapsing, we have to undo it when we aborted // the closing - mStatusBarWindowController.setStatusBarFocusable(true); + mNotificationShadeWindowController.setNotificationShadeFocusable(true); } } @@ -3631,7 +3657,7 @@ public class StatusBar extends SystemUI implements DemoMode, */ public void collapseShade() { if (mNotificationPanelViewController.isTracking()) { - mStatusBarWindowViewController.cancelCurrentTouch(); + mNotificationShadeWindowViewController.cancelCurrentTouch(); } if (mPanelExpanded && mState == StatusBarState.SHADE) { mShadeController.animateCollapsePanels(); @@ -3652,7 +3678,7 @@ public class StatusBar extends SystemUI implements DemoMode, updateVisibleToUser(); updateNotificationPanelTouchState(); - mStatusBarWindowViewController.cancelCurrentTouch(); + mNotificationShadeWindowViewController.cancelCurrentTouch(); if (mLaunchCameraOnFinishedGoingToSleep) { mLaunchCameraOnFinishedGoingToSleep = false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 407d25691798..de37cd955f9a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -92,7 +92,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private static String TAG = "StatusBarKeyguardViewManager"; protected final Context mContext; - private final StatusBarWindowController mStatusBarWindowController; + private final NotificationShadeWindowController mNotificationShadeWindowController; private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() { @Override public void onFullyShown() { @@ -199,13 +199,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb KeyguardUpdateMonitor keyguardUpdateMonitor, NavigationModeController navigationModeController, DockManager dockManager, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, NotificationMediaManager notificationMediaManager) { mContext = context; mViewMediatorCallback = callback; mLockPatternUtils = lockPatternUtils; - mStatusBarWindowController = statusBarWindowController; + mNotificationShadeWindowController = notificationShadeWindowController; mKeyguardStateController = keyguardStateController; mMediaManager = notificationMediaManager; mKeyguardUpdateManager = keyguardUpdateMonitor; @@ -315,7 +315,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb */ public void show(Bundle options) { mShowing = true; - mStatusBarWindowController.setKeyguardShowing(true); + mNotificationShadeWindowController.setKeyguardShowing(true); mKeyguardStateController.notifyKeyguardState(mShowing, mKeyguardStateController.isOccluded()); reset(true /* hideBouncerWhenShowing */); @@ -491,11 +491,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } public void setNeedsInput(boolean needsInput) { - mStatusBarWindowController.setKeyguardNeedsInput(needsInput); + mNotificationShadeWindowController.setKeyguardNeedsInput(needsInput); } public boolean isUnlockWithWallpaper() { - return mStatusBarWindowController.isShowingWallpaper(); + return mNotificationShadeWindowController.isShowingWallpaper(); } public void setOccluded(boolean occluded, boolean animate) { @@ -509,7 +509,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb new Runnable() { @Override public void run() { - mStatusBarWindowController.setKeyguardOccluded(mOccluded); + mNotificationShadeWindowController.setKeyguardOccluded(mOccluded); reset(true /* hideBouncerWhenShowing */); } }); @@ -524,7 +524,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (mShowing) { mMediaManager.updateMediaMetaData(false, animate && !occluded); } - mStatusBarWindowController.setKeyguardOccluded(occluded); + mNotificationShadeWindowController.setKeyguardOccluded(occluded); // setDozing(false) will call reset once we stop dozing. if (!mDozing) { @@ -578,8 +578,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() { @Override public void run() { - mStatusBarWindowController.setKeyguardShowing(false); - mStatusBarWindowController.setKeyguardFadingAway(true); + mNotificationShadeWindowController.setKeyguardShowing(false); + mNotificationShadeWindowController.setKeyguardFadingAway(true); hideBouncer(true /* destroyView */); updateStates(); } @@ -587,7 +587,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void run() { mStatusBar.hideKeyguard(); - mStatusBarWindowController.setKeyguardFadingAway(false); + mNotificationShadeWindowController.setKeyguardFadingAway(false); mViewMediatorCallback.keyguardGone(); executeAfterKeyguardGoneAction(); } @@ -624,7 +624,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } else { boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); if (!staying) { - mStatusBarWindowController.setKeyguardFadingAway(true); + mNotificationShadeWindowController.setKeyguardFadingAway(true); if (needsFading) { ViewGroupFadeHelper.fadeOutAllChildrenExcept( mNotificationPanelViewController.getView(), @@ -650,7 +650,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } updateLockIcon(); updateStates(); - mStatusBarWindowController.setKeyguardShowing(false); + mNotificationShadeWindowController.setKeyguardShowing(false); mViewMediatorCallback.keyguardGone(); } StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED, @@ -684,8 +684,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } public void onKeyguardFadedAway() { - mContainer.postDelayed(() -> mStatusBarWindowController.setKeyguardFadingAway(false), - 100); + mContainer.postDelayed(() -> mNotificationShadeWindowController + .setKeyguardFadingAway(false), 100); ViewGroupFadeHelper.reset(mNotificationPanelViewController.getView()); mStatusBar.finishKeyguardFadingAway(); mBiometricUnlockController.finishKeyguardFadingAway(); @@ -818,7 +818,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) { - mStatusBarWindowController.setBouncerShowing(bouncerShowing); + mNotificationShadeWindowController.setBouncerShowing(bouncerShowing); mStatusBar.setBouncerShowing(bouncerShowing); updateLockIcon(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java index b4d5dadda5b8..7615bf826287 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java @@ -151,7 +151,7 @@ public class StatusBarModule { Lazy<AssistManager> assistManagerLazy, NotificationListener notificationListener, ConfigurationController configurationController, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, LockscreenLockIconController lockscreenLockIconController, DozeParameters dozeParameters, ScrimController scrimController, @@ -233,7 +233,7 @@ public class StatusBarModule { assistManagerLazy, notificationListener, configurationController, - statusBarWindowController, + notificationShadeWindowController, lockscreenLockIconController, dozeParameters, scrimController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java index 720f22964915..1336b2de82d3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java @@ -134,7 +134,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter, public StatusBarNotificationPresenter(Context context, NotificationPanelViewController panel, HeadsUpManagerPhone headsUp, - StatusBarWindowView statusBarWindow, + NotificationShadeWindowView statusBarWindow, ViewGroup stackScroller, DozeScrimController dozeScrimController, ScrimController scrimController, @@ -191,7 +191,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter, Dependency.get(NotificationRemoteInputManager.Callback.class), mNotificationPanel.createRemoteInputDelegate()); remoteInputManager.getController().addCallback( - Dependency.get(StatusBarWindowController.class)); + Dependency.get(NotificationShadeWindowController.class)); NotificationListContainer notifListContainer = (NotificationListContainer) stackScroller; initController.addPostInitTask(() -> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java index 3d25749265f1..b8fb6d3ebacf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java @@ -17,15 +17,13 @@ package com.android.systemui.statusbar.phone; import android.annotation.NonNull; -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.Rect; import android.view.View; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; import com.android.systemui.Dependency; +import com.android.systemui.R; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; @@ -38,60 +36,62 @@ public final class StatusBarTouchableRegionManager implements OnComputeInternalInsetsListener, ConfigurationListener { private final BubbleController mBubbleController = Dependency.get(BubbleController.class); - private final Context mContext; private final HeadsUpManagerPhone mHeadsUpManager; private boolean mIsStatusBarExpanded = false; private boolean mShouldAdjustInsets = false; private final StatusBar mStatusBar; - private int mStatusBarHeight; - private final View mStatusBarWindowView; + private final View mNotificationShadeWindowView; + private View mNotificationPanelView; private boolean mForceCollapsedUntilLayout = false; - private final StatusBarWindowController mStatusBarWindowController; + private final NotificationShadeWindowController mNotificationShadeWindowController; - public StatusBarTouchableRegionManager(@NonNull Context context, - HeadsUpManagerPhone headsUpManager, + public StatusBarTouchableRegionManager(HeadsUpManagerPhone headsUpManager, @NonNull StatusBar statusBar, - @NonNull View statusBarWindowView) { - mContext = context; + @NonNull View notificationShadeWindowView) { mHeadsUpManager = headsUpManager; mStatusBar = statusBar; - mStatusBarWindowView = statusBarWindowView; - mStatusBarWindowController = Dependency.get(StatusBarWindowController.class); - - initResources(); + mNotificationShadeWindowView = notificationShadeWindowView; + mNotificationShadeWindowController = + Dependency.get(NotificationShadeWindowController.class); mBubbleController.setBubbleStateChangeListener((hasBubbles) -> { updateTouchableRegion(); }); - mStatusBarWindowController.setForcePluginOpenListener((forceOpen) -> { + mNotificationShadeWindowController.setForcePluginOpenListener((forceOpen) -> { updateTouchableRegion(); }); Dependency.get(ConfigurationController.class).addCallback(this); + if (mNotificationShadeWindowView != null) { + mNotificationPanelView = mNotificationShadeWindowView.findViewById( + R.id.notification_panel); + } } /** * Set the touchable portion of the status bar based on what elements are visible. */ public void updateTouchableRegion() { - boolean hasCutoutInset = (mStatusBarWindowView != null) - && (mStatusBarWindowView.getRootWindowInsets() != null) - && (mStatusBarWindowView.getRootWindowInsets().getDisplayCutout() != null); + boolean hasCutoutInset = (mNotificationShadeWindowView != null) + && (mNotificationShadeWindowView.getRootWindowInsets() != null) + && (mNotificationShadeWindowView.getRootWindowInsets().getDisplayCutout() != null); boolean shouldObserve = mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpManager.isHeadsUpGoingAway() || mBubbleController.hasBubbles() || mForceCollapsedUntilLayout || hasCutoutInset - || mStatusBarWindowController.getForcePluginOpen(); + || mNotificationShadeWindowController.getForcePluginOpen(); if (shouldObserve == mShouldAdjustInsets) { return; } if (shouldObserve) { - mStatusBarWindowView.getViewTreeObserver().addOnComputeInternalInsetsListener(this); - mStatusBarWindowView.requestLayout(); + mNotificationShadeWindowView.getViewTreeObserver() + .addOnComputeInternalInsetsListener(this); + mNotificationShadeWindowView.requestLayout(); } else { - mStatusBarWindowView.getViewTreeObserver().removeOnComputeInternalInsetsListener(this); + mNotificationShadeWindowView.getViewTreeObserver() + .removeOnComputeInternalInsetsListener(this); } mShouldAdjustInsets = shouldObserve; } @@ -100,19 +100,20 @@ public final class StatusBarTouchableRegionManager implements * Calls {@code updateTouchableRegion()} after a layout pass completes. */ public void updateTouchableRegionAfterLayout() { - mForceCollapsedUntilLayout = true; - mStatusBarWindowView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, - int oldTop, int oldRight, int oldBottom) { - if (mStatusBarWindowView.getHeight() <= mStatusBarHeight) { - mStatusBarWindowView.removeOnLayoutChangeListener(this); - mForceCollapsedUntilLayout = false; - updateTouchableRegion(); + if (mNotificationPanelView != null) { + mForceCollapsedUntilLayout = true; + mNotificationPanelView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (!mNotificationPanelView.isVisibleToUser()) { + mNotificationPanelView.removeOnLayoutChangeListener(this); + mForceCollapsedUntilLayout = false; + updateTouchableRegion(); + } } - } - }); + }); + } } /** @@ -145,25 +146,4 @@ public final class StatusBarTouchableRegionManager implements info.touchableRegion.union(bubbleRect); } } - - @Override - public void onConfigChanged(Configuration newConfig) { - initResources(); - } - - @Override - public void onDensityOrFontScaleChanged() { - initResources(); - } - - @Override - public void onOverlayChanged() { - initResources(); - } - - private void initResources() { - Resources resources = mContext.getResources(); - mStatusBarHeight = resources.getDimensionPixelSize( - com.android.internal.R.dimen.status_bar_height); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java index ce498a39d941..7cf5147a9f26 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * 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. @@ -11,55 +11,25 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ package com.android.systemui.statusbar.phone; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; -import static com.android.systemui.DejankUtils.whitelistIpcs; -import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; - -import android.app.IActivityManager; import android.content.Context; -import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.graphics.PixelFormat; import android.os.Binder; -import android.os.RemoteException; -import android.os.SystemProperties; -import android.os.Trace; import android.util.Log; -import android.view.Display; import android.view.Gravity; -import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; -import android.view.WindowManager.LayoutParams; -import com.android.systemui.Dumpable; -import com.android.systemui.R; -import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; -import com.android.systemui.statusbar.RemoteInputController.Callback; -import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SuperStatusBarViewFactory; -import com.android.systemui.statusbar.SysuiStatusBarStateController; -import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; - -import com.google.android.collect.Lists; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; import javax.inject.Inject; import javax.inject.Singleton; @@ -68,101 +38,36 @@ import javax.inject.Singleton; * Encapsulates all logic for the status bar window state management. */ @Singleton -public class StatusBarWindowController implements Callback, Dumpable, ConfigurationListener { - +public class StatusBarWindowController { private static final String TAG = "StatusBarWindowController"; private static final boolean DEBUG = false; private final Context mContext; private final WindowManager mWindowManager; - private final IActivityManager mActivityManager; - private final DozeParameters mDozeParameters; - private final LayoutParams mLpChanged; - private final boolean mKeyguardScreenRotation; - private final long mLockScreenDisplayTimeout; - private final Display.Mode mKeyguardDisplayMode; - private final KeyguardBypassController mKeyguardBypassController; - private ViewGroup mStatusBarView; - private LayoutParams mLp; - private boolean mHasTopUi; - private boolean mHasTopUiChanged; + private final SuperStatusBarViewFactory mSuperStatusBarViewFactory; + private final Resources mResources; private int mBarHeight = -1; - private float mScreenBrightnessDoze; private final State mCurrentState = new State(); - private OtherwisedCollapsedListener mListener; - private ForcePluginOpenListener mForcePluginOpenListener; - private final ArrayList<WeakReference<StatusBarWindowCallback>> - mCallbacks = Lists.newArrayList(); - private final SysuiColorExtractor mColorExtractor; - private final SuperStatusBarViewFactory mSuperStatusBarViewFactory; - private final Resources mResources; + private ViewGroup mStatusBarView; + private WindowManager.LayoutParams mLp; + private final WindowManager.LayoutParams mLpChanged; @Inject public StatusBarWindowController(Context context, WindowManager windowManager, - IActivityManager activityManager, DozeParameters dozeParameters, - StatusBarStateController statusBarStateController, - ConfigurationController configurationController, - KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor, SuperStatusBarViewFactory superStatusBarViewFactory, @Main Resources resources) { mContext = context; mWindowManager = windowManager; - mActivityManager = activityManager; - mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation(); - mDozeParameters = dozeParameters; - mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze(); - mLpChanged = new LayoutParams(); - mKeyguardBypassController = keyguardBypassController; - mColorExtractor = colorExtractor; mSuperStatusBarViewFactory = superStatusBarViewFactory; mStatusBarView = mSuperStatusBarViewFactory.getStatusBarWindowView(); + mLpChanged = new WindowManager.LayoutParams(); mResources = resources; if (mBarHeight < 0) { mBarHeight = mResources.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); } - - mLockScreenDisplayTimeout = context.getResources() - .getInteger(R.integer.config_lockScreenDisplayTimeout); - ((SysuiStatusBarStateController) statusBarStateController) - .addCallback(mStateListener, - SysuiStatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER); - configurationController.addCallback(this); - - Display.Mode[] supportedModes = context.getDisplay().getSupportedModes(); - Display.Mode currentMode = context.getDisplay().getMode(); - // Running on the highest frame rate available can be expensive. - // Let's specify a preferred refresh rate, and allow higher FPS only when we - // know that we're not falsing (because we unlocked.) - int keyguardRefreshRate = context.getResources() - .getInteger(R.integer.config_keyguardRefreshRate); - // Find supported display mode with the same resolution and requested refresh rate. - mKeyguardDisplayMode = Arrays.stream(supportedModes).filter(mode -> - (int) mode.getRefreshRate() == keyguardRefreshRate - && mode.getPhysicalWidth() == currentMode.getPhysicalWidth() - && mode.getPhysicalHeight() == currentMode.getPhysicalHeight()) - .findFirst().orElse(null); - } - - /** - * Register to receive notifications about status bar window state changes. - */ - public void registerCallback(StatusBarWindowCallback callback) { - // Prevent adding duplicate callbacks - for (int i = 0; i < mCallbacks.size(); i++) { - if (mCallbacks.get(i).get() == callback) { - return; - } - } - mCallbacks.add(new WeakReference<StatusBarWindowCallback>(callback)); - } - - private boolean shouldEnableKeyguardScreenRotation() { - Resources res = mContext.getResources(); - return SystemProperties.getBoolean("lockscreen.rot_override", false) - || res.getBoolean(R.bool.config_enableLockScreenRotation); } public int getStatusBarHeight() { @@ -192,574 +97,46 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat // Now that the status bar window encompasses the sliding panel and its // translucent backdrop, the entire thing is made TRANSLUCENT and is // hardware-accelerated. - mLp = new LayoutParams( + mLp = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, mBarHeight, - LayoutParams.TYPE_STATUS_BAR, - LayoutParams.FLAG_NOT_FOCUSABLE - | LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING - | LayoutParams.FLAG_SPLIT_TOUCH - | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, + WindowManager.LayoutParams.TYPE_STATUS_BAR, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH + | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, PixelFormat.TRANSLUCENT); mLp.token = new Binder(); mLp.gravity = Gravity.TOP; - mLp.setFitWindowInsetsTypes(0 /* types */); - mLp.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE; mLp.setTitle("StatusBar"); mLp.packageName = mContext.getPackageName(); mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + mWindowManager.addView(mStatusBarView, mLp); mLpChanged.copyFrom(mLp); - onThemeChanged(); - } - - public ViewGroup getStatusBarView() { - return mStatusBarView; - } - - public void setDozeScreenBrightness(int value) { - mScreenBrightnessDoze = value / 255f; - } - - private void setKeyguardDark(boolean dark) { - int vis = mStatusBarView.getSystemUiVisibility(); - if (dark) { - vis = vis | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; - vis = vis | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; - } else { - vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; - vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; - } - mStatusBarView.setSystemUiVisibility(vis); - } - - private void applyKeyguardFlags(State state) { - if (state.keyguardShowing) { - mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_KEYGUARD; - } else { - mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_KEYGUARD; - } - - final boolean scrimsOccludingWallpaper = - state.scrimsVisibility == ScrimController.OPAQUE; - final boolean keyguardOrAod = state.keyguardShowing - || (state.dozing && mDozeParameters.getAlwaysOn()); - if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) { - mLpChanged.flags |= LayoutParams.FLAG_SHOW_WALLPAPER; - } else { - mLpChanged.flags &= ~LayoutParams.FLAG_SHOW_WALLPAPER; - } - - if (state.dozing) { - mLpChanged.privateFlags |= LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; - } else { - mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; - } - - if (mKeyguardDisplayMode != null) { - boolean bypassOnKeyguard = mKeyguardBypassController.getBypassEnabled() - && state.statusBarState == StatusBarState.KEYGUARD && !state.keyguardFadingAway - && !state.keyguardGoingAway; - if (state.dozing || bypassOnKeyguard) { - mLpChanged.preferredDisplayModeId = mKeyguardDisplayMode.getModeId(); - } else { - mLpChanged.preferredDisplayModeId = 0; - } - Trace.setCounter("display_mode_id", mLpChanged.preferredDisplayModeId); - } - } - - private void adjustScreenOrientation(State state) { - if (state.isKeyguardShowingAndNotOccluded() || state.dozing) { - if (mKeyguardScreenRotation) { - mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER; - } else { - mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; - } - } else { - mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - } - } - - private void applyFocusableFlag(State state) { - boolean panelFocusable = state.statusBarFocusable && state.panelExpanded; - if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput) - || ENABLE_REMOTE_INPUT && state.remoteInputActive - || state.bubbleExpanded) { - mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE; - mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM; - } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) { - mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE; - mLpChanged.flags |= LayoutParams.FLAG_ALT_FOCUSABLE_IM; - } else { - mLpChanged.flags |= LayoutParams.FLAG_NOT_FOCUSABLE; - mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM; - } - - mLpChanged.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE; - } - - private void applyForceShowNavigationFlag(State state) { - if (state.panelExpanded || state.bouncerShowing - || ENABLE_REMOTE_INPUT && state.remoteInputActive) { - mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; - } else { - mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; - } - } - - private void applyHeight(State state) { - boolean expanded = isExpanded(state); - if (state.forcePluginOpen) { - if (mListener != null) { - mListener.setWouldOtherwiseCollapse(expanded); - } - expanded = true; - } - if (expanded) { - mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT; - } else { - mLpChanged.height = mBarHeight; - } - } - - private boolean isExpanded(State state) { - return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded() - || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing - || state.headsUpShowing || state.bubblesShowing - || state.scrimsVisibility != ScrimController.TRANSPARENT); } - private void applyFitsSystemWindows(State state) { - boolean fitsSystemWindows = !state.isKeyguardShowingAndNotOccluded(); - if (mStatusBarView != null && mStatusBarView.getFitsSystemWindows() != fitsSystemWindows) { - mStatusBarView.setFitsSystemWindows(fitsSystemWindows); - mStatusBarView.requestApplyInsets(); - } - } - - private void applyUserActivityTimeout(State state) { - if (state.isKeyguardShowingAndNotOccluded() - && state.statusBarState == StatusBarState.KEYGUARD - && !state.qsExpanded) { - mLpChanged.userActivityTimeout = state.bouncerShowing - ? KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS : mLockScreenDisplayTimeout; - } else { - mLpChanged.userActivityTimeout = -1; - } - } - - private void applyInputFeatures(State state) { - if (state.isKeyguardShowingAndNotOccluded() - && state.statusBarState == StatusBarState.KEYGUARD - && !state.qsExpanded && !state.forceUserActivity) { - mLpChanged.inputFeatures |= - LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; - } else { - mLpChanged.inputFeatures &= - ~LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; - } - } - - private void applyStatusBarColorSpaceAgnosticFlag(State state) { - if (!isExpanded(state)) { - mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC; - } else { - mLpChanged.privateFlags &= - ~LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC; - } + /** Set force status bar visible. */ + public void setForceStatusBarVisible(boolean forceStatusBarVisible) { + mCurrentState.mForceStatusBarVisible = forceStatusBarVisible; + apply(mCurrentState); } private void apply(State state) { - applyKeyguardFlags(state); applyForceStatusBarVisibleFlag(state); - applyFocusableFlag(state); - applyForceShowNavigationFlag(state); - adjustScreenOrientation(state); - applyHeight(state); - applyUserActivityTimeout(state); - applyInputFeatures(state); - applyFitsSystemWindows(state); - applyModalFlag(state); - applyBrightness(state); - applyHasTopUi(state); - applyNotTouchable(state); - applyStatusBarColorSpaceAgnosticFlag(state); if (mLp != null && mLp.copyFrom(mLpChanged) != 0) { mWindowManager.updateViewLayout(mStatusBarView, mLp); } - if (mHasTopUi != mHasTopUiChanged) { - whitelistIpcs(() -> { - try { - mActivityManager.setHasTopUi(mHasTopUiChanged); - } catch (RemoteException e) { - Log.e(TAG, "Failed to call setHasTopUi", e); - } - mHasTopUi = mHasTopUiChanged; - }); - } - notifyStateChangedCallbacks(); } - public void notifyStateChangedCallbacks() { - for (int i = 0; i < mCallbacks.size(); i++) { - StatusBarWindowCallback cb = mCallbacks.get(i).get(); - if (cb != null) { - cb.onStateChanged(mCurrentState.keyguardShowing, - mCurrentState.keyguardOccluded, - mCurrentState.bouncerShowing); - } - } + private static class State { + boolean mForceStatusBarVisible; } private void applyForceStatusBarVisibleFlag(State state) { - if (state.forceStatusBarVisible || state.forcePluginOpen) { - mLpChanged.privateFlags |= WindowManager - .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; - } else { - mLpChanged.privateFlags - &= ~LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; - } - } - - private void applyModalFlag(State state) { - if (state.headsUpShowing) { - mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCH_MODAL; + if (state.mForceStatusBarVisible) { + mLpChanged.privateFlags |= PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; } else { - mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCH_MODAL; - } - } - - private void applyBrightness(State state) { - if (state.forceDozeBrightness) { - mLpChanged.screenBrightness = mScreenBrightnessDoze; - } else { - mLpChanged.screenBrightness = LayoutParams.BRIGHTNESS_OVERRIDE_NONE; - } - } - - private void applyHasTopUi(State state) { - mHasTopUiChanged = state.forceHasTopUi || isExpanded(state); - } - - private void applyNotTouchable(State state) { - if (state.notTouchable) { - mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCHABLE; - } else { - mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCHABLE; - } - } - - public void setKeyguardShowing(boolean showing) { - mCurrentState.keyguardShowing = showing; - apply(mCurrentState); - } - - public void setKeyguardOccluded(boolean occluded) { - mCurrentState.keyguardOccluded = occluded; - apply(mCurrentState); - } - - public void setKeyguardNeedsInput(boolean needsInput) { - mCurrentState.keyguardNeedsInput = needsInput; - apply(mCurrentState); - } - - public void setPanelVisible(boolean visible) { - mCurrentState.panelVisible = visible; - mCurrentState.statusBarFocusable = visible; - apply(mCurrentState); - } - - public void setStatusBarFocusable(boolean focusable) { - mCurrentState.statusBarFocusable = focusable; - apply(mCurrentState); - } - - public void setBouncerShowing(boolean showing) { - mCurrentState.bouncerShowing = showing; - apply(mCurrentState); - } - - public void setBackdropShowing(boolean showing) { - mCurrentState.backdropShowing = showing; - apply(mCurrentState); - } - - public void setKeyguardFadingAway(boolean keyguardFadingAway) { - mCurrentState.keyguardFadingAway = keyguardFadingAway; - apply(mCurrentState); - } - - public void setQsExpanded(boolean expanded) { - mCurrentState.qsExpanded = expanded; - apply(mCurrentState); - } - - public void setForceUserActivity(boolean forceUserActivity) { - mCurrentState.forceUserActivity = forceUserActivity; - apply(mCurrentState); - } - - public void setScrimsVisibility(int scrimsVisibility) { - mCurrentState.scrimsVisibility = scrimsVisibility; - apply(mCurrentState); - } - - public void setHeadsUpShowing(boolean showing) { - mCurrentState.headsUpShowing = showing; - apply(mCurrentState); - } - - public void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) { - mCurrentState.wallpaperSupportsAmbientMode = supportsAmbientMode; - apply(mCurrentState); - } - - /** - * @param state The {@link StatusBarStateController} of the status bar. - */ - private void setStatusBarState(int state) { - mCurrentState.statusBarState = state; - apply(mCurrentState); - } - - public void setForceStatusBarVisible(boolean forceStatusBarVisible) { - mCurrentState.forceStatusBarVisible = forceStatusBarVisible; - apply(mCurrentState); - } - - /** - * Force the window to be collapsed, even if it should theoretically be expanded. - * Used for when a heads-up comes in but we still need to wait for the touchable regions to - * be computed. - */ - public void setForceWindowCollapsed(boolean force) { - mCurrentState.forceCollapsed = force; - apply(mCurrentState); - } - - public void setPanelExpanded(boolean isExpanded) { - mCurrentState.panelExpanded = isExpanded; - apply(mCurrentState); - } - - @Override - public void onRemoteInputActive(boolean remoteInputActive) { - mCurrentState.remoteInputActive = remoteInputActive; - apply(mCurrentState); - } - - /** - * Set whether the screen brightness is forced to the value we use for doze mode by the status - * bar window. - */ - public void setForceDozeBrightness(boolean forceDozeBrightness) { - mCurrentState.forceDozeBrightness = forceDozeBrightness; - apply(mCurrentState); - } - - public void setDozing(boolean dozing) { - mCurrentState.dozing = dozing; - apply(mCurrentState); - } - - public void setForcePluginOpen(boolean forcePluginOpen) { - mCurrentState.forcePluginOpen = forcePluginOpen; - apply(mCurrentState); - if (mForcePluginOpenListener != null) { - mForcePluginOpenListener.onChange(forcePluginOpen); + mLpChanged.privateFlags &= ~PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; } } - - /** - * The forcePluginOpen state for the status bar. - */ - public boolean getForcePluginOpen() { - return mCurrentState.forcePluginOpen; - } - - public void setNotTouchable(boolean notTouchable) { - mCurrentState.notTouchable = notTouchable; - apply(mCurrentState); - } - - /** - * Sets whether there are bubbles showing on the screen. - */ - public void setBubblesShowing(boolean bubblesShowing) { - mCurrentState.bubblesShowing = bubblesShowing; - apply(mCurrentState); - } - - /** - * The bubbles showing state for the status bar. - */ - public boolean getBubblesShowing() { - return mCurrentState.bubblesShowing; - } - - /** - * Sets if there is a bubble being expanded on the screen. - */ - public void setBubbleExpanded(boolean bubbleExpanded) { - mCurrentState.bubbleExpanded = bubbleExpanded; - apply(mCurrentState); - } - - /** - * Whether the bubble is shown in expanded state for the status bar. - */ - public boolean getBubbleExpanded() { - return mCurrentState.bubbleExpanded; - } - - /** - * Whether the status bar panel is expanded or not. - */ - public boolean getPanelExpanded() { - return mCurrentState.panelExpanded; - } - - public void setStateListener(OtherwisedCollapsedListener listener) { - mListener = listener; - } - - public void setForcePluginOpenListener(ForcePluginOpenListener listener) { - mForcePluginOpenListener = listener; - } - - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("StatusBarWindowController:"); - pw.println(" mKeyguardDisplayMode=" + mKeyguardDisplayMode); - pw.println(mCurrentState); - } - - public boolean isShowingWallpaper() { - return !mCurrentState.backdropShowing; - } - - @Override - public void onThemeChanged() { - if (mStatusBarView == null) { - return; - } - - final boolean useDarkText = mColorExtractor.getNeutralColors().supportsDarkText(); - // Make sure we have the correct navbar/statusbar colors. - setKeyguardDark(useDarkText); - } - - /** - * When keyguard will be dismissed but didn't start animation yet. - */ - public void setKeyguardGoingAway(boolean goingAway) { - mCurrentState.keyguardGoingAway = goingAway; - apply(mCurrentState); - } - - public boolean getForceHasTopUi() { - return mCurrentState.forceHasTopUi; - } - - public void setForceHasTopUi(boolean forceHasTopUi) { - mCurrentState.forceHasTopUi = forceHasTopUi; - apply(mCurrentState); - } - - private static class State { - boolean keyguardShowing; - boolean keyguardOccluded; - boolean keyguardNeedsInput; - boolean panelVisible; - boolean panelExpanded; - boolean statusBarFocusable; - boolean bouncerShowing; - boolean keyguardFadingAway; - boolean keyguardGoingAway; - boolean qsExpanded; - boolean headsUpShowing; - boolean forceStatusBarVisible; - boolean forceCollapsed; - boolean forceDozeBrightness; - boolean forceUserActivity; - boolean backdropShowing; - boolean wallpaperSupportsAmbientMode; - boolean notTouchable; - boolean bubblesShowing; - boolean bubbleExpanded; - boolean forceHasTopUi; - - /** - * The {@link StatusBar} state from the status bar. - */ - int statusBarState; - - boolean remoteInputActive; - boolean forcePluginOpen; - boolean dozing; - int scrimsVisibility; - - private boolean isKeyguardShowingAndNotOccluded() { - return keyguardShowing && !keyguardOccluded; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - String newLine = "\n"; - result.append("Window State {"); - result.append(newLine); - - Field[] fields = this.getClass().getDeclaredFields(); - - // Print field names paired with their values - for (Field field : fields) { - result.append(" "); - try { - result.append(field.getName()); - result.append(": "); - //requires access to private field: - result.append(field.get(this)); - } catch (IllegalAccessException ex) { - } - result.append(newLine); - } - result.append("}"); - - return result.toString(); - } - } - - private final StateListener mStateListener = new StateListener() { - @Override - public void onStateChanged(int newState) { - setStatusBarState(newState); - } - - @Override - public void onDozingChanged(boolean isDozing) { - setDozing(isDozing); - } - }; - - /** - * Custom listener to pipe data back to plugins about whether or not the status bar would be - * collapsed if not for the plugin. - * TODO: Find cleaner way to do this. - */ - public interface OtherwisedCollapsedListener { - void setWouldOtherwiseCollapse(boolean otherwiseCollapse); - } - - /** - * Listener to indicate forcePluginOpen has changed - */ - public interface ForcePluginOpenListener { - /** - * Called when mState.forcePluginOpen is changed - */ - void onChange(boolean forceOpen); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 1e3c5d608bf8..da5df6a72961 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * 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. @@ -16,599 +16,19 @@ package com.android.systemui.statusbar.phone; -import android.annotation.ColorInt; -import android.annotation.DrawableRes; -import android.annotation.LayoutRes; import android.content.Context; -import android.content.res.Configuration; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Insets; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; import android.util.AttributeSet; -import android.view.ActionMode; -import android.view.DisplayCutout; -import android.view.InputQueue; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.Window; -import android.view.WindowInsets; -import android.view.WindowInsetsController; import android.widget.FrameLayout; -import com.android.internal.view.FloatingActionMode; -import com.android.internal.widget.FloatingToolbar; -import com.android.systemui.R; - /** - * Combined status bar and notification panel view. Also holding backdrop and scrims. + * Status bar view. */ public class StatusBarWindowView extends FrameLayout { - public static final String TAG = "StatusBarWindowView"; - public static final boolean DEBUG = StatusBar.DEBUG; - - private int mRightInset = 0; - private int mLeftInset = 0; - - // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by - // DecorView, but since this is a special window we have to roll our own. - private View mFloatingActionModeOriginatingView; - private ActionMode mFloatingActionMode; - private FloatingToolbar mFloatingToolbar; - private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener; - private InteractionEventHandler mInteractionEventHandler; + public static final String TAG = "PhoneStatusBarWindowView"; + public static final boolean DEBUG = StatusBar.DEBUG; public StatusBarWindowView(Context context, AttributeSet attrs) { super(context, attrs); - setMotionEventSplittingEnabled(false); - } - - public NotificationPanelView getNotificationPanelView() { - return findViewById(R.id.notification_panel); - } - - @Override - public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) { - final Insets insets = windowInsets.getMaxInsets(WindowInsets.Type.systemBars()); - if (getFitsSystemWindows()) { - boolean paddingChanged = insets.top != getPaddingTop() - || insets.bottom != getPaddingBottom(); - - int rightCutout = 0; - int leftCutout = 0; - DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout(); - if (displayCutout != null) { - leftCutout = displayCutout.getSafeInsetLeft(); - rightCutout = displayCutout.getSafeInsetRight(); - } - - int targetLeft = Math.max(insets.left, leftCutout); - int targetRight = Math.max(insets.right, rightCutout); - - // Super-special right inset handling, because scrims and backdrop need to ignore it. - if (targetRight != mRightInset || targetLeft != mLeftInset) { - mRightInset = targetRight; - mLeftInset = targetLeft; - applyMargins(); - } - // Drop top inset, and pass through bottom inset. - if (paddingChanged) { - setPadding(0, 0, 0, 0); - } - } else { - if (mRightInset != 0 || mLeftInset != 0) { - mRightInset = 0; - mLeftInset = 0; - applyMargins(); - } - boolean changed = getPaddingLeft() != 0 - || getPaddingRight() != 0 - || getPaddingTop() != 0 - || getPaddingBottom() != 0; - if (changed) { - setPadding(0, 0, 0, 0); - } - } - return windowInsets; - } - - private void applyMargins() { - final int N = getChildCount(); - for (int i = 0; i < N; i++) { - View child = getChildAt(i); - if (child.getLayoutParams() instanceof LayoutParams) { - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if (!lp.ignoreRightInset - && (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset)) { - lp.rightMargin = mRightInset; - lp.leftMargin = mLeftInset; - child.requestLayout(); - } - } - } - } - - @Override - public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(getContext(), attrs); - } - - @Override - protected FrameLayout.LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - } - - @Override - protected void onAttachedToWindow () { - super.onAttachedToWindow(); - setWillNotDraw(!DEBUG); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (mInteractionEventHandler.interceptMediaKey(event)) { - return true; - } - - if (super.dispatchKeyEvent(event)) { - return true; - } - - return mInteractionEventHandler.dispatchKeyEvent(event); - } - - protected void setInteractionEventHandler(InteractionEventHandler listener) { - mInteractionEventHandler = listener; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - Boolean result = mInteractionEventHandler.handleDispatchTouchEvent(ev); - - return result != null ? result : super.dispatchTouchEvent(ev); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - boolean intercept = mInteractionEventHandler.shouldInterceptTouchEvent(ev); - if (!intercept) { - intercept = super.onInterceptTouchEvent(ev); - } - if (intercept) { - mInteractionEventHandler.didIntercept(ev); - } - - return intercept; } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - boolean handled = mInteractionEventHandler.handleTouchEvent(ev); - - if (!handled) { - handled = super.onTouchEvent(ev); - } - - if (!handled) { - mInteractionEventHandler.didNotHandleTouchEvent(ev); - } - - return handled; - } - - @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (DEBUG) { - Paint pt = new Paint(); - pt.setColor(0x80FFFF00); - pt.setStrokeWidth(12.0f); - pt.setStyle(Paint.Style.STROKE); - canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt); - } - } - - public class LayoutParams extends FrameLayout.LayoutParams { - - public boolean ignoreRightInset; - - public LayoutParams(int width, int height) { - super(width, height); - } - - public LayoutParams(Context c, AttributeSet attrs) { - super(c, attrs); - - TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout); - ignoreRightInset = a.getBoolean( - R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false); - a.recycle(); - } - } - - @Override - public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback, - int type) { - if (type == ActionMode.TYPE_FLOATING) { - return startActionMode(originalView, callback, type); - } - return super.startActionModeForChild(originalView, callback, type); - } - - private ActionMode createFloatingActionMode( - View originatingView, ActionMode.Callback2 callback) { - if (mFloatingActionMode != null) { - mFloatingActionMode.finish(); - } - cleanupFloatingActionModeViews(); - mFloatingToolbar = new FloatingToolbar(mFakeWindow); - final FloatingActionMode mode = - new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar); - mFloatingActionModeOriginatingView = originatingView; - mFloatingToolbarPreDrawListener = - new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - mode.updateViewLocationInWindow(); - return true; - } - }; - return mode; - } - - private void setHandledFloatingActionMode(ActionMode mode) { - mFloatingActionMode = mode; - mFloatingActionMode.invalidate(); // Will show the floating toolbar if necessary. - mFloatingActionModeOriginatingView.getViewTreeObserver() - .addOnPreDrawListener(mFloatingToolbarPreDrawListener); - } - - private void cleanupFloatingActionModeViews() { - if (mFloatingToolbar != null) { - mFloatingToolbar.dismiss(); - mFloatingToolbar = null; - } - if (mFloatingActionModeOriginatingView != null) { - if (mFloatingToolbarPreDrawListener != null) { - mFloatingActionModeOriginatingView.getViewTreeObserver() - .removeOnPreDrawListener(mFloatingToolbarPreDrawListener); - mFloatingToolbarPreDrawListener = null; - } - mFloatingActionModeOriginatingView = null; - } - } - - private ActionMode startActionMode( - View originatingView, ActionMode.Callback callback, int type) { - ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback); - ActionMode mode = createFloatingActionMode(originatingView, wrappedCallback); - if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) { - setHandledFloatingActionMode(mode); - } else { - mode = null; - } - return mode; - } - - private class ActionModeCallback2Wrapper extends ActionMode.Callback2 { - private final ActionMode.Callback mWrapped; - - public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) { - mWrapped = wrapped; - } - - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - return mWrapped.onCreateActionMode(mode, menu); - } - - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - requestFitSystemWindows(); - return mWrapped.onPrepareActionMode(mode, menu); - } - - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - return mWrapped.onActionItemClicked(mode, item); - } - - public void onDestroyActionMode(ActionMode mode) { - mWrapped.onDestroyActionMode(mode); - if (mode == mFloatingActionMode) { - cleanupFloatingActionModeViews(); - mFloatingActionMode = null; - } - requestFitSystemWindows(); - } - - @Override - public void onGetContentRect(ActionMode mode, View view, Rect outRect) { - if (mWrapped instanceof ActionMode.Callback2) { - ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect); - } else { - super.onGetContentRect(mode, view, outRect); - } - } - } - - interface InteractionEventHandler { - /** - * Returns a result for {@link ViewGroup#dispatchTouchEvent(MotionEvent)} or null to defer - * to the super method. - */ - Boolean handleDispatchTouchEvent(MotionEvent ev); - - /** - * Returns if the view should intercept the touch event. - * - * The touch event may still be interecepted if - * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)} decides to do so. - */ - boolean shouldInterceptTouchEvent(MotionEvent ev); - - /** - * Called when the view decides to intercept the touch event. - */ - void didIntercept(MotionEvent ev); - - boolean handleTouchEvent(MotionEvent ev); - - void didNotHandleTouchEvent(MotionEvent ev); - - boolean interceptMediaKey(KeyEvent event); - - boolean dispatchKeyEvent(KeyEvent event); - } - - /** - * Minimal window to satisfy FloatingToolbar. - */ - private Window mFakeWindow = new Window(mContext) { - @Override - public void takeSurface(SurfaceHolder.Callback2 callback) { - } - - @Override - public void takeInputQueue(InputQueue.Callback callback) { - } - - @Override - public boolean isFloating() { - return false; - } - - @Override - public void alwaysReadCloseOnTouchAttr() { - } - - @Override - public void setContentView(@LayoutRes int layoutResID) { - } - - @Override - public void setContentView(View view) { - } - - @Override - public void setContentView(View view, ViewGroup.LayoutParams params) { - } - - @Override - public void addContentView(View view, ViewGroup.LayoutParams params) { - } - - @Override - public void clearContentView() { - } - - @Override - public View getCurrentFocus() { - return null; - } - - @Override - public LayoutInflater getLayoutInflater() { - return null; - } - - @Override - public void setTitle(CharSequence title) { - } - - @Override - public void setTitleColor(@ColorInt int textColor) { - } - - @Override - public void openPanel(int featureId, KeyEvent event) { - } - - @Override - public void closePanel(int featureId) { - } - - @Override - public void togglePanel(int featureId, KeyEvent event) { - } - - @Override - public void invalidatePanelMenu(int featureId) { - } - - @Override - public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) { - return false; - } - - @Override - public boolean performPanelIdentifierAction(int featureId, int id, int flags) { - return false; - } - - @Override - public void closeAllPanels() { - } - - @Override - public boolean performContextMenuIdentifierAction(int id, int flags) { - return false; - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - } - - @Override - public void setBackgroundDrawable(Drawable drawable) { - } - - @Override - public void setFeatureDrawableResource(int featureId, @DrawableRes int resId) { - } - - @Override - public void setFeatureDrawableUri(int featureId, Uri uri) { - } - - @Override - public void setFeatureDrawable(int featureId, Drawable drawable) { - } - - @Override - public void setFeatureDrawableAlpha(int featureId, int alpha) { - } - - @Override - public void setFeatureInt(int featureId, int value) { - } - - @Override - public void takeKeyEvents(boolean get) { - } - - @Override - public boolean superDispatchKeyEvent(KeyEvent event) { - return false; - } - - @Override - public boolean superDispatchKeyShortcutEvent(KeyEvent event) { - return false; - } - - @Override - public boolean superDispatchTouchEvent(MotionEvent event) { - return false; - } - - @Override - public boolean superDispatchTrackballEvent(MotionEvent event) { - return false; - } - - @Override - public boolean superDispatchGenericMotionEvent(MotionEvent event) { - return false; - } - - @Override - public View getDecorView() { - return StatusBarWindowView.this; - } - - @Override - public View peekDecorView() { - return null; - } - - @Override - public Bundle saveHierarchyState() { - return null; - } - - @Override - public void restoreHierarchyState(Bundle savedInstanceState) { - } - - @Override - protected void onActive() { - } - - @Override - public void setChildDrawable(int featureId, Drawable drawable) { - } - - @Override - public void setChildInt(int featureId, int value) { - } - - @Override - public boolean isShortcutKey(int keyCode, KeyEvent event) { - return false; - } - - @Override - public void setVolumeControlStream(int streamType) { - } - - @Override - public int getVolumeControlStream() { - return 0; - } - - @Override - public int getStatusBarColor() { - return 0; - } - - @Override - public void setStatusBarColor(@ColorInt int color) { - } - - @Override - public int getNavigationBarColor() { - return 0; - } - - @Override - public void setNavigationBarColor(@ColorInt int color) { - } - - @Override - public void setDecorCaptionShade(int decorCaptionShade) { - } - - @Override - public void setResizingCaptionDrawable(Drawable drawable) { - } - - @Override - public void onMultiWindowModeChanged() { - } - - @Override - public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { - } - - @Override - public void reportActivityRelaunched() { - } - - @Override - public WindowInsetsController getInsetsController() { - return null; - } - }; - } - diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java index 21d0bb8c2daf..802da3e8c21c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java @@ -19,8 +19,9 @@ package com.android.systemui.statusbar.phone.dagger; import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.android.systemui.statusbar.phone.NotificationPanelViewController; -import com.android.systemui.statusbar.phone.StatusBarWindowView; -import com.android.systemui.statusbar.phone.StatusBarWindowViewController; +import com.android.systemui.statusbar.phone.NotificationShadeWindowView; +import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController; +import com.android.systemui.statusbar.phone.StatusBarWindowController; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -41,7 +42,8 @@ public interface StatusBarComponent { */ @Subcomponent.Builder interface Builder { - @BindsInstance Builder statusBarWindowView(StatusBarWindowView statusBarWindowView); + @BindsInstance Builder statusBarWindowView( + NotificationShadeWindowView notificationShadeWindowView); StatusBarComponent build(); } @@ -54,10 +56,16 @@ public interface StatusBarComponent { @interface StatusBarScope {} /** + * Creates a NotificationShadeWindowViewController. + */ + @StatusBarScope + NotificationShadeWindowViewController getNotificationShadeWindowViewController(); + + /** * Creates a StatusBarWindowViewController. */ @StatusBarScope - StatusBarWindowViewController getStatusBarWindowViewController(); + StatusBarWindowController getStatusBarWindowController(); /** * Creates a NotificationPanelViewController. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java index 20bd51d27050..37d8c9ae2958 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.phone.dagger; import com.android.systemui.statusbar.phone.NotificationPanelView; -import com.android.systemui.statusbar.phone.StatusBarWindowView; +import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import dagger.Module; import dagger.Provides; @@ -28,8 +28,8 @@ public abstract class StatusBarViewModule { @Provides @StatusBarComponent.StatusBarScope public static NotificationPanelView getNotificationPanelView( - StatusBarWindowView statusBarWindowView) { - return statusBarWindowView.getNotificationPanelView(); + NotificationShadeWindowView notificationShadeWindowView) { + return notificationShadeWindowView.getNotificationPanelView(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java index 625d88481c5a..d62da10de3d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java @@ -25,7 +25,7 @@ import android.widget.FrameLayout; import com.android.systemui.R; import com.android.systemui.statusbar.phone.NotificationPanelViewController; -import com.android.systemui.statusbar.phone.StatusBarWindowView; +import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import java.util.Objects; import java.util.function.Consumer; @@ -36,14 +36,14 @@ import java.util.function.Consumer; public class BrightnessMirrorController implements CallbackController<BrightnessMirrorController.BrightnessMirrorListener> { - private final StatusBarWindowView mStatusBarWindow; + private final NotificationShadeWindowView mStatusBarWindow; private final Consumer<Boolean> mVisibilityCallback; private final NotificationPanelViewController mNotificationPanel; private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>(); private final int[] mInt2Cache = new int[2]; private View mBrightnessMirror; - public BrightnessMirrorController(StatusBarWindowView statusBarWindow, + public BrightnessMirrorController(NotificationShadeWindowView statusBarWindow, NotificationPanelViewController notificationPanelViewController, @NonNull Consumer<Boolean> visibilityCallback) { mStatusBarWindow = statusBarWindow; diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index ba264c0ae6db..5706bee3f60d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -53,6 +53,7 @@ import com.android.systemui.ScreenDecorations.TunablePaddingTagListener; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.FragmentService; +import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarWindowView; import com.android.systemui.tuner.TunablePadding; @@ -80,7 +81,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { private WindowManager mWindowManager; private FragmentService mFragmentService; private FragmentHostManager mFragmentHostManager; - private StatusBarWindowView mView; + private NotificationShadeWindowView mView; + private StatusBarWindowView mStatusBarWindowView; private TunablePaddingService mTunablePaddingService; private Handler mMainHandler; @Mock @@ -99,9 +101,11 @@ public class ScreenDecorationsTest extends SysuiTestCase { mFragmentService = mDependency.injectMockDependency(FragmentService.class); mWindowManager = mock(WindowManager.class); - mView = spy(new StatusBarWindowView(mContext, null)); + mView = spy(new NotificationShadeWindowView(mContext, null)); + mStatusBarWindowView = spy(new StatusBarWindowView(mContext, null)); when(mStatusBarLazy.get()).thenReturn(mStatusBar); - when(mStatusBar.getStatusBarWindow()).thenReturn(mView); + when(mStatusBar.getNotificationShadeWindowView()).thenReturn(mView); + when(mStatusBar.getStatusBarWindow()).thenReturn(mStatusBarWindowView); Display display = mContext.getSystemService(WindowManager.class).getDefaultDisplay(); when(mWindowManager.getDefaultDisplay()).thenReturn(display); diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java index 162b16ed3728..25bcb54a9e50 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java @@ -18,19 +18,25 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricManager.Authenticators; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricPrompt; import android.os.Bundle; +import android.os.UserManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; @@ -57,6 +63,7 @@ public class AuthContainerViewTest extends SysuiTestCase { private TestableAuthContainer mAuthContainer; private @Mock AuthDialogCallback mCallback; + private @Mock UserManager mUserManager; @Before public void setup() { @@ -156,6 +163,18 @@ public class AuthContainerViewTest extends SysuiTestCase { verify(mAuthContainer.mFrameLayout).addView(mAuthContainer.mCredentialView); } + @Test + public void testCredentialViewUsesEffectiveUserId() { + final int dummyEffectiveUserId = 200; + when(mUserManager.getCredentialOwnerProfile(anyInt())).thenReturn(dummyEffectiveUserId); + + initializeContainer(Authenticators.DEVICE_CREDENTIAL); + mAuthContainer.onAttachedToWindowInternal(); + assertTrue(mAuthContainer.mCredentialView instanceof AuthCredentialPatternView); + assertEquals(dummyEffectiveUserId, mAuthContainer.mCredentialView.mEffectiveUserId); + assertEquals(Utils.CREDENTIAL_PATTERN, mAuthContainer.mCredentialView.mCredentialType); + } + private void initializeContainer(int authenticators) { AuthContainerView.Config config = new AuthContainerView.Config(); config.mContext = mContext; @@ -211,5 +230,15 @@ public class AuthContainerViewTest extends SysuiTestCase { public int getAnimateCredentialStartDelayMs() { return 0; } + + @Override + public UserManager getUserManager(Context context) { + return mUserManager; + } + + @Override + public @Utils.CredentialType int getCredentialType(Context context, int effectiveUserId) { + return Utils.CREDENTIAL_PATTERN; + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index c0e92e09c486..65399bfb901e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -20,7 +20,6 @@ import static android.hardware.biometrics.BiometricManager.Authenticators; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; -import static junit.framework.TestCase.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -292,6 +291,24 @@ public class AuthControllerTest extends SysuiTestCase { // Corner case tests @Test + public void testCancelAuthentication_whenCredentialConfirmed_doesntCrash() throws Exception { + // It's possible that before the client is notified that credential is confirmed, the client + // requests to cancel authentication. + // + // Test that the following sequence of events does not crash SystemUI: + // 1) Credential is confirmed + // 2) Client cancels authentication + + showDialog(Authenticators.DEVICE_CREDENTIAL, BiometricPrompt.TYPE_NONE); + verify(mDialog1).show(any(), any()); + + mAuthController.onDismissed(AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED); + verify(mReceiver).onDialogDismissed(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED); + + mAuthController.hideAuthenticationDialog(); + } + + @Test public void testShowNewDialog_beforeOldDialogDismissed_SkipsAnimations() { showDialog(Authenticators.BIOMETRIC_WEAK, BiometricPrompt.TYPE_FACE); verify(mDialog1).show(any(), any()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index c3df3f633f3b..04116ec68600 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -74,8 +74,8 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationGroupManager; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -126,7 +126,7 @@ public class BubbleControllerTest extends SysuiTestCase { private ArgumentCaptor<NotificationRemoveInterceptor> mRemoveInterceptorCaptor; private TestableBubbleController mBubbleController; - private StatusBarWindowController mStatusBarWindowController; + private NotificationShadeWindowController mNotificationShadeWindowController; private NotificationEntryListener mEntryListener; private NotificationRemoveInterceptor mRemoveInterceptor; @@ -170,11 +170,11 @@ public class BubbleControllerTest extends SysuiTestCase { new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent())); // Bubbles get added to status bar window view - mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager, - mActivityManager, mDozeParameters, mStatusBarStateController, + mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, + mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardBypassController, mColorExtractor, - mSuperStatusBarViewFactory, mResources); - mStatusBarWindowController.attach(); + mSuperStatusBarViewFactory); + mNotificationShadeWindowController.attach(); // Need notifications for bubbles mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency); @@ -201,7 +201,7 @@ public class BubbleControllerTest extends SysuiTestCase { mock(NotificationInterruptionStateProvider.HeadsUpSuppressor.class)); mBubbleData = new BubbleData(mContext); mBubbleController = new TestableBubbleController(mContext, - mStatusBarWindowController, + mNotificationShadeWindowController, mStatusBarStateController, mShadeController, mBubbleData, @@ -250,7 +250,7 @@ public class BubbleControllerTest extends SysuiTestCase { mBubbleController.removeBubble( mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); - assertFalse(mStatusBarWindowController.getBubblesShowing()); + assertFalse(mNotificationShadeWindowController.getBubblesShowing()); assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey())); verify(mNotificationEntryManager, times(2)).updateNotifications(anyString()); verify(mBubbleStateChangeListener).onHasBubblesChanged(false); @@ -290,7 +290,7 @@ public class BubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.hasBubbles()); mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE); - assertFalse(mStatusBarWindowController.getBubblesShowing()); + assertFalse(mNotificationShadeWindowController.getBubblesShowing()); verify(mNotificationEntryManager, times(3)).updateNotifications(any()); assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey())); assertNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().getKey())); @@ -308,14 +308,14 @@ public class BubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.hasBubbles()); assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade( mRow.getEntry().getKey())); - assertFalse(mStatusBarWindowController.getBubbleExpanded()); + assertFalse(mNotificationShadeWindowController.getBubbleExpanded()); // Expand the stack BubbleStackView stackView = mBubbleController.getStackView(); mBubbleController.expandStack(); assertTrue(mBubbleController.isStackExpanded()); verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey()); - assertTrue(mStatusBarWindowController.getBubbleExpanded()); + assertTrue(mNotificationShadeWindowController.getBubbleExpanded()); // Make sure the notif is suppressed assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade( @@ -325,7 +325,7 @@ public class BubbleControllerTest extends SysuiTestCase { mBubbleController.collapseStack(); verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey()); assertFalse(mBubbleController.isStackExpanded()); - assertFalse(mStatusBarWindowController.getBubbleExpanded()); + assertFalse(mNotificationShadeWindowController.getBubbleExpanded()); } @Test @@ -711,7 +711,7 @@ public class BubbleControllerTest extends SysuiTestCase { static class TestableBubbleController extends BubbleController { // Let's assume surfaces can be synchronized immediately. TestableBubbleController(Context context, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, StatusBarStateController statusBarStateController, ShadeController shadeController, BubbleData data, @@ -723,7 +723,7 @@ public class BubbleControllerTest extends SysuiTestCase { NotificationEntryManager entryManager, RemoteInputUriController remoteInputUriController) { super(context, - statusBarWindowController, statusBarStateController, shadeController, + notificationShadeWindowController, statusBarStateController, shadeController, data, Runnable::run, configurationController, interruptionStateProvider, zenModeController, lockscreenUserManager, groupManager, entryManager, remoteInputUriController); diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 64fbc1bac658..acc30d9f8374 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -36,8 +36,8 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; @@ -57,7 +57,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock LockPatternUtils mLockPatternUtils; private @Mock KeyguardUpdateMonitor mUpdateMonitor; private @Mock StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - private @Mock StatusBarWindowController mStatusBarWindowController; + private @Mock NotificationShadeWindowController mNotificationShadeWindowController; private @Mock BroadcastDispatcher mBroadcastDispatcher; private @Mock DismissCallbackRegistry mDismissCallbackRegistry; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -77,7 +77,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { TestableLooper.get(this).runWithLooper(() -> { mViewMediator = new KeyguardViewMediator( mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher, - mStatusBarWindowController, () -> mStatusBarKeyguardViewManager, + mNotificationShadeWindowController, () -> mStatusBarKeyguardViewManager, mDismissCallbackRegistry, mUiBgExecutor); }); } @@ -87,6 +87,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mViewMediator.start(); mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER); verify(mUpdateMonitor).setKeyguardGoingAway(false); - verify(mStatusBarWindowController, never()).setKeyguardGoingAway(anyBoolean()); + verify(mNotificationShadeWindowController, never()).setKeyguardGoingAway(anyBoolean()); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java index bb9c14bbb2a3..6d83ac32cef5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java @@ -34,8 +34,8 @@ import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener; import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; -import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.HeadsUpManager; import org.junit.Before; @@ -97,6 +97,6 @@ public class NonPhoneDependencyTest extends SysuiTestCase { viewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer); TestableLooper.get(this).processAllMessages(); - assertFalse(mDependency.hasInstantiatedDependency(StatusBarWindowController.class)); + assertFalse(mDependency.hasInstantiatedDependency(NotificationShadeWindowController.class)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index 3fdbd3edfcaa..61e43b010dda 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -55,7 +55,7 @@ import com.android.systemui.statusbar.notification.row.NotificationRowContentBin import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.StatusBarWindowController; +import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.tests.R; import java.util.concurrent.CountDownLatch; @@ -87,7 +87,7 @@ public class NotificationTestHelper { mContext = context; dependency.injectMockDependency(NotificationMediaManager.class); dependency.injectMockDependency(BubbleController.class); - dependency.injectMockDependency(StatusBarWindowController.class); + dependency.injectMockDependency(NotificationShadeWindowController.class); dependency.injectMockDependency(SmartReplyController.class); StatusBarStateController stateController = mock(StatusBarStateController.class); mGroupManager = new NotificationGroupManager(stateController); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java index a54f7335ba67..a07cfc3c3226 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java @@ -34,8 +34,8 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.NotificationPanelViewController; -import com.android.systemui.statusbar.phone.StatusBarWindowView; -import com.android.systemui.statusbar.phone.StatusBarWindowViewController; +import com.android.systemui.statusbar.phone.NotificationShadeWindowView; +import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController; import org.junit.Assert; import org.junit.Before; @@ -49,20 +49,22 @@ public class ActivityLaunchAnimatorTest extends SysuiTestCase { private ActivityLaunchAnimator mLaunchAnimator; private ActivityLaunchAnimator.Callback mCallback = mock(ActivityLaunchAnimator.Callback.class); - private StatusBarWindowViewController mStatusBarWindowViewController = mock( - StatusBarWindowViewController.class); - private StatusBarWindowView mStatusBarWindowView = mock(StatusBarWindowView.class); + private NotificationShadeWindowViewController mNotificationShadeWindowViewController = mock( + NotificationShadeWindowViewController.class); + private NotificationShadeWindowView mNotificationShadeWindowView = mock( + NotificationShadeWindowView.class); private NotificationListContainer mNotificationContainer = mock(NotificationListContainer.class); private ExpandableNotificationRow mRow = mock(ExpandableNotificationRow.class); @Before public void setUp() throws Exception { - when(mStatusBarWindowViewController.getView()).thenReturn(mStatusBarWindowView); - when(mStatusBarWindowView.getResources()).thenReturn(mContext.getResources()); + when(mNotificationShadeWindowViewController.getView()) + .thenReturn(mNotificationShadeWindowView); + when(mNotificationShadeWindowView.getResources()).thenReturn(mContext.getResources()); when(mCallback.areLaunchAnimationsEnabled()).thenReturn(true); mLaunchAnimator = new ActivityLaunchAnimator( - mStatusBarWindowViewController, + mNotificationShadeWindowViewController, mCallback, mock(NotificationPanelViewController.class), mNotificationContainer); @@ -92,7 +94,7 @@ public class ActivityLaunchAnimatorTest extends SysuiTestCase { RemoteAnimationAdapter launchAnimation = mLaunchAnimator.getLaunchAnimation(mRow, false /* occluded */); Assert.assertTrue("No animation generated", launchAnimation != null); - executePostsImmediately(mStatusBarWindowView); + executePostsImmediately(mNotificationShadeWindowView); mLaunchAnimator.setLaunchResult(ActivityManager.START_SUCCESS, true /* wasIntentActivity */); verify(mCallback).onExpandAnimationTimedOut(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index 5907a0a683a8..769b774aeec2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -67,7 +67,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @Mock - private StatusBarWindowController mStatusBarWindowController; + private NotificationShadeWindowController mNotificationShadeWindowController; @Mock private DozeScrimController mDozeScrimController; @Mock @@ -104,9 +104,9 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { res.addOverride(com.android.internal.R.integer.config_wakeUpDelayDoze, 0); mBiometricUnlockController = new BiometricUnlockController(mContext, mDozeScrimController, mKeyguardViewMediator, mScrimController, mStatusBar, mShadeController, - mStatusBarWindowController, mKeyguardStateController, mHandler, mUpdateMonitor, - res.getResources(), mKeyguardBypassController, mDozeParameters, mMetricsLogger, - mDumpController); + mNotificationShadeWindowController, mKeyguardStateController, mHandler, + mUpdateMonitor, res.getResources(), mKeyguardBypassController, mDozeParameters, + mMetricsLogger, mDumpController); mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java index d31f17531889..3c6a69882d44 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java @@ -79,12 +79,12 @@ public class DozeServiceHostTest extends SysuiTestCase { @Mock private DozeLog mDozeLog; @Mock private PulseExpansionHandler mPulseExpansionHandler; @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; - @Mock private StatusBarWindowController mStatusBarWindowController; + @Mock private NotificationShadeWindowController mNotificationShadeWindowController; @Mock private PowerManager mPowerManager; @Mock private WakefulnessLifecycle mWakefullnessLifecycle; @Mock private StatusBar mStatusBar; @Mock private NotificationIconAreaController mNotificationIconAreaController; - @Mock private StatusBarWindowViewController mStatusBarWindowViewController; + @Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController; @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @Mock private NotificationPanelViewController mNotificationPanel; @Mock private View mAmbientIndicationContainer; @@ -99,12 +99,12 @@ public class DozeServiceHostTest extends SysuiTestCase { mBatteryController, mScrimController, () -> mBiometricUnlockController, mKeyguardViewMediator, () -> mAssistManager, mDozeScrimController, mKeyguardUpdateMonitor, mVisualStabilityManager, mPulseExpansionHandler, - mStatusBarWindowController, mNotificationWakeUpCoordinator, + mNotificationShadeWindowController, mNotificationWakeUpCoordinator, mLockscreenLockIconController); mDozeServiceHost.initialize(mStatusBar, mNotificationIconAreaController, - mStatusBarKeyguardViewManager, mStatusBarWindowViewController, mNotificationPanel, - mAmbientIndicationContainer); + mStatusBarKeyguardViewManager, mNotificationShadeWindowViewController, + mNotificationPanel, mAmbientIndicationContainer); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java index 7fa69018b496..50d8bf0b02c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java @@ -57,7 +57,7 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { private HeadsUpManagerPhone mHeadsUpManager; @Mock private NotificationGroupManager mGroupManager; - @Mock private View mStatusBarWindowView; + @Mock private View mNotificationShadeWindowView; @Mock private VisualStabilityManager mVSManager; @Mock private StatusBar mBar; @Mock private StatusBarStateController mStatusBarStateController; @@ -65,13 +65,13 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { private boolean mLivesPastNormalTime; private final class TestableHeadsUpManagerPhone extends HeadsUpManagerPhone { - TestableHeadsUpManagerPhone(Context context, View statusBarWindowView, + TestableHeadsUpManagerPhone(Context context, View notificationShadeWindowView, NotificationGroupManager groupManager, StatusBar bar, VisualStabilityManager vsManager, StatusBarStateController statusBarStateController, KeyguardBypassController keyguardBypassController) { super(context, statusBarStateController, keyguardBypassController); - setUp(statusBarWindowView, groupManager, bar, vsManager); + setUp(notificationShadeWindowView, groupManager, bar, vsManager); mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME; mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME; } @@ -89,9 +89,9 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { .thenReturn(TEST_AUTO_DISMISS_TIME); when(mVSManager.isReorderingAllowed()).thenReturn(true); mDependency.injectMockDependency(BubbleController.class); - mDependency.injectMockDependency(StatusBarWindowController.class); + mDependency.injectMockDependency(NotificationShadeWindowController.class); mDependency.injectMockDependency(ConfigurationController.class); - mHeadsUpManager = new TestableHeadsUpManagerPhone(mContext, mStatusBarWindowView, + mHeadsUpManager = new TestableHeadsUpManagerPhone(mContext, mNotificationShadeWindowView, mGroupManager, mBar, mVSManager, mStatusBarStateController, mBypassController); super.setUp(); mHeadsUpManager.mHandler = mTestHandler; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java index 147edf6589e9..40d3395f2ca1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java @@ -11,7 +11,7 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ package com.android.systemui.statusbar.phone; @@ -25,7 +25,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.IActivityManager; -import android.content.res.Resources; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.WindowManager; @@ -49,11 +48,11 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @RunWithLooper @SmallTest -public class StatusBarWindowControllerTest extends SysuiTestCase { +public class NotificationShadeWindowControllerTest extends SysuiTestCase { @Mock private WindowManager mWindowManager; @Mock private DozeParameters mDozeParameters; - @Mock private StatusBarWindowView mStatusBarView; + @Mock private NotificationShadeWindowView mStatusBarView; @Mock private IActivityManager mActivityManager; @Mock private SysuiStatusBarStateController mStatusBarStateController; @Mock private ConfigurationController mConfigurationController; @@ -61,28 +60,28 @@ public class StatusBarWindowControllerTest extends SysuiTestCase { @Mock private SysuiColorExtractor mColorExtractor; @Mock ColorExtractor.GradientColors mGradientColors; @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory; - @Mock private Resources mResources; - private StatusBarWindowController mStatusBarWindowController; + private NotificationShadeWindowController mNotificationShadeWindowController; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mDozeParameters.getAlwaysOn()).thenReturn(true); when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); - when(mSuperStatusBarViewFactory.getStatusBarWindowView()).thenReturn(mStatusBarView); + when(mSuperStatusBarViewFactory.getNotificationShadeWindowView()) + .thenReturn(mStatusBarView); - mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager, - mActivityManager, mDozeParameters, mStatusBarStateController, + mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, + mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardBypassController, mColorExtractor, - mSuperStatusBarViewFactory, mResources); + mSuperStatusBarViewFactory); - mStatusBarWindowController.attach(); + mNotificationShadeWindowController.attach(); } @Test public void testSetDozing_hidesSystemOverlays() { - mStatusBarWindowController.setDozing(true); + mNotificationShadeWindowController.setDozing(true); ArgumentCaptor<WindowManager.LayoutParams> captor = ArgumentCaptor.forClass(WindowManager.LayoutParams.class); verify(mWindowManager).updateViewLayout(any(), captor.capture()); @@ -91,7 +90,7 @@ public class StatusBarWindowControllerTest extends SysuiTestCase { assertThat(flag).isNotEqualTo(0); reset(mWindowManager); - mStatusBarWindowController.setDozing(false); + mNotificationShadeWindowController.setDozing(false); verify(mWindowManager).updateViewLayout(any(), captor.capture()); flag = captor.getValue().privateFlags & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; @@ -100,7 +99,7 @@ public class StatusBarWindowControllerTest extends SysuiTestCase { @Test public void testOnThemeChanged_doesntCrash() { - mStatusBarWindowController.onThemeChanged(); + mNotificationShadeWindowController.onThemeChanged(); } @Test @@ -110,6 +109,6 @@ public class StatusBarWindowControllerTest extends SysuiTestCase { @Test public void testSetForcePluginOpen_beforeStatusBarInitialization() { - mStatusBarWindowController.setForcePluginOpen(true); + mNotificationShadeWindowController.setForcePluginOpen(true); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java index f9848f3c0719..985354007e25 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java @@ -56,10 +56,10 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest -public class StatusBarWindowViewTest extends SysuiTestCase { +public class NotificationShadeWindowViewTest extends SysuiTestCase { - private StatusBarWindowView mView; - private StatusBarWindowViewController mController; + private NotificationShadeWindowView mView; + private NotificationShadeWindowViewController mController; @Mock private NotificationWakeUpCoordinator mCoordinator; @Mock private PulseExpansionHandler mPulseExpansionHandler; @@ -84,15 +84,16 @@ public class StatusBarWindowViewTest extends SysuiTestCase { public void setUp() { MockitoAnnotations.initMocks(this); - mView = spy(new StatusBarWindowView(getContext(), null)); + mView = spy(new NotificationShadeWindowView(getContext(), null)); when(mView.findViewById(R.id.notification_stack_scroller)) .thenReturn(mNotificationStackScrollLayout); + when(mStatusBarStateController.isDozing()).thenReturn(false); mDependency.injectTestDependency(ShadeController.class, mShadeController); when(mDockManager.isDocked()).thenReturn(false); - mController = new StatusBarWindowViewController( + mController = new NotificationShadeWindowViewController( new InjectionInflationController( SystemUIFactory.getInstance().getRootComponent()), mCoordinator, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 5b5eaadee552..675a2df768d8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -104,7 +104,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { mock(KeyguardUpdateMonitor.class), mock(NavigationModeController.class), mock(DockManager.class), - mock(StatusBarWindowController.class), + mock(NotificationShadeWindowController.class), mKeyguardStateController, mock(NotificationMediaManager.class)); mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer, @@ -270,12 +270,12 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { KeyguardUpdateMonitor keyguardUpdateMonitor, NavigationModeController navigationModeController, DockManager dockManager, - StatusBarWindowController statusBarWindowController, + NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, NotificationMediaManager notificationMediaManager) { super(context, callback, lockPatternUtils, sysuiStatusBarStateController, configurationController, keyguardUpdateMonitor, navigationModeController, - dockManager, statusBarWindowController, keyguardStateController, + dockManager, notificationShadeWindowController, keyguardStateController, notificationMediaManager); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java index 782e14c83951..dd896be0e120 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java @@ -100,16 +100,17 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase { mDependency.injectMockDependency(NotificationMediaManager.class); mDependency.injectMockDependency(VisualStabilityManager.class); mDependency.injectMockDependency(NotificationGutsManager.class); - mDependency.injectMockDependency(StatusBarWindowController.class); + mDependency.injectMockDependency(NotificationShadeWindowController.class); NotificationEntryManager entryManager = mDependency.injectMockDependency(NotificationEntryManager.class); when(entryManager.getActiveNotificationsForCurrentUser()).thenReturn(new ArrayList<>()); - StatusBarWindowView statusBarWindowView = mock(StatusBarWindowView.class); - when(statusBarWindowView.getResources()).thenReturn(mContext.getResources()); + NotificationShadeWindowView notificationShadeWindowView = + mock(NotificationShadeWindowView.class); + when(notificationShadeWindowView.getResources()).thenReturn(mContext.getResources()); mStatusBarNotificationPresenter = new StatusBarNotificationPresenter(mContext, mock(NotificationPanelViewController.class), mock(HeadsUpManagerPhone.class), - statusBarWindowView, mock(NotificationListContainerViewGroup.class), + notificationShadeWindowView, mock(NotificationListContainerViewGroup.class), mock(DozeScrimController.class), mock(ScrimController.class), mock(ActivityLaunchAnimator.class), mock(DynamicPrivacyController.class), mock(NotificationAlertingManager.class), 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 fee48522683d..e90e398ba061 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 @@ -201,7 +201,7 @@ public class StatusBarTest extends SysuiTestCase { @Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger; @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock private AmbientDisplayConfiguration mAmbientDisplayConfiguration; - @Mock private StatusBarWindowView mStatusBarWindowView; + @Mock private NotificationShadeWindowView mNotificationShadeWindowView; @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock private AssistManager mAssistManager; @Mock private NotificationGutsManager mNotificationGutsManager; @@ -224,9 +224,9 @@ public class StatusBarTest extends SysuiTestCase { @Mock private BubbleController mBubbleController; @Mock private NotificationGroupManager mGroupManager; @Mock private NotificationGroupAlertTransferHelper mGroupAlertTransferHelper; - @Mock private StatusBarWindowController mStatusBarWindowController; + @Mock private NotificationShadeWindowController mNotificationShadeWindowController; @Mock private NotificationIconAreaController mNotificationIconAreaController; - @Mock private StatusBarWindowViewController mStatusBarWindowViewController; + @Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController; @Mock private DozeParameters mDozeParameters; @Mock private Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy; @Mock private LockscreenWallpaper mLockscreenWallpaper; @@ -324,11 +324,11 @@ public class StatusBarTest extends SysuiTestCase { when(mStatusBarComponentBuilderProvider.get()).thenReturn(mStatusBarComponentBuilder); when(mStatusBarComponentBuilder.build()).thenReturn(mStatusBarComponent); - when(mStatusBarComponent.getStatusBarWindowViewController()).thenReturn( - mStatusBarWindowViewController); + when(mStatusBarComponent.getNotificationShadeWindowViewController()).thenReturn( + mNotificationShadeWindowViewController); mShadeController = new ShadeControllerImpl(mCommandQueue, - mStatusBarStateController, mStatusBarWindowController, + mStatusBarStateController, mNotificationShadeWindowController, mStatusBarKeyguardViewManager, mContext.getSystemService(WindowManager.class), () -> mStatusBar, () -> mAssistManager, () -> mBubbleController); @@ -384,7 +384,7 @@ public class StatusBarTest extends SysuiTestCase { () -> mAssistManager, mNotificationListener, configurationController, - mStatusBarWindowController, + mNotificationShadeWindowController, mLockscreenLockIconController, mDozeParameters, mScrimController, @@ -417,7 +417,7 @@ public class StatusBarTest extends SysuiTestCase { mNotificationRowBinder, mDismissCallbackRegistry); - when(mStatusBarWindowView.findViewById(R.id.lock_icon_container)).thenReturn( + when(mNotificationShadeWindowView.findViewById(R.id.lock_icon_container)).thenReturn( mLockIconContainer); when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class), @@ -430,7 +430,7 @@ public class StatusBarTest extends SysuiTestCase { // TODO: we should be able to call mStatusBar.start() and have all the below values // initialized automatically. - mStatusBar.mStatusBarWindow = mStatusBarWindowView; + mStatusBar.mNotificationShadeWindowView = mNotificationShadeWindowView; mStatusBar.mNotificationPanelViewController = mNotificationPanelViewController; mStatusBar.mDozeScrimController = mDozeScrimController; mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController; diff --git a/services/Android.bp b/services/Android.bp index 5afed6c4fd19..914ea2859fb1 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -6,7 +6,7 @@ filegroup { } filegroup { - name: "services-sources", + name: "services-stub-sources", srcs: [ ":services.core-sources", ":services.accessibility-sources", @@ -29,6 +29,7 @@ filegroup { ":services.usage-sources", ":services.usb-sources", ":services.voiceinteraction-sources", + ":service-permission-sources", ], visibility: ["//visibility:private"], } @@ -110,7 +111,7 @@ filegroup { droidstubs { name: "services-stubs.sources", - srcs: [":services-sources"], + srcs: [":services-stub-sources"], installable: false, // TODO: remove the --hide options below args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES,process=android.annotation.SystemApi.Process.SYSTEM_SERVER\\)" + diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java index 8ce92a3154f3..a6041e0ee91c 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java @@ -701,6 +701,7 @@ public class AccessibilityWindowManager { case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: case WindowManager.LayoutParams.TYPE_SEARCH_BAR: case WindowManager.LayoutParams.TYPE_STATUS_BAR: + case WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE: case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL: case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL: case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY: diff --git a/services/api/current.txt b/services/api/current.txt index 18e38b1c6547..8a82e610c233 100644 --- a/services/api/current.txt +++ b/services/api/current.txt @@ -1,4 +1,49 @@ // Signature format: 2.0 +package com.android.permission.persistence { + + public interface RuntimePermissionsPersistence { + method @NonNull public static com.android.permission.persistence.RuntimePermissionsPersistence createInstance(); + method public void delete(@NonNull android.os.UserHandle); + method @Nullable public com.android.permission.persistence.RuntimePermissionsState read(@NonNull android.os.UserHandle); + method public void write(@NonNull com.android.permission.persistence.RuntimePermissionsState, @NonNull android.os.UserHandle); + } + + public final class RuntimePermissionsState { + ctor public RuntimePermissionsState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>>, @NonNull java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>>); + method @Nullable public String getFingerprint(); + method @NonNull public java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>> getPackagePermissions(); + method @NonNull public java.util.Map<java.lang.String,java.util.List<com.android.permission.persistence.RuntimePermissionsState.PermissionState>> getSharedUserPermissions(); + method public int getVersion(); + field public static final int NO_VERSION = -1; // 0xffffffff + } + + public static class RuntimePermissionsState.PermissionState { + ctor public RuntimePermissionsState.PermissionState(@NonNull String, boolean, int); + method public int getFlags(); + method @NonNull public String getName(); + method public boolean isGranted(); + } + +} + +package com.android.role.persistence { + + public interface RolesPersistence { + method @NonNull public static com.android.role.persistence.RolesPersistence createInstance(); + method public void delete(@NonNull android.os.UserHandle); + method @Nullable public com.android.role.persistence.RolesState read(@NonNull android.os.UserHandle); + method public void write(@NonNull com.android.role.persistence.RolesState, @NonNull android.os.UserHandle); + } + + public final class RolesState { + ctor public RolesState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>>); + method @Nullable public String getPackagesHash(); + method @NonNull public java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getRoles(); + method public int getVersion(); + } + +} + package com.android.server { public abstract class SystemService { diff --git a/services/core/Android.bp b/services/core/Android.bp index b2fba730fac1..02d4f94662b5 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -90,6 +90,7 @@ java_library_static { ], libs: [ + "services-stubs", "services.net", "android.hardware.light-V2.0-java", "android.hardware.power-V1.0-java", diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 5e495b98c58a..98b572801716 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5848,9 +5848,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken()); - // TODO : remove this once all factories are updated to send NOT_SUSPENDED + // TODO : remove this once all factories are updated to send NOT_SUSPENDED and NOT_ROAMING if (!newNc.hasTransport(TRANSPORT_CELLULAR)) { newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED); + newNc.addCapability(NET_CAPABILITY_NOT_ROAMING); } return newNc; @@ -5899,7 +5900,9 @@ public class ConnectivityService extends IConnectivityManager.Stub processListenRequests(nai); final boolean prevSuspended = !prevNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); final boolean suspended = !newNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); - if (prevSuspended != suspended) { + final boolean prevRoaming = !prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); + final boolean roaming = !newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); + if (prevSuspended != suspended || prevRoaming != roaming) { // TODO (b/73132094) : remove this call once the few users of onSuspended and // onResumed have been removed. notifyNetworkCallbacks(nai, suspended ? ConnectivityManager.CALLBACK_SUSPENDED @@ -6615,7 +6618,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @NonNull private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) { final NetworkInfo newInfo = new NetworkInfo(info); - // The suspended bit is managed in NetworkCapabilities. + // The suspended and roaming bits are managed in NetworkCapabilities. final boolean suspended = !nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); if (suspended && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) { @@ -6628,6 +6631,7 @@ public class ConnectivityService extends IConnectivityManager.Stub newInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, info.getReason(), info.getExtraInfo()); } + newInfo.setRoaming(!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING)); return newInfo; } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index bcc3bdb0a232..c95d3e87f2b0 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -2989,6 +2989,24 @@ class StorageManagerService extends IStorageManager.Stub } /* + * Clear disk encryption key bound to the associated token / secret pair. Removing the user + * binding of the Disk encryption key is done in two phases: first, this call will retrieve + * the disk encryption key using the provided token / secret pair and store it by + * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth + * is called to delete all other bindings of the disk encryption key. + */ + @Override + public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) { + enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); + + try { + mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); + } catch (Exception e) { + Slog.wtf(TAG, e); + } + } + + /* * Delete all disk encryption token/secret pairs except the most recently added one */ @Override diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 4f03a8e878e1..7324d9793cc9 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -2413,43 +2413,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { Intent intent = new Intent(ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); intent.putExtra(PHONE_CONSTANTS_STATE_KEY, dataStateToString(state)); intent.putExtra(PHONE_CONSTANTS_DATA_APN_KEY, apn); - intent.putExtra(PHONE_CONSTANTS_DATA_APN_TYPE_KEY, getApnTypesStringFromBitmask(apnType)); + intent.putExtra(PHONE_CONSTANTS_DATA_APN_TYPE_KEY, + ApnSetting.getApnTypesStringFromBitmask(apnType)); intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId); mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } - private static final Map<Integer, String> APN_TYPE_INT_MAP; - static { - APN_TYPE_INT_MAP = new android.util.ArrayMap<Integer, String>(); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_DEFAULT, "default"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_MMS, "mms"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_SUPL, "supl"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_DUN, "dun"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_HIPRI, "hipri"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_FOTA, "fota"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_IMS, "ims"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_CBS, "cbs"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_IA, "ia"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_EMERGENCY, "emergency"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_MCX, "mcx"); - APN_TYPE_INT_MAP.put(ApnSetting.TYPE_XCAP, "xcap"); - } - - /** - * Copy of ApnSetting#getApnTypesStringFromBitmask for legacy broadcast. - * @param apnTypeBitmask bitmask of APN types. - * @return comma delimited list of APN types. - */ - private static String getApnTypesStringFromBitmask(int apnTypeBitmask) { - List<String> types = new ArrayList<>(); - for (Integer type : APN_TYPE_INT_MAP.keySet()) { - if ((apnTypeBitmask & type) == type) { - types.add(APN_TYPE_INT_MAP.get(type)); - } - } - return android.text.TextUtils.join(",", types); - } - private void enforceNotifyPermissionOrCarrierPrivilege(String method) { if (checkNotifyPermission()) { return; diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index ed3bab97ca19..35a980286d8f 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -218,7 +218,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { // Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up // resources, even for binder death or unwanted calls. synchronized (mTestNetworkTracker) { - mTestNetworkTracker.remove(network.netId); + mTestNetworkTracker.remove(getNetwork().netId); } } } @@ -337,7 +337,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { callingUid, binder); - mTestNetworkTracker.put(agent.network.netId, agent); + mTestNetworkTracker.put(agent.getNetwork().netId, agent); } } catch (SocketException e) { throw new UncheckedIOException(e); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index e2a036aec172..3ffa5dea4d89 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -36,6 +36,7 @@ import android.app.ActivityManagerInternal; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.ApplicationExitInfo; import android.app.IApplicationThread; import android.app.IServiceConnection; import android.app.Notification; @@ -2730,7 +2731,7 @@ public final class ActiveServices { created = true; } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); - mAm.appDiedLocked(app); + mAm.appDiedLocked(app, "Died when creating service"); throw e; } finally { if (!created) { @@ -3649,7 +3650,8 @@ public final class ActiveServices { && proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID && proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { proc.kill("bound to service " + sr.shortInstanceName - + " in dying proc " + (app != null ? app.processName : "??"), true); + + " in dying proc " + (app != null ? app.processName : "??"), + ApplicationExitInfo.REASON_OTHER, true); } } } diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 9085d18167f6..fc4bad722904 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -30,10 +30,14 @@ import android.provider.DeviceConfig.OnPropertiesChangedListener; import android.provider.DeviceConfig.Properties; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArraySet; import android.util.KeyValueListParser; import android.util.Slog; import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; /** * Settings constants that can modify the activity manager's behavior. @@ -65,6 +69,10 @@ final class ActivityManagerConstants extends ContentObserver { = "service_usage_interaction_time"; private static final String KEY_USAGE_STATS_INTERACTION_INTERVAL = "usage_stats_interaction_interval"; + private static final String KEY_IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES = + "imperceptible_kill_exempt_packages"; + private static final String KEY_IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES = + "imperceptible_kill_exempt_proc_states"; static final String KEY_SERVICE_RESTART_DURATION = "service_restart_duration"; static final String KEY_SERVICE_RESET_RUN_DURATION = "service_reset_run_duration"; static final String KEY_SERVICE_RESTART_DURATION_FACTOR = "service_restart_duration_factor"; @@ -282,6 +290,19 @@ final class ActivityManagerConstants extends ContentObserver { // memory trimming. public int CUR_TRIM_CACHED_PROCESSES; + /** + * Packages that can't be killed even if it's requested to be killed on imperceptible. + */ + public ArraySet<String> IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES = new ArraySet<String>(); + + /** + * Proc State that can't be killed even if it's requested to be killed on imperceptible. + */ + public ArraySet<Integer> IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES = new ArraySet<Integer>(); + + private List<String> mDefaultImperceptibleKillExemptPackages; + private List<Integer> mDefaultImperceptibleKillExemptProcStates; + @SuppressWarnings("unused") private static final int OOMADJ_UPDATE_POLICY_SLOW = 0; private static final int OOMADJ_UPDATE_POLICY_QUICK = 1; @@ -332,6 +353,10 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_OOMADJ_UPDATE_POLICY: updateOomAdjUpdatePolicy(); break; + case KEY_IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES: + case KEY_IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES: + updateImperceptibleKillExemptions(); + break; default: break; } @@ -350,6 +375,13 @@ final class ActivityManagerConstants extends ContentObserver { MIN_AUTOMATIC_HEAP_DUMP_PSS_THRESHOLD_BYTES, context.getResources().getInteger( com.android.internal.R.integer.config_debugSystemServerPssThresholdBytes)); + mDefaultImperceptibleKillExemptPackages = Arrays.asList( + context.getResources().getStringArray( + com.android.internal.R.array.config_defaultImperceptibleKillingExemptionPkgs)); + mDefaultImperceptibleKillExemptProcStates = Arrays.stream( + context.getResources().getIntArray( + com.android.internal.R.array.config_defaultImperceptibleKillingExemptionProcStates)) + .boxed().collect(Collectors.toList()); } public void start(ContentResolver resolver) { @@ -371,6 +403,7 @@ final class ActivityManagerConstants extends ContentObserver { updateActivityStartsLoggingEnabled(); updateBackgroundActivityStarts(); updateOomAdjUpdatePolicy(); + updateImperceptibleKillExemptions(); } public void setOverrideMaxCachedProcesses(int value) { @@ -497,6 +530,29 @@ final class ActivityManagerConstants extends ContentObserver { == OOMADJ_UPDATE_POLICY_QUICK; } + private void updateImperceptibleKillExemptions() { + IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.clear(); + IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(mDefaultImperceptibleKillExemptPackages); + String val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES, null); + if (!TextUtils.isEmpty(val)) { + IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(Arrays.asList(val.split(","))); + } + + IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.clear(); + IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.addAll(mDefaultImperceptibleKillExemptProcStates); + val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES, null); + if (!TextUtils.isEmpty(val)) { + Arrays.asList(val.split(",")).stream().forEach((v) -> { + try { + IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.add(Integer.parseInt(v)); + } catch (NumberFormatException e) { + } + }); + } + } + private void updateEnableAutomaticSystemServerHeapDumps() { if (!mSystemServerAutomaticHeapDumpEnabled) { Slog.wtf(TAG, @@ -603,6 +659,10 @@ final class ActivityManagerConstants extends ContentObserver { pw.println(MEMORY_INFO_THROTTLE_TIME); pw.print(" "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("="); pw.println(TOP_TO_FGS_GRACE_DURATION); + pw.print(" "); pw.print(KEY_IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES); pw.print("="); + pw.println(Arrays.toString(IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.toArray())); + pw.print(" "); pw.print(KEY_IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES); pw.print("="); + pw.println(Arrays.toString(IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.toArray())); pw.println(); if (mOverrideMaxCachedProcesses >= 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 883e7c6799dc..b0369752bdaf 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -155,6 +155,7 @@ import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.AppOpsManagerInternal.CheckOpsDelegate; import android.app.ApplicationErrorReport; +import android.app.ApplicationExitInfo; import android.app.ApplicationThreadConstants; import android.app.BroadcastOptions; import android.app.ContentProviderHolder; @@ -684,7 +685,7 @@ public class ActivityManagerService extends IActivityManager.Stub /** * Process management. */ - final ProcessList mProcessList = new ProcessList(); + final ProcessList mProcessList; /** * Tracking long-term execution of processes to look for abuse and other @@ -1534,7 +1535,7 @@ public class ActivityManagerService extends IActivityManager.Stub TAG, "Death received in " + this + " for thread " + mAppThread.asBinder()); synchronized(ActivityManagerService.this) { - appDiedLocked(mApp, mPid, mAppThread, true); + appDiedLocked(mApp, mPid, mAppThread, true, null); } } } @@ -2382,6 +2383,7 @@ public class ActivityManagerService extends IActivityManager.Stub ? new ActivityManagerConstants(mContext, this, mHandler) : null; final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */); mPlatformCompat = null; + mProcessList = injector.getProcessList(this); mProcessList.init(this, activeUids, mPlatformCompat); mLowMemDetector = null; mOomAdjuster = hasHandlerThread @@ -2436,6 +2438,7 @@ public class ActivityManagerService extends IActivityManager.Stub final ActiveUids activeUids = new ActiveUids(this, true /* postChangesToAtm */); mPlatformCompat = (PlatformCompat) ServiceManager.getService( Context.PLATFORM_COMPAT_SERVICE); + mProcessList = mInjector.getProcessList(this); mProcessList.init(this, activeUids, mPlatformCompat); mLowMemDetector = new LowMemDetector(this); mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids); @@ -3680,13 +3683,13 @@ public class ActivityManagerService extends IActivityManager.Stub } @GuardedBy("this") - final void appDiedLocked(ProcessRecord app) { - appDiedLocked(app, app.pid, app.thread, false); + final void appDiedLocked(ProcessRecord app, String reason) { + appDiedLocked(app, app.pid, app.thread, false, reason); } @GuardedBy("this") final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread, - boolean fromBinderDied) { + boolean fromBinderDied, String reason) { // First check if this ProcessRecord is actually active for the pid. synchronized (mPidsSelfLocked) { ProcessRecord curProc = mPidsSelfLocked.get(pid); @@ -3704,6 +3707,8 @@ public class ActivityManagerService extends IActivityManager.Stub if (!app.killed) { if (!fromBinderDied) { killProcessQuiet(pid); + mProcessList.noteAppKill(app, ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_UNKNOWN, reason); } ProcessList.killProcessGroup(app.uid, pid); app.killed = true; @@ -4727,7 +4732,7 @@ public class ActivityManagerService extends IActivityManager.Stub cleanupAppInLaunchingProvidersLocked(app, true); // Take care of any services that are waiting for the process. mServices.processStartTimedOutLocked(app); - app.kill("start timeout", true); + app.kill("start timeout", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true); if (app.isolated) { mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid); } @@ -4814,6 +4819,8 @@ public class ActivityManagerService extends IActivityManager.Stub if (pid > 0 && pid != MY_PID) { killProcessQuiet(pid); //TODO: killProcessGroup(app.info.uid, pid); + mProcessList.noteAppKill(app, ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_UNKNOWN, "attach failed"); } else { try { thread.scheduleExit(); @@ -5153,7 +5160,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (badApp) { - app.kill("error during init", true); + app.kill("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true); handleAppDiedLocked(app, false, true); return false; } @@ -7544,7 +7551,7 @@ public class ActivityManagerService extends IActivityManager.Stub proc.info.uid); final long ident = Binder.clearCallingIdentity(); try { - appDiedLocked(proc); + appDiedLocked(proc, "unstable content provider"); } finally { Binder.restoreCallingIdentity(ident); } @@ -8856,7 +8863,7 @@ public class ActivityManagerService extends IActivityManager.Stub } int adj = proc.setAdj; if (adj >= worstType && !proc.killedByAm) { - proc.kill(reason, true); + proc.kill(reason, ApplicationExitInfo.REASON_OTHER, true); killed = true; } } @@ -8904,7 +8911,7 @@ public class ActivityManagerService extends IActivityManager.Stub final int adj = proc.setAdj; if (adj > belowAdj && !proc.killedByAm) { - proc.kill(reason, true); + proc.kill(reason, ApplicationExitInfo.REASON_PERMISSION_CHANGE, true); killed = true; } } @@ -8912,6 +8919,26 @@ public class ActivityManagerService extends IActivityManager.Stub return killed; } + /** + * Similar to {@link #killPids} but killing will be delayed until the device is idle + * and the given process is imperceptible. + */ + @Override + public void killProcessesWhenImperceptible(int[] pids, String reason) { + if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires permission " + + android.Manifest.permission.FORCE_STOP_PACKAGES); + } + int callerUid = Binder.getCallingUid(); + long iden = Binder.clearCallingIdentity(); + try { + mProcessList.killProcessesWhenImperceptible(pids, reason, callerUid); + } finally { + Binder.restoreCallingIdentity(iden); + } + } + @Override public void hang(final IBinder who, boolean allowRestart) { if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) @@ -9048,7 +9075,10 @@ public class ActivityManagerService extends IActivityManager.Stub TimeUtils.formatDuration(lowRamSinceLastIdle, sb); Slog.wtfQuiet(TAG, sb.toString()); proc.kill("idle maint (pss " + proc.lastPss - + " from " + proc.initialIdlePss + ")", true); + + " from " + proc.initialIdlePss + ")", + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_MEMORY_PRESSURE, + true); } } } else if (proc.setProcState < ActivityManager.PROCESS_STATE_HOME @@ -9145,6 +9175,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Make sure we have the current profile info, since it is needed for security checks. mUserController.onSystemReady(); mAppOpsService.systemReady(); + mProcessList.onSystemReady(); mSystemReady = true; t.traceEnd(); } @@ -9674,7 +9705,7 @@ public class ActivityManagerService extends IActivityManager.Stub * Utility function for addErrorToDropBox and handleStrictModeViolation's logging * to append various headers to the dropbox log text. */ - private void appendDropBoxProcessHeaders(ProcessRecord process, String processName, + void appendDropBoxProcessHeaders(ProcessRecord process, String processName, StringBuilder sb) { // Watchdog thread ends up invoking this function (with // a null ProcessRecord) to add the stack file to dropbox. @@ -9972,6 +10003,67 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public ParceledListSlice<ApplicationExitInfo> getHistoricalProcessExitReasons( + String packageName, int pid, int maxNum, int userId) { + enforceNotIsolatedCaller("getHistoricalProcessExitReasons"); + + // For the simplification, we don't support USER_ALL nor USER_CURRENT here. + if (userId == UserHandle.USER_ALL || userId == UserHandle.USER_CURRENT) { + throw new IllegalArgumentException("Unsupported userId"); + } + + final int callingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); + final int callingUserId = UserHandle.getCallingUserId(); + mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_NON_FULL, + "getHistoricalProcessExitReasons", null); + + final ArrayList<ApplicationExitInfo> results = new ArrayList<ApplicationExitInfo>(); + if (!TextUtils.isEmpty(packageName)) { + final int uid = enforceDumpPermissionForPackage(packageName, userId, callingUid, + "getHistoricalProcessExitReasons"); + if (uid != Process.INVALID_UID) { + mProcessList.mAppExitInfoTracker.getExitInfo( + packageName, uid, pid, maxNum, results); + } + } else { + // If no package name is given, use the caller's uid as the filter uid. + mProcessList.mAppExitInfoTracker.getExitInfo( + packageName, callingUid, pid, maxNum, results); + } + + return new ParceledListSlice<ApplicationExitInfo>(results); + } + + /** + * Check if the calling process has the permission to dump given package, + * throw SecurityException if it doesn't have the permission. + * + * @return The UID of the given package, or {@link android.os.Process#INVALID_UID} + * if the package is not found. + */ + private int enforceDumpPermissionForPackage(String packageName, int userId, int callingUid, + String function) { + long identity = Binder.clearCallingIdentity(); + int uid = Process.INVALID_UID; + try { + uid = mPackageManagerInt.getPackageUid(packageName, + MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId); + } finally { + Binder.restoreCallingIdentity(identity); + } + if (uid == Process.INVALID_UID) { + return Process.INVALID_UID; + } + if (UserHandle.getAppId(uid) != UserHandle.getAppId(callingUid)) { + // Requires the DUMP permission if the target package doesn't belong + // to the caller. + enforceCallingPermission(android.Manifest.permission.DUMP, function); + } + return uid; + } + + @Override public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outState) { if (outState == null) { throw new IllegalArgumentException("outState is null"); @@ -10150,6 +10242,12 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpAll) { pw.println("-------------------------------------------------------------------------------"); } + mProcessList.mAppExitInfoTracker.dumpHistoryProcessExitInfo(pw, dumpPackage); + pw.println(); + if (dumpAll) { + pw.println("-------------------------------------------------------------------" + + "------------"); + } dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage, dumpAppId); pw.println(); if (dumpAll) { @@ -10448,6 +10546,12 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (this) { dumpUsersLocked(pw); } + } else if ("exit-info".equals(cmd)) { + if (opti < args.length) { + dumpPackage = args[opti]; + opti++; + } + mProcessList.mAppExitInfoTracker.dumpHistoryProcessExitInfo(pw, dumpPackage); } else { // Dumping a single activity? if (!mAtmInternal.dumpActivity(fd, pw, cmd, args, opti, dumpAll, @@ -14061,7 +14165,9 @@ public class ActivityManagerService extends IActivityManager.Stub capp.kill("depends on provider " + cpr.name.flattenToShortString() + " in dying proc " + (proc != null ? proc.processName : "??") - + " (adj " + (proc != null ? proc.setAdj : "??") + ")", true); + + " (adj " + (proc != null ? proc.setAdj : "??") + ")", + ApplicationExitInfo.REASON_OTHER, + true); } } else if (capp.thread != null && conn.provider.provider != null) { try { @@ -14146,6 +14252,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Take care of any launching providers waiting for this process. if (cleanupAppInLaunchingProvidersLocked(app, false)) { + mProcessList.noteProcessDiedLocked(app); restart = true; } @@ -14242,6 +14349,7 @@ public class ActivityManagerService extends IActivityManager.Stub mProcessesOnHold.remove(app); mAtmInternal.onCleanUpApplicationRecord(app.getWindowProcessController()); + mProcessList.noteProcessDiedLocked(app); if (restart && !app.isolated) { // We have components that still need to be running in the @@ -16968,7 +17076,10 @@ public class ActivityManagerService extends IActivityManager.Stub uptimeSince, cputimeUsed); } app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince - + " dur=" + checkDur + " limit=" + cpuLimit, true); + + " dur=" + checkDur + " limit=" + cpuLimit, + ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE, + ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU, + true); app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList); for (int ipkg = app.pkgList.size() - 1; ipkg >= 0; ipkg--) { ProcessStats.ProcessStateHolder holder = app.pkgList.valueAt(ipkg); @@ -17602,7 +17713,10 @@ public class ActivityManagerService extends IActivityManager.Stub + (app.thread != null ? app.thread.asBinder() : null) + ")\n"); if (app.pid > 0 && app.pid != MY_PID) { - app.kill("empty", false); + app.kill("empty", + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_TRIM_EMPTY, + false); } else if (app.thread != null) { try { app.thread.scheduleExit(); @@ -18432,7 +18546,7 @@ public class ActivityManagerService extends IActivityManager.Stub final ProcessRecord pr = (ProcessRecord) wpc.mOwner; if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND && pr.curReceivers.isEmpty()) { - pr.kill("remove task", true); + pr.kill("remove task", ApplicationExitInfo.REASON_OTHER, true); } else { // We delay killing processes that are not in the background or running a // receiver. @@ -19237,6 +19351,13 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } + /** + * Return the process list instance + */ + public ProcessList getProcessList(ActivityManagerService service) { + return new ProcessList(); + } + private boolean ensureHasNetworkManagementInternal() { if (mNmi == null) { mNmi = LocalServices.getService(NetworkManagementInternal.class); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index d7ad1c252401..e7d6eb7bb46b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -91,7 +91,6 @@ import android.view.Display; import com.android.internal.compat.CompatibilityChangeConfig; import com.android.internal.util.HexDump; import com.android.internal.util.MemInfoReader; -import com.android.internal.util.Preconditions; import com.android.server.compat.PlatformCompat; import java.io.BufferedReader; @@ -217,6 +216,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runSetWatchHeap(pw); case "clear-watch-heap": return runClearWatchHeap(pw); + case "clear-exit-info": + return runClearExitInfo(pw); case "bug-report": return runBugReport(pw); case "force-stop": @@ -1019,6 +1020,30 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } + int runClearExitInfo(PrintWriter pw) throws RemoteException { + mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS, + "runClearExitInfo()"); + String opt; + int userId = UserHandle.USER_CURRENT; + String packageName = null; + while ((opt = getNextOption()) != null) { + if (opt.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } else { + packageName = opt; + } + } + if (userId == UserHandle.USER_CURRENT) { + UserInfo user = mInterface.getCurrentUser(); + if (user == null) { + return -1; + } + userId = user.id; + } + mInternal.mProcessList.mAppExitInfoTracker.clearHistoryProcessExitInfo(packageName, userId); + return 0; + } + int runBugReport(PrintWriter pw) throws RemoteException { String opt; boolean fullBugreport = true; @@ -1145,7 +1170,7 @@ final class ActivityManagerShellCommand extends ShellCommand { static final int RESULT_ANR_DIALOG = 0; static final int RESULT_ANR_KILL = 1; - static final int RESULT_ANR_WAIT = 1; + static final int RESULT_ANR_WAIT = 2; int mResult; @@ -3008,6 +3033,7 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" s[ervices] [COMP_SPEC ...]: service state"); pw.println(" allowed-associations: current package association restrictions"); pw.println(" as[sociations]: tracked app associations"); + pw.println(" exit-info [PACKAGE_NAME]: historical process exit information"); pw.println(" lmk: stats on low memory killer"); pw.println(" lru: raw LRU process list"); pw.println(" binder-proxies: stats on binder objects and IPCs"); @@ -3142,6 +3168,8 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" above <HEAP-LIMIT> then a heap dump is collected for the user to report."); pw.println(" clear-watch-heap"); pw.println(" Clear the previously set-watch-heap."); + pw.println(" clear-exit-info [--user <USER_ID> | all | current] [package]"); + pw.println(" Clear the process exit-info for given package"); pw.println(" bug-report [--progress | --telephony]"); pw.println(" Request bug report generation; will launch a notification"); pw.println(" when done to select where it should be delivered. Options are:"); diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 8071f52037e6..145f91bdb0b3 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -29,6 +29,7 @@ import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_N import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ApplicationErrorReport; +import android.app.ApplicationExitInfo; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; @@ -315,11 +316,23 @@ class AppErrors { } void killAppAtUserRequestLocked(ProcessRecord app) { - app.getDialogController().clearAllErrorDialogs(); - killAppImmediateLocked(app, "user-terminated", "user request after error"); + ProcessRecord.ErrorDialogController controller = + app.getDialogController(); + + int reasonCode = ApplicationExitInfo.REASON_ANR; + int subReason = ApplicationExitInfo.SUBREASON_UNKNOWN; + if (controller.hasDebugWaitingDialog()) { + reasonCode = ApplicationExitInfo.REASON_OTHER; + subReason = ApplicationExitInfo.SUBREASON_WAIT_FOR_DEBUGGER; + } + + controller.clearAllErrorDialogs(); + killAppImmediateLocked(app, reasonCode, subReason, + "user-terminated", "user request after error"); } - private void killAppImmediateLocked(ProcessRecord app, String reason, String killReason) { + private void killAppImmediateLocked(ProcessRecord app, int reasonCode, int subReason, + String reason, String killReason) { app.setCrashing(false); app.crashingReport = null; app.setNotResponding(false); @@ -327,7 +340,7 @@ class AppErrors { if (app.pid > 0 && app.pid != MY_PID) { handleAppCrashLocked(app, reason, null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/); - app.kill(killReason, true); + app.kill(killReason, reasonCode, subReason, true); } } @@ -381,7 +394,9 @@ class AppErrors { mService.mHandler.postDelayed( () -> { synchronized (mService) { - killAppImmediateLocked(p, "forced", "killed for invalid state"); + killAppImmediateLocked(p, ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_UNKNOWN, + "forced", "killed for invalid state"); } }, 5000L); @@ -422,6 +437,13 @@ class AppErrors { if (r != null) { mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode(), PackageWatchdog.FAILURE_REASON_APP_CRASH); + + mService.mProcessList.noteAppKill(r, (crashInfo != null + && "Native crash".equals(crashInfo.exceptionClassName)) + ? ApplicationExitInfo.REASON_CRASH_NATIVE + : ApplicationExitInfo.REASON_CRASH, + ApplicationExitInfo.SUBREASON_UNKNOWN, + "crash"); } final int relaunchReason = r != null @@ -488,7 +510,8 @@ class AppErrors { stopReportingCrashesLocked(r); } if (res == AppErrorDialog.RESTART) { - mService.mProcessList.removeProcessLocked(r, false, true, "crash"); + mService.mProcessList.removeProcessLocked(r, false, true, "crash", + ApplicationExitInfo.REASON_CRASH); if (taskId != INVALID_TASK_ID) { try { mService.startActivityFromRecents(taskId, @@ -506,7 +529,8 @@ class AppErrors { // Kill it with fire! mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController()); if (!r.isPersistent()) { - mService.mProcessList.removeProcessLocked(r, false, false, "crash"); + mService.mProcessList.removeProcessLocked(r, false, false, "crash", + ApplicationExitInfo.REASON_CRASH); mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */); } } finally { @@ -549,22 +573,26 @@ class AppErrors { return mService.mAtmInternal.handleAppCrashInActivityController( name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace, () -> { - if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) - && "Native crash".equals(crashInfo.exceptionClassName)) { - Slog.w(TAG, "Skip killing native crashed app " + name - + "(" + pid + ") during testing"); - } else { - Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); - if (r != null) { - if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) { - r.kill("crash", true); - } + if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) + && "Native crash".equals(crashInfo.exceptionClassName)) { + Slog.w(TAG, "Skip killing native crashed app " + name + + "(" + pid + ") during testing"); } else { - // Huh. - Process.killProcess(pid); - ProcessList.killProcessGroup(uid, pid); + Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); + if (r != null) { + if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) { + r.kill("crash", ApplicationExitInfo.REASON_CRASH, true); + } + } else { + // Huh. + Process.killProcess(pid); + ProcessList.killProcessGroup(uid, pid); + mService.mProcessList.noteAppKill(pid, uid, + ApplicationExitInfo.REASON_CRASH, + ApplicationExitInfo.SUBREASON_UNKNOWN, + "crash"); + } } - } }); } @@ -719,7 +747,8 @@ class AppErrors { // Don't let services in this process be restarted and potentially // annoy the user repeatedly. Unless it is persistent, since those // processes run critical code. - mService.mProcessList.removeProcessLocked(app, false, tryAgain, "crash"); + mService.mProcessList.removeProcessLocked(app, false, tryAgain, "crash", + ApplicationExitInfo.REASON_CRASH); mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */); if (!showBackground) { return false; diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java new file mode 100644 index 000000000000..6e135d65f127 --- /dev/null +++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java @@ -0,0 +1,1302 @@ +/* + * 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.server.am; + +import static android.app.ActivityManager.RunningAppProcessInfo.procStateToImportance; + +import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; + +import android.app.ApplicationExitInfo; +import android.app.ApplicationExitInfo.Reason; +import android.app.ApplicationExitInfo.SubReason; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.icu.text.SimpleDateFormat; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.system.OsConstants; +import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.AtomicFile; +import android.util.Pair; +import android.util.Pools.SynchronizedPool; +import android.util.Slog; +import android.util.SparseArray; +import android.util.proto.ProtoInputStream; +import android.util.proto.ProtoOutputStream; +import android.util.proto.WireTypeMismatchException; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.app.ProcessMap; +import com.android.server.IoThread; +import com.android.server.SystemServiceManager; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; + +/** + * A class to manage all the {@link android.app.ApplicationExitInfo} records. + */ +public final class AppExitInfoTracker { + private static final String TAG = TAG_WITH_CLASS_NAME ? "AppExitInfoTracker" : TAG_AM; + + /** + * Interval of persisting the app exit info to persistent storage. + */ + private static final long APP_EXIT_INFO_PERSIST_INTERVAL = TimeUnit.MINUTES.toMillis(30); + + /** These are actions that the forEachPackage should take after each iteration */ + private static final int FOREACH_ACTION_NONE = 0; + private static final int FOREACH_ACTION_REMOVE_PACKAGE = 1; + private static final int FOREACH_ACTION_STOP_ITERATION = 2; + + private static final int APP_EXIT_RAW_INFO_POOL_SIZE = 8; + + @VisibleForTesting + static final String APP_EXIT_INFO_FILE = "procexitinfo"; + + private final Object mLock = new Object(); + + /** + * Initialized in {@link #init} and read-only after that. + */ + private ActivityManagerService mService; + + /** + * Initialized in {@link #init} and read-only after that. + */ + private KillHandler mKillHandler; + + /** + * The task to persist app process exit info + */ + @GuardedBy("mLock") + private Runnable mAppExitInfoPersistTask = null; + + /** + * Last time(in ms) since epoch that the app exit info was persisted into persistent storage. + */ + @GuardedBy("mLock") + private long mLastAppExitInfoPersistTimestamp = 0L; + + /** + * Retention policy: keep up to X historical exit info per package. + * + * Initialized in {@link #init} and read-only after that. + * Not lock is needed. + */ + private int mAppExitInfoHistoryListSize; + + /* + * PackageName/uid -> [pid/info, ...] holder, the uid here is the package uid. + */ + @GuardedBy("mLock") + private final ProcessMap<AppExitInfoContainer> mData; + + /** A pool of raw {@link android.app.ApplicationExitInfo} records. */ + @GuardedBy("mService") + private final SynchronizedPool<ApplicationExitInfo> mRawRecordsPool; + + /** + * Wheather or not we've loaded the historical app process exit info from + * persistent storage. + */ + @VisibleForTesting + @GuardedBy("mLock") + boolean mAppExitInfoLoaded = false; + + /** + * Temporary list being used to filter/sort intermediate results in {@link #getExitInfo}. + */ + @GuardedBy("mLock") + final ArrayList<ApplicationExitInfo> mTmpInfoList = new ArrayList<ApplicationExitInfo>(); + + /** + * Temporary list being used to filter/sort intermediate results in {@link #getExitInfo}. + */ + @GuardedBy("mLock") + final ArrayList<ApplicationExitInfo> mTmpInfoList2 = new ArrayList<ApplicationExitInfo>(); + + /** + * The path to the historical proc exit info file, persisted in the storage. + */ + @VisibleForTesting + File mProcExitInfoFile; + + /** + * Mapping between the isolated UID to its application uid. + */ + final IsolatedUidRecords mIsolatedUidRecords = + new IsolatedUidRecords(); + + /** + * Bookkeeping app process exit info from Zygote. + */ + final AppExitInfoExternalSource mAppExitInfoSourceZygote = + new AppExitInfoExternalSource("zygote", null); + + /** + * Bookkeeping low memory kills info from lmkd. + */ + final AppExitInfoExternalSource mAppExitInfoSourceLmkd = + new AppExitInfoExternalSource("lmkd", ApplicationExitInfo.REASON_LOW_MEMORY); + + AppExitInfoTracker() { + mData = new ProcessMap<AppExitInfoContainer>(); + mRawRecordsPool = new SynchronizedPool<ApplicationExitInfo>(APP_EXIT_RAW_INFO_POOL_SIZE); + } + + void init(ActivityManagerService service, Looper looper) { + mService = service; + mKillHandler = new KillHandler(looper); + mProcExitInfoFile = new File(SystemServiceManager.ensureSystemDir(), APP_EXIT_INFO_FILE); + + mAppExitInfoHistoryListSize = service.mContext.getResources().getInteger( + com.android.internal.R.integer.config_app_exit_info_history_list_size); + } + + void onSystemReady() { + // Read the sysprop set by lmkd and set this to persist so app could read it. + SystemProperties.set("persist.sys.lmk.reportkills", + Boolean.toString(SystemProperties.getBoolean("sys.lmk.reportkills", false))); + registerForUserRemoval(); + registerForPackageRemoval(); + IoThread.getHandler().post(this::loadExistingProcessExitInfo); + } + + @GuardedBy("mService") + void scheduleNoteProcessDiedLocked(final ProcessRecord app) { + if (app == null || app.info == null) { + return; + } + + synchronized (mLock) { + if (!mAppExitInfoLoaded) { + return; + } + } + // The current thread is holding the global lock, let's extract the info from it + // and schedule the info note task in the kill handler. + mKillHandler.obtainMessage(KillHandler.MSG_PROC_DIED, obtainRawRecordLocked(app)) + .sendToTarget(); + } + + void scheduleNoteAppKill(final ProcessRecord app, final @Reason int reason, + final @SubReason int subReason, final String msg) { + synchronized (mLock) { + if (!mAppExitInfoLoaded) { + return; + } + } + synchronized (mService) { + if (app == null || app.info == null) { + return; + } + + ApplicationExitInfo raw = obtainRawRecordLocked(app); + raw.setReason(reason); + raw.setSubReason(subReason); + raw.setDescription(msg); + mKillHandler.obtainMessage(KillHandler.MSG_APP_KILL, raw).sendToTarget(); + } + } + + void scheduleNoteAppKill(final int pid, final int uid, final @Reason int reason, + final @SubReason int subReason, final String msg) { + synchronized (mLock) { + if (!mAppExitInfoLoaded) { + return; + } + } + synchronized (mService) { + ProcessRecord app; + synchronized (mService.mPidsSelfLocked) { + app = mService.mPidsSelfLocked.get(pid); + } + if (app == null) { + if (DEBUG_PROCESSES) { + Slog.w(TAG, "Skipping saving the kill reason for pid " + pid + + "(uid=" + uid + ") since its process record is not found"); + } + } else { + scheduleNoteAppKill(app, reason, subReason, msg); + } + } + } + + interface LmkdKillListener { + /** + * Called when there is a process kill by lmkd. + */ + void onLmkdKillOccurred(int pid, int uid); + } + + void setLmkdKillListener(final LmkdKillListener listener) { + synchronized (mLock) { + mAppExitInfoSourceLmkd.setOnProcDiedListener((pid, uid) -> + listener.onLmkdKillOccurred(pid, uid)); + } + } + + /** Called when there is a low memory kill */ + void scheduleNoteLmkdProcKilled(final int pid, final int uid) { + mKillHandler.obtainMessage(KillHandler.MSG_LMKD_PROC_KILLED, pid, uid) + .sendToTarget(); + } + + private void scheduleChildProcDied(int pid, int uid, int status) { + mKillHandler.obtainMessage(KillHandler.MSG_CHILD_PROC_DIED, pid, uid, (Integer) status) + .sendToTarget(); + } + + /** Calls when zygote sends us SIGCHLD */ + void handleZygoteSigChld(int pid, int uid, int status) { + if (DEBUG_PROCESSES) { + Slog.i(TAG, "Got SIGCHLD from zygote: pid=" + pid + ", uid=" + uid + + ", status=" + Integer.toHexString(status)); + } + scheduleChildProcDied(pid, uid, status); + } + + /** + * Main routine to create or update the {@link android.app.ApplicationExitInfo} for the given + * ProcessRecord, also query the zygote and lmkd records to make the information more accurate. + */ + @VisibleForTesting + @GuardedBy("mLock") + void handleNoteProcessDiedLocked(final ApplicationExitInfo raw) { + if (raw != null) { + if (DEBUG_PROCESSES) { + Slog.i(TAG, "Update process exit info for " + raw.getPackageName() + + "(" + raw.getPid() + "/u" + raw.getRealUid() + ")"); + } + + ApplicationExitInfo info = getExitInfo(raw.getPackageName(), + raw.getPackageUid(), raw.getPid()); + + // query zygote and lmkd to get the exit info, and clear the saved info + Pair<Long, Object> zygote = mAppExitInfoSourceZygote.remove( + raw.getPid(), raw.getRealUid()); + Pair<Long, Object> lmkd = mAppExitInfoSourceLmkd.remove( + raw.getPid(), raw.getRealUid()); + mIsolatedUidRecords.removeIsolatedUid(raw.getRealUid()); + + if (info == null) { + info = addExitInfoLocked(raw); + } + + if (lmkd != null) { + updateExistingExitInfoRecordLocked(info, null, + ApplicationExitInfo.REASON_LOW_MEMORY); + } else if (zygote != null) { + updateExistingExitInfoRecordLocked(info, (Integer) zygote.second, null); + } + } + } + + /** + * Make note when ActivityManagerService decides to kill an application process. + */ + @VisibleForTesting + @GuardedBy("mLock") + void handleNoteAppKillLocked(final ApplicationExitInfo raw) { + ApplicationExitInfo info = getExitInfo( + raw.getPackageName(), raw.getPackageUid(), raw.getPid()); + + if (info == null) { + addExitInfoLocked(raw); + } else { + // always override the existing info since we are now more informational. + info.setReason(raw.getReason()); + info.setStatus(0); + info.setTimestamp(System.currentTimeMillis()); + info.setDescription(raw.getDescription()); + } + } + + @GuardedBy("mLock") + private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw) { + if (!mAppExitInfoLoaded) { + Slog.w(TAG, "Skipping saving the exit info due to ongoing loading from storage"); + return null; + } + + final ApplicationExitInfo info = new ApplicationExitInfo(raw); + final String[] packages = raw.getPackageList(); + final int uid = raw.getPackageUid(); + for (int i = 0; i < packages.length; i++) { + addExitInfoInner(packages[i], uid, info); + } + + schedulePersistProcessExitInfo(false); + + return info; + } + + /** + * Update an existing {@link android.app.ApplicationExitInfo} record with given information. + */ + @GuardedBy("mLock") + private void updateExistingExitInfoRecordLocked(ApplicationExitInfo info, + Integer status, Integer reason) { + if (info == null || !isFresh(info.getTimestamp())) { + // if the record is way outdated, don't update it then (because of potential pid reuse) + return; + } + if (status != null) { + if (OsConstants.WIFEXITED(status)) { + info.setReason(ApplicationExitInfo.REASON_EXIT_SELF); + info.setStatus(OsConstants.WEXITSTATUS(status)); + } else if (OsConstants.WIFSIGNALED(status)) { + if (info.getReason() == ApplicationExitInfo.REASON_UNKNOWN) { + info.setReason(ApplicationExitInfo.REASON_SIGNALED); + info.setStatus(OsConstants.WTERMSIG(status)); + } else if (info.getReason() == ApplicationExitInfo.REASON_CRASH_NATIVE) { + info.setStatus(OsConstants.WTERMSIG(status)); + } + } + } + if (reason != null) { + info.setReason(reason); + } + } + + /** + * Update an existing {@link android.app.ApplicationExitInfo} record with given information. + * + * @return true if a recond is updated + */ + private boolean updateExitInfoIfNecessary(int pid, int uid, Integer status, Integer reason) { + synchronized (mLock) { + if (UserHandle.isIsolated(uid)) { + Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid); + if (k != null) { + uid = k; + } + } + ArrayList<ApplicationExitInfo> tlist = mTmpInfoList; + tlist.clear(); + final int targetUid = uid; + forEachPackage((packageName, records) -> { + AppExitInfoContainer container = records.get(targetUid); + if (container == null) { + return FOREACH_ACTION_NONE; + } + tlist.clear(); + container.getExitInfoLocked(pid, 1, tlist); + if (tlist.size() == 0) { + return FOREACH_ACTION_NONE; + } + ApplicationExitInfo info = tlist.get(0); + if (info.getRealUid() != targetUid) { + tlist.clear(); + return FOREACH_ACTION_NONE; + } + // Okay found it, update its reason. + updateExistingExitInfoRecordLocked(info, status, reason); + + return FOREACH_ACTION_STOP_ITERATION; + }); + return tlist.size() > 0; + } + } + + /** + * Get the exit info with matching package name, filterUid and filterPid (if > 0) + */ + @VisibleForTesting + void getExitInfo(final String packageName, final int filterUid, + final int filterPid, final int maxNum, final ArrayList<ApplicationExitInfo> results) { + synchronized (mLock) { + boolean emptyPackageName = TextUtils.isEmpty(packageName); + if (!emptyPackageName) { + // fast path + AppExitInfoContainer container = mData.get(packageName, filterUid); + if (container != null) { + container.getExitInfoLocked(filterPid, maxNum, results); + } + } else { + // slow path + final ArrayList<ApplicationExitInfo> list = mTmpInfoList2; + list.clear(); + // get all packages + forEachPackage((name, records) -> { + AppExitInfoContainer container = records.get(filterUid); + if (container != null) { + mTmpInfoList.clear(); + results.addAll(container.toListLocked(mTmpInfoList, filterPid)); + } + return AppExitInfoTracker.FOREACH_ACTION_NONE; + }); + + Collections.sort(list, (a, b) -> (int) (b.getTimestamp() - a.getTimestamp())); + int size = list.size(); + if (maxNum > 0) { + size = Math.min(size, maxNum); + } + for (int i = 0; i < size; i++) { + results.add(list.get(i)); + } + list.clear(); + } + } + } + + /** + * Return the first matching exit info record, for internal use, the parameters are not supposed + * to be empty. + */ + private ApplicationExitInfo getExitInfo(final String packageName, + final int filterUid, final int filterPid) { + synchronized (mLock) { + ArrayList<ApplicationExitInfo> list = mTmpInfoList; + list.clear(); + getExitInfo(packageName, filterUid, filterPid, 1, list); + + ApplicationExitInfo info = list.size() > 0 ? list.get(0) : null; + list.clear(); + return info; + } + } + + @VisibleForTesting + void onUserRemoved(int userId) { + mAppExitInfoSourceZygote.removeByUserId(userId); + mAppExitInfoSourceLmkd.removeByUserId(userId); + mIsolatedUidRecords.removeByUserId(userId); + removeByUserId(userId); + schedulePersistProcessExitInfo(true); + } + + @VisibleForTesting + void onPackageRemoved(String packageName, int uid, boolean allUsers) { + if (packageName != null) { + mAppExitInfoSourceZygote.removeByUid(uid, allUsers); + mAppExitInfoSourceLmkd.removeByUid(uid, allUsers); + mIsolatedUidRecords.removeAppUid(uid, allUsers); + removePackage(packageName, allUsers ? UserHandle.USER_ALL : UserHandle.getUserId(uid)); + schedulePersistProcessExitInfo(true); + } + } + + private void registerForUserRemoval() { + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_USER_REMOVED); + mService.mContext.registerReceiverForAllUsers(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + if (userId < 1) return; + onUserRemoved(userId); + } + }, filter, null, mKillHandler); + } + + private void registerForPackageRemoval() { + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addDataScheme("package"); + mService.mContext.registerReceiverForAllUsers(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int uid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL); + boolean allUsers = intent.getBooleanExtra( + Intent.EXTRA_REMOVED_FOR_ALL_USERS, false); + onPackageRemoved(intent.getData().getSchemeSpecificPart(), uid, allUsers); + } + }, filter, null, mKillHandler); + } + + /** + * Load the existing {@link android.app.ApplicationExitInfo} records from persistent storage. + */ + @VisibleForTesting + void loadExistingProcessExitInfo() { + if (!mProcExitInfoFile.canRead()) { + synchronized (mLock) { + mAppExitInfoLoaded = true; + } + return; + } + + FileInputStream fin = null; + try { + AtomicFile af = new AtomicFile(mProcExitInfoFile); + fin = af.openRead(); + ProtoInputStream proto = new ProtoInputStream(fin); + for (int next = proto.nextField(); + next != ProtoInputStream.NO_MORE_FIELDS; + next = proto.nextField()) { + switch (next) { + case (int) AppsExitInfoProto.LAST_UPDATE_TIMESTAMP: + synchronized (mLock) { + mLastAppExitInfoPersistTimestamp = + proto.readLong(AppsExitInfoProto.LAST_UPDATE_TIMESTAMP); + } + break; + case (int) AppsExitInfoProto.PACKAGES: + loadPackagesFromProto(proto, next); + break; + } + } + } catch (IOException | IllegalArgumentException | WireTypeMismatchException e) { + Slog.w(TAG, "Error in loading historical app exit info from persistent storage: " + e); + } finally { + if (fin != null) { + try { + fin.close(); + } catch (IOException e) { + } + } + } + synchronized (mLock) { + mAppExitInfoLoaded = true; + } + } + + private void loadPackagesFromProto(ProtoInputStream proto, long fieldId) + throws IOException, WireTypeMismatchException { + long token = proto.start(fieldId); + String pkgName = ""; + for (int next = proto.nextField(); + next != ProtoInputStream.NO_MORE_FIELDS; + next = proto.nextField()) { + switch (next) { + case (int) AppsExitInfoProto.Package.PACKAGE_NAME: + pkgName = proto.readString(AppsExitInfoProto.Package.PACKAGE_NAME); + break; + case (int) AppsExitInfoProto.Package.USERS: + AppExitInfoContainer container = new AppExitInfoContainer( + mAppExitInfoHistoryListSize); + int uid = container.readFromProto(proto, AppsExitInfoProto.Package.USERS); + synchronized (mLock) { + mData.put(pkgName, uid, container); + } + break; + } + } + proto.end(token); + } + + /** + * Persist the existing {@link android.app.ApplicationExitInfo} records to storage. + */ + @VisibleForTesting + void persistProcessExitInfo() { + AtomicFile af = new AtomicFile(mProcExitInfoFile); + FileOutputStream out = null; + long now = System.currentTimeMillis(); + try { + out = af.startWrite(); + ProtoOutputStream proto = new ProtoOutputStream(out); + proto.write(AppsExitInfoProto.LAST_UPDATE_TIMESTAMP, now); + synchronized (mLock) { + forEachPackage((packageName, records) -> { + long token = proto.start(AppsExitInfoProto.PACKAGES); + proto.write(AppsExitInfoProto.Package.PACKAGE_NAME, packageName); + int uidArraySize = records.size(); + for (int j = 0; j < uidArraySize; j++) { + records.valueAt(j).writeToProto(proto, AppsExitInfoProto.Package.USERS); + } + proto.end(token); + return AppExitInfoTracker.FOREACH_ACTION_NONE; + }); + mLastAppExitInfoPersistTimestamp = now; + } + proto.flush(); + af.finishWrite(out); + } catch (IOException e) { + Slog.w(TAG, "Unable to write historical app exit info into persistent storage: " + e); + af.failWrite(out); + } + synchronized (mLock) { + mAppExitInfoPersistTask = null; + } + } + + /** + * Schedule a task to persist the {@link android.app.ApplicationExitInfo} records to storage. + */ + @VisibleForTesting + void schedulePersistProcessExitInfo(boolean immediately) { + synchronized (mLock) { + if (mAppExitInfoPersistTask == null || immediately) { + if (mAppExitInfoPersistTask != null) { + IoThread.getHandler().removeCallbacks(mAppExitInfoPersistTask); + } + mAppExitInfoPersistTask = this::persistProcessExitInfo; + IoThread.getHandler().postDelayed(mAppExitInfoPersistTask, + immediately ? 0 : APP_EXIT_INFO_PERSIST_INTERVAL); + } + } + } + + /** + * Helper function for testing only. + */ + @VisibleForTesting + void clearProcessExitInfo(boolean removeFile) { + synchronized (mLock) { + if (mAppExitInfoPersistTask != null) { + IoThread.getHandler().removeCallbacks(mAppExitInfoPersistTask); + mAppExitInfoPersistTask = null; + } + if (removeFile && mProcExitInfoFile != null) { + mProcExitInfoFile.delete(); + } + mData.getMap().clear(); + } + } + + /** + * Helper function for shell command + */ + void clearHistoryProcessExitInfo(String packageName, int userId) { + synchronized (mLock) { + if (TextUtils.isEmpty(packageName)) { + if (userId == UserHandle.USER_ALL) { + mData.getMap().clear(); + } else { + removeByUserId(userId); + } + } else { + removePackage(packageName, userId); + } + } + schedulePersistProcessExitInfo(true); + } + + void dumpHistoryProcessExitInfo(PrintWriter pw, String packageName) { + pw.println("ACTIVITY MANAGER LRU PROCESSES (dumpsys activity exit-info)"); + SimpleDateFormat sdf = new SimpleDateFormat(); + synchronized (mLock) { + pw.println("Last Timestamp of Persistence Into Persistent Storage: " + + sdf.format(new Date(mLastAppExitInfoPersistTimestamp))); + if (TextUtils.isEmpty(packageName)) { + forEachPackage((name, records) -> { + dumpHistoryProcessExitInfoLocked(pw, " ", name, records, sdf); + return AppExitInfoTracker.FOREACH_ACTION_NONE; + }); + } else { + SparseArray<AppExitInfoContainer> array = mData.getMap().get(packageName); + if (array != null) { + dumpHistoryProcessExitInfoLocked(pw, " ", packageName, array, sdf); + } + } + } + } + + @GuardedBy("mLock") + private void dumpHistoryProcessExitInfoLocked(PrintWriter pw, String prefix, + String packageName, SparseArray<AppExitInfoContainer> array, + SimpleDateFormat sdf) { + pw.println(prefix + "package: " + packageName); + int size = array.size(); + for (int i = 0; i < size; i++) { + pw.println(prefix + " Historical Process Exit for userId=" + array.keyAt(i)); + array.valueAt(i).dumpLocked(pw, prefix + " ", sdf); + } + } + + private void addExitInfoInner(String packageName, int userId, ApplicationExitInfo info) { + synchronized (mLock) { + AppExitInfoContainer container = mData.get(packageName, userId); + if (container == null) { + container = new AppExitInfoContainer(mAppExitInfoHistoryListSize); + if (UserHandle.isIsolated(info.getRealUid())) { + Integer k = mIsolatedUidRecords.getUidByIsolatedUid(info.getRealUid()); + if (k != null) { + container.mUid = k; + } + } else { + container.mUid = info.getRealUid(); + } + mData.put(packageName, userId, container); + } + container.addExitInfoLocked(info); + } + } + + private void forEachPackage( + BiFunction<String, SparseArray<AppExitInfoContainer>, Integer> callback) { + if (callback != null) { + synchronized (mLock) { + ArrayMap<String, SparseArray<AppExitInfoContainer>> map = mData.getMap(); + for (int i = map.size() - 1; i >= 0; i--) { + switch (callback.apply(map.keyAt(i), map.valueAt(i))) { + case FOREACH_ACTION_REMOVE_PACKAGE: + map.removeAt(i); + break; + case FOREACH_ACTION_STOP_ITERATION: + i = 0; + break; + case FOREACH_ACTION_NONE: + default: + break; + } + } + } + } + } + + private void removePackage(String packageName, int userId) { + synchronized (mLock) { + if (userId == UserHandle.USER_ALL) { + mData.getMap().remove(packageName); + } else { + ArrayMap<String, SparseArray<AppExitInfoContainer>> map = + mData.getMap(); + SparseArray<AppExitInfoContainer> array = map.get(packageName); + if (array == null) { + return; + } + for (int i = array.size() - 1; i >= 0; i--) { + if (UserHandle.getUserId(array.keyAt(i)) == userId) { + array.removeAt(i); + break; + } + } + if (array.size() == 0) { + map.remove(packageName); + } + } + } + } + + private void removeByUserId(final int userId) { + if (userId == UserHandle.USER_ALL) { + synchronized (mLock) { + mData.getMap().clear(); + } + return; + } + forEachPackage((packageName, records) -> { + for (int i = records.size() - 1; i >= 0; i--) { + if (UserHandle.getUserId(records.keyAt(i)) == userId) { + records.removeAt(i); + break; + } + } + return records.size() == 0 ? FOREACH_ACTION_REMOVE_PACKAGE : FOREACH_ACTION_NONE; + }); + } + + @VisibleForTesting + @GuardedBy("mService") + ApplicationExitInfo obtainRawRecordLocked(ProcessRecord app) { + ApplicationExitInfo info = mRawRecordsPool.acquire(); + if (info == null) { + info = new ApplicationExitInfo(); + } + + final int definingUid = app.hostingRecord != null ? app.hostingRecord.getDefiningUid() : 0; + info.setPid(app.pid); + info.setRealUid(app.uid); + info.setPackageUid(app.info.uid); + info.setDefiningUid(definingUid > 0 ? definingUid : app.info.uid); + info.setProcessName(app.processName); + info.setConnectionGroup(app.connectionGroup); + info.setPackageName(app.info.packageName); + info.setPackageList(app.getPackageList()); + info.setReason(ApplicationExitInfo.REASON_UNKNOWN); + info.setStatus(0); + info.setImportance(procStateToImportance(app.setProcState)); + info.setPss(app.lastMemInfo == null ? 0 : app.lastMemInfo.getTotalPss()); + info.setRss(app.lastMemInfo == null ? 0 : app.lastMemInfo.getTotalRss()); + info.setTimestamp(System.currentTimeMillis()); + + return info; + } + + @VisibleForTesting + @GuardedBy("mService") + void recycleRawRecordLocked(ApplicationExitInfo info) { + info.setProcessName(null); + info.setDescription(null); + info.setPackageList(null); + + mRawRecordsPool.release(info); + } + + /** + * A container class of {@link android.app.ApplicationExitInfo} + */ + final class AppExitInfoContainer { + private SparseArray<ApplicationExitInfo> mInfos; // index is pid + private int mMaxCapacity; + private int mUid; // Application uid, not isolated uid. + + AppExitInfoContainer(final int maxCapacity) { + mInfos = new SparseArray<ApplicationExitInfo>(); + mMaxCapacity = maxCapacity; + } + + @GuardedBy("mLock") + void getExitInfoLocked(final int filterPid, final int maxNum, + ArrayList<ApplicationExitInfo> results) { + if (filterPid > 0) { + ApplicationExitInfo r = mInfos.get(filterPid); + if (r != null) { + results.add(r); + } + } else { + final int numRep = mInfos.size(); + if (maxNum <= 0 || numRep <= maxNum) { + // Return all records. + for (int i = 0; i < numRep; i++) { + results.add(mInfos.valueAt(i)); + } + Collections.sort(results, + (a, b) -> (int) (b.getTimestamp() - a.getTimestamp())); + } else { + if (maxNum == 1) { + // Most of the caller might be only interested with the most recent one + ApplicationExitInfo r = mInfos.valueAt(0); + for (int i = 1; i < numRep; i++) { + ApplicationExitInfo t = mInfos.valueAt(i); + if (r.getTimestamp() < t.getTimestamp()) { + r = t; + } + } + results.add(r); + } else { + // Huh, need to sort it out then. + ArrayList<ApplicationExitInfo> list = mTmpInfoList2; + list.clear(); + for (int i = 0; i < numRep; i++) { + list.add(mInfos.valueAt(i)); + } + Collections.sort(list, + (a, b) -> (int) (b.getTimestamp() - a.getTimestamp())); + for (int i = 0; i < maxNum; i++) { + results.add(list.get(i)); + } + list.clear(); + } + } + } + } + + @GuardedBy("mLock") + void addExitInfoLocked(ApplicationExitInfo info) { + int size; + if ((size = mInfos.size()) >= mMaxCapacity) { + int oldestIndex = -1; + long oldestTimeStamp = Long.MAX_VALUE; + for (int i = 0; i < size; i++) { + ApplicationExitInfo r = mInfos.valueAt(i); + if (r.getTimestamp() < oldestTimeStamp) { + oldestTimeStamp = r.getTimestamp(); + oldestIndex = i; + } + } + if (oldestIndex >= 0) { + mInfos.removeAt(oldestIndex); + } + } + mInfos.append(info.getPid(), info); + } + + @GuardedBy("mLock") + void dumpLocked(PrintWriter pw, String prefix, SimpleDateFormat sdf) { + ArrayList<ApplicationExitInfo> list = new ArrayList<ApplicationExitInfo>(); + for (int i = mInfos.size() - 1; i >= 0; i--) { + list.add(mInfos.valueAt(i)); + } + Collections.sort(list, (a, b) -> (int) (b.getTimestamp() - a.getTimestamp())); + int size = list.size(); + for (int i = 0; i < size; i++) { + list.get(i).dump(pw, prefix + " ", "#" + i, sdf); + } + } + + @GuardedBy("mLock") + void writeToProto(ProtoOutputStream proto, long fieldId) { + long token = proto.start(fieldId); + proto.write(AppsExitInfoProto.Package.User.UID, mUid); + int size = mInfos.size(); + for (int i = 0; i < size; i++) { + mInfos.valueAt(i).writeToProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO); + } + proto.end(token); + } + + int readFromProto(ProtoInputStream proto, long fieldId) + throws IOException, WireTypeMismatchException { + long token = proto.start(fieldId); + for (int next = proto.nextField(); + next != ProtoInputStream.NO_MORE_FIELDS; + next = proto.nextField()) { + switch (next) { + case (int) AppsExitInfoProto.Package.User.UID: + mUid = proto.readInt(AppsExitInfoProto.Package.User.UID); + break; + case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO: + ApplicationExitInfo info = new ApplicationExitInfo(); + info.readFromProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO); + mInfos.put(info.getPid(), info); + break; + } + } + proto.end(token); + return mUid; + } + + @GuardedBy("mLock") + List<ApplicationExitInfo> toListLocked(List<ApplicationExitInfo> list, int filterPid) { + if (list == null) { + list = new ArrayList<ApplicationExitInfo>(); + } + for (int i = mInfos.size() - 1; i >= 0; i--) { + if (filterPid == 0 || filterPid == mInfos.keyAt(i)) { + list.add(mInfos.valueAt(i)); + } + } + return list; + } + } + + /** + * Maintains the mapping between real UID and the application uid. + */ + final class IsolatedUidRecords { + /** + * A mapping from application uid (with the userId) to isolated uids. + */ + @GuardedBy("mLock") + private final SparseArray<ArraySet<Integer>> mUidToIsolatedUidMap; + + /** + * A mapping from isolated uids to application uid (with the userId) + */ + @GuardedBy("mLock") + private final SparseArray<Integer> mIsolatedUidToUidMap; + + IsolatedUidRecords() { + mUidToIsolatedUidMap = new SparseArray<ArraySet<Integer>>(); + mIsolatedUidToUidMap = new SparseArray<Integer>(); + } + + void addIsolatedUid(int isolatedUid, int uid) { + synchronized (mLock) { + ArraySet<Integer> set = mUidToIsolatedUidMap.get(uid); + if (set == null) { + set = new ArraySet<Integer>(); + mUidToIsolatedUidMap.put(uid, set); + } + set.add(isolatedUid); + + mIsolatedUidToUidMap.put(isolatedUid, uid); + } + } + + Integer getUidByIsolatedUid(int isolatedUid) { + if (UserHandle.isIsolated(isolatedUid)) { + synchronized (mLock) { + return mIsolatedUidToUidMap.get(isolatedUid); + } + } + return isolatedUid; + } + + @GuardedBy("mLock") + private void removeAppUidLocked(int uid) { + ArraySet<Integer> set = mUidToIsolatedUidMap.get(uid); + if (set != null) { + for (int i = set.size() - 1; i >= 0; i--) { + int isolatedUid = set.removeAt(i); + mIsolatedUidToUidMap.remove(isolatedUid); + } + } + } + + void removeAppUid(int uid, boolean allUsers) { + synchronized (mLock) { + if (allUsers) { + uid = UserHandle.getAppId(uid); + for (int i = mUidToIsolatedUidMap.size() - 1; i >= 0; i--) { + int u = mUidToIsolatedUidMap.keyAt(i); + if (uid == UserHandle.getAppId(u)) { + removeAppUidLocked(u); + } + mUidToIsolatedUidMap.removeAt(i); + } + } else { + removeAppUidLocked(uid); + mUidToIsolatedUidMap.remove(uid); + } + } + } + + int removeIsolatedUid(int isolatedUid) { + if (!UserHandle.isIsolated(isolatedUid)) { + return isolatedUid; + } + synchronized (mLock) { + int uid = mIsolatedUidToUidMap.get(isolatedUid, -1); + if (uid == -1) { + return isolatedUid; + } + mIsolatedUidToUidMap.remove(isolatedUid); + ArraySet<Integer> set = mUidToIsolatedUidMap.get(uid); + if (set != null) { + set.remove(isolatedUid); + } + // let the ArraySet stay in the mUidToIsolatedUidMap even if it's empty + return uid; + } + } + + void removeByUserId(int userId) { + if (userId == UserHandle.USER_CURRENT) { + userId = mService.mUserController.getCurrentUserId(); + } + synchronized (mLock) { + if (userId == UserHandle.USER_ALL) { + mIsolatedUidToUidMap.clear(); + mUidToIsolatedUidMap.clear(); + return; + } + for (int i = mIsolatedUidToUidMap.size() - 1; i >= 0; i--) { + int isolatedUid = mIsolatedUidToUidMap.keyAt(i); + int uid = mIsolatedUidToUidMap.valueAt(i); + if (UserHandle.getUserId(uid) == userId) { + mIsolatedUidToUidMap.removeAt(i); + mUidToIsolatedUidMap.remove(uid); + } + } + } + } + } + + final class KillHandler extends Handler { + static final int MSG_LMKD_PROC_KILLED = 4101; + static final int MSG_CHILD_PROC_DIED = 4102; + static final int MSG_PROC_DIED = 4103; + static final int MSG_APP_KILL = 4104; + + KillHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_LMKD_PROC_KILLED: + mAppExitInfoSourceLmkd.onProcDied(msg.arg1 /* pid */, msg.arg2 /* uid */, + null /* status */); + break; + case MSG_CHILD_PROC_DIED: + mAppExitInfoSourceZygote.onProcDied(msg.arg1 /* pid */, msg.arg2 /* uid */, + (Integer) msg.obj /* status */); + break; + case MSG_PROC_DIED: { + ApplicationExitInfo raw = (ApplicationExitInfo) msg.obj; + synchronized (mLock) { + handleNoteProcessDiedLocked(raw); + } + synchronized (mService) { + recycleRawRecordLocked(raw); + } + } + break; + case MSG_APP_KILL: { + ApplicationExitInfo raw = (ApplicationExitInfo) msg.obj; + synchronized (mLock) { + handleNoteAppKillLocked(raw); + } + synchronized (mService) { + recycleRawRecordLocked(raw); + } + } + break; + default: + super.handleMessage(msg); + } + } + } + + private static boolean isFresh(long timestamp) { + // A process could be dying but being stuck in some state, i.e., + // being TRACED by tombstoned, thus the zygote receives SIGCHILD + // way after we already knew the kill (maybe because we did the kill :P), + // so here check if the last known kill information is "fresh" enough. + long now = System.currentTimeMillis(); + + return (timestamp + AppExitInfoExternalSource.APP_EXIT_INFO_FRESHNESS_MS) >= now; + } + + /** + * Keep the raw information about app kills from external sources, i.e., lmkd + */ + final class AppExitInfoExternalSource { + private static final long APP_EXIT_INFO_FRESHNESS_MS = 300 * 1000; + + /** + * A mapping between uid -> pid -> {timestamp, extra info(Nullable)}. + * The uid here is the application uid, not the isolated uid. + */ + @GuardedBy("mLock") + private final SparseArray<SparseArray<Pair<Long, Object>>> mData; + + /** A tag for logging only */ + private final String mTag; + + /** A preset reason in case a proc dies */ + private final Integer mPresetReason; + + /** A callback that will be notified when a proc dies */ + private BiConsumer<Integer, Integer> mProcDiedListener; + + AppExitInfoExternalSource(String tag, Integer reason) { + mData = new SparseArray<SparseArray<Pair<Long, Object>>>(); + mTag = tag; + mPresetReason = reason; + } + + void add(int pid, int uid, Object extra) { + if (UserHandle.isIsolated(uid)) { + Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid); + if (k != null) { + uid = k; + } + } + + synchronized (mLock) { + SparseArray<Pair<Long, Object>> array = mData.get(uid); + if (array == null) { + array = new SparseArray<Pair<Long, Object>>(); + mData.put(uid, array); + } + array.put(pid, new Pair<Long, Object>(System.currentTimeMillis(), extra)); + } + } + + Pair<Long, Object> remove(int pid, int uid) { + if (UserHandle.isIsolated(uid)) { + Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid); + if (k != null) { + uid = k; + } + } + + synchronized (mLock) { + SparseArray<Pair<Long, Object>> array = mData.get(uid); + if (array != null) { + Pair<Long, Object> p = array.get(pid); + if (p != null) { + array.remove(pid); + return isFresh(p.first) ? p : null; + } + } + } + return null; + } + + void removeByUserId(int userId) { + if (userId == UserHandle.USER_CURRENT) { + userId = mService.mUserController.getCurrentUserId(); + } + synchronized (mLock) { + if (userId == UserHandle.USER_ALL) { + mData.clear(); + return; + } + for (int i = mData.size() - 1; i >= 0; i--) { + int uid = mData.keyAt(i); + if (UserHandle.getUserId(uid) == userId) { + mData.removeAt(i); + } + } + } + } + + void removeByUid(int uid, boolean allUsers) { + if (UserHandle.isIsolated(uid)) { + Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid); + if (k != null) { + uid = k; + } + } + + if (allUsers) { + uid = UserHandle.getAppId(uid); + synchronized (mLock) { + for (int i = mData.size() - 1; i >= 0; i--) { + if (UserHandle.getAppId(mData.keyAt(i)) == uid) { + mData.removeAt(i); + } + } + } + } else { + synchronized (mLock) { + mData.remove(uid); + } + } + } + + void setOnProcDiedListener(BiConsumer<Integer, Integer> listener) { + synchronized (mLock) { + mProcDiedListener = listener; + } + } + + void onProcDied(final int pid, final int uid, final Integer status) { + if (DEBUG_PROCESSES) { + Slog.i(TAG, mTag + ": proc died: pid=" + pid + " uid=" + uid + + ", status=" + status); + } + + if (mService == null) { + return; + } + + // Unlikely but possible: the record has been created + // Let's update it if we could find a ApplicationExitInfo record + if (!updateExitInfoIfNecessary(pid, uid, status, mPresetReason)) { + add(pid, uid, status); + } + + // Notify any interesed party regarding the lmkd kills + synchronized (mLock) { + final BiConsumer<Integer, Integer> listener = mProcDiedListener; + if (listener != null) { + mService.mHandler.post(()-> listener.accept(pid, uid)); + } + } + } + } +} diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index f86d6a70a076..0b115ea5ca5a 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -64,6 +64,7 @@ import static com.android.server.am.ActivityManagerService.TOP_APP_PRIORITY_BOOS import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; import android.app.ActivityManager; +import android.app.ApplicationExitInfo; import android.app.usage.UsageEvents; import android.content.Context; import android.content.pm.ServiceInfo; @@ -757,7 +758,10 @@ public final class OomAdjuster { lastCachedGroupUid = lastCachedGroup = 0; } if ((numCached - numCachedExtraGroup) > cachedProcessLimit) { - app.kill("cached #" + numCached, true); + app.kill("cached #" + numCached, + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED, + true); } break; case PROCESS_STATE_CACHED_EMPTY: @@ -765,11 +769,17 @@ public final class OomAdjuster { && app.lastActivityTime < oldTime) { app.kill("empty for " + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime) - / 1000) + "s", true); + / 1000) + "s", + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_TRIM_EMPTY, + true); } else { numEmpty++; if (numEmpty > emptyProcessLimit) { - app.kill("empty #" + numEmpty, true); + app.kill("empty #" + numEmpty, + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY, + true); } } break; @@ -786,7 +796,7 @@ public final class OomAdjuster { // definition not re-use the same process again, and it is // good to avoid having whatever code was running in them // left sitting around after no longer needed. - app.kill("isolated not needed", true); + app.kill("isolated not needed", ApplicationExitInfo.REASON_OTHER, true); } else { // Keeping this process, update its uid. updateAppUidRecLocked(app); @@ -2032,7 +2042,7 @@ public final class OomAdjuster { } if (app.waitingToKill != null && app.curReceivers.isEmpty() && app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) { - app.kill(app.waitingToKill, true); + app.kill(app.waitingToKill, ApplicationExitInfo.REASON_OTHER, true); success = false; } else { int processGroup; diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index b7f867df04c2..7f9477ed5c9b 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -22,6 +22,7 @@ import static android.app.ActivityThread.PROC_START_SEQ_IDENT; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO; import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode; import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground; +import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; import static android.os.Process.SYSTEM_UID; import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import static android.os.Process.getFreeMemory; @@ -53,23 +54,33 @@ import android.app.ActivityManager; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppProtoEnums; +import android.app.ApplicationExitInfo; +import android.app.ApplicationExitInfo.Reason; +import android.app.ApplicationExitInfo.SubReason; import android.app.IApplicationThread; +import android.app.IUidObserver; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManagerInternal; import android.content.res.Resources; import android.graphics.Point; +import android.net.LocalSocket; +import android.net.LocalSocketAddress; import android.os.AppZygote; import android.os.Binder; import android.os.Build; import android.os.Bundle; +import android.os.DropBoxManager; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.StrictMode; @@ -113,6 +124,7 @@ import com.android.server.wm.WindowManagerService; import dalvik.system.VMRuntime; import java.io.File; +import java.io.FileDescriptor; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; @@ -282,6 +294,10 @@ public final class ProcessList { private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE = "persist.device_config.runtime_native.use_app_image_startup_cache"; + // The socket path for zygote to send unsolicited msg. + // Must keep sync with com_android_internal_os_Zygote.cpp. + private static final String UNSOL_ZYGOTE_MSG_SOCKET_PATH = "/data/system/unsolzygotesocket"; + // Low Memory Killer Daemon command codes. // These must be kept in sync with lmk_cmd definitions in lmkd.h // @@ -416,12 +432,6 @@ public final class ProcessList { ActiveUids mActiveUids; /** - * The listener who is intereted with the lmkd kills. - */ - @GuardedBy("mService") - private LmkdKillListener mLmkdKillListener = null; - - /** * The currently running isolated processes. */ final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<>(); @@ -432,6 +442,12 @@ public final class ProcessList { final ProcessMap<AppZygote> mAppZygotes = new ProcessMap<AppZygote>(); /** + * Managees the {@link android.app.ApplicationExitInfo} records. + */ + @GuardedBy("mAppExitInfoTracker") + final AppExitInfoTracker mAppExitInfoTracker = new AppExitInfoTracker(); + + /** * The processes that are forked off an application zygote. */ final ArrayMap<AppZygote, ArrayList<ProcessRecord>> mAppZygoteProcesses = @@ -439,6 +455,28 @@ public final class ProcessList { private PlatformCompat mPlatformCompat = null; + /** + * The server socket in system_server, zygote will connect to it + * in order to send unsolicited messages to system_server. + */ + private LocalSocket mSystemServerSocketForZygote; + + /** + * Maximum number of bytes that an incoming unsolicited zygote message could be. + * To be updated if new message type needs to be supported. + */ + private static final int MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE = 16; + + /** + * The buffer to be used to receive the incoming unsolicited zygote message. + */ + private final byte[] mZygoteUnsolicitedMessage = new byte[MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE]; + + /** + * The buffer to be used to receive the SIGCHLD data, it includes pid/uid/status. + */ + private final int[] mZygoteSigChldMessage = new int[3]; + interface LmkdKillListener { /** * Called when there is a process kill by lmkd. @@ -597,7 +635,6 @@ public final class ProcessList { final class KillHandler extends Handler { static final int KILL_PROCESS_GROUP_MSG = 4000; static final int LMKD_RECONNECT_MSG = 4001; - static final int LMKD_PROC_KILLED_MSG = 4002; public KillHandler(Looper looper) { super(looper, null, true); @@ -620,16 +657,17 @@ public final class ProcessList { KillHandler.LMKD_RECONNECT_MSG), LMKD_RECONNECT_DELAY_MS); } break; - case LMKD_PROC_KILLED_MSG: - handleLmkdProcKilled(msg.arg1 /* pid */, msg.arg2 /* uid */); - break; - default: super.handleMessage(msg); } } } + /** + * A runner to handle the imperceptible killings. + */ + ImperceptibleKillRunner mImperceptibleKillRunner; + //////////////////// END FIELDS //////////////////// ProcessList() { @@ -692,9 +730,8 @@ public final class ProcessList { if (receivedLen != 12) { return false; } - sKillHandler.obtainMessage(KillHandler.LMKD_PROC_KILLED_MSG, - dataReceived.getInt(4), dataReceived.getInt(8)) - .sendToTarget(); + mAppExitInfoTracker.scheduleNoteLmkdProcKilled( + dataReceived.getInt(4), dataReceived.getInt(8)); return true; default: return false; @@ -702,9 +739,22 @@ public final class ProcessList { } } ); + // Start listening on incoming connections from zygotes. + mSystemServerSocketForZygote = createSystemServerSocketForZygote(); + if (mSystemServerSocketForZygote != null) { + sKillHandler.getLooper().getQueue().addOnFileDescriptorEventListener( + mSystemServerSocketForZygote.getFileDescriptor(), + EVENT_INPUT, this::handleZygoteMessages); + } + mAppExitInfoTracker.init(mService, sKillThread.getLooper()); + mImperceptibleKillRunner = new ImperceptibleKillRunner(sKillThread.getLooper()); } } + void onSystemReady() { + mAppExitInfoTracker.onSystemReady(); + } + void applyDisplaySize(WindowManagerService wm) { if (!mHaveDisplaySize) { Point p = new Point(); @@ -1437,7 +1487,10 @@ public final class ProcessList { proc.lastCachedPss, holder.appVersion); } } - proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true); + proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_LARGE_CACHED, + true); } else if (proc != null && !keepIfLarge && mService.mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL && proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) { @@ -1456,7 +1509,10 @@ public final class ProcessList { proc.lastCachedPss, holder.appVersion); } } - proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true); + proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", + ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_LARGE_CACHED, + true); } } return proc; @@ -2151,6 +2207,9 @@ public final class ProcessList { if (doKill) { // do the killing ProcessList.killProcessGroup(app.uid, app.pid); + noteAppKill(app, ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_UNKNOWN, + String.format(formatString, "")); } // wait for the death @@ -2229,6 +2288,8 @@ public final class ProcessList { app.pendingStart = false; killProcessQuiet(pid); Process.killProcessGroup(app.uid, app.pid); + noteAppKill(app, ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_UNKNOWN, reason); return false; } mService.mBatteryStatsService.noteProcessStart(app.processName, app.info.uid); @@ -2314,6 +2375,8 @@ public final class ProcessList { if (app.pid > 0) { killProcessQuiet(app.pid); ProcessList.killProcessGroup(app.uid, app.pid); + noteAppKill(app, ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_UNKNOWN, "hasn't been killed"); } else { app.pendingStart = false; } @@ -2444,6 +2507,12 @@ public final class ProcessList { @GuardedBy("mService") boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, String reason) { + return removeProcessLocked(app, callerWillRestart, allowRestart, reason, + ApplicationExitInfo.REASON_OTHER); + } + + boolean removeProcessLocked(ProcessRecord app, + boolean callerWillRestart, boolean allowRestart, String reason, int reasonCode) { final String name = app.processName; final int uid = app.uid; if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES, @@ -2479,7 +2548,7 @@ public final class ProcessList { needRestart = true; } } - app.kill(reason, true); + app.kill(reason, reasonCode, true); mService.handleAppDiedLocked(app, willRestart, allowRestart); if (willRestart) { removeLruProcessLocked(app); @@ -2564,6 +2633,7 @@ public final class ProcessList { // the uid of the isolated process is specified by the caller. uid = isolatedUid; } + mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(uid, info.uid); mService.getPackageManagerInternalLocked().addIsolatedUid(uid, info.uid); // Register the isolated UID with this application so BatteryStats knows to @@ -3537,27 +3607,382 @@ public final class ProcessList { } } - void setLmkdKillListener(final LmkdKillListener listener) { - synchronized (mService) { - mLmkdKillListener = listener; + /** + * Create a server socket in system_server, zygote will connect to it + * in order to send unsolicited messages to system_server. + */ + private LocalSocket createSystemServerSocketForZygote() { + // The file system entity for this socket is created with 0666 perms, owned + // by system:system. selinux restricts things so that only zygotes can + // access it. + final File socketFile = new File(UNSOL_ZYGOTE_MSG_SOCKET_PATH); + if (socketFile.exists()) { + socketFile.delete(); + } + + LocalSocket serverSocket = null; + try { + serverSocket = new LocalSocket(LocalSocket.SOCKET_DGRAM); + serverSocket.bind(new LocalSocketAddress( + UNSOL_ZYGOTE_MSG_SOCKET_PATH, LocalSocketAddress.Namespace.FILESYSTEM)); + Os.chmod(UNSOL_ZYGOTE_MSG_SOCKET_PATH, 0666); + } catch (Exception e) { + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException ex) { + } + serverSocket = null; + } } + return serverSocket; } - private void handleLmkdProcKilled(final int pid, final int uid) { - // Log only now + /** + * Handle the unsolicited message from zygote. + */ + private int handleZygoteMessages(FileDescriptor fd, int events) { + final int eventFd = fd.getInt$(); + if ((events & EVENT_INPUT) != 0) { + // An incoming message from zygote + try { + final int len = Os.read(fd, mZygoteUnsolicitedMessage, 0, + mZygoteUnsolicitedMessage.length); + if (len > 0 && mZygoteSigChldMessage.length == Zygote.nativeParseSigChld( + mZygoteUnsolicitedMessage, len, mZygoteSigChldMessage)) { + mAppExitInfoTracker.handleZygoteSigChld( + mZygoteSigChldMessage[0] /* pid */, + mZygoteSigChldMessage[1] /* uid */, + mZygoteSigChldMessage[2] /* status */); + } + } catch (Exception e) { + Slog.w(TAG, "Exception in reading unsolicited zygote message: " + e); + } + } + return EVENT_INPUT; + } + + /** + * Called by ActivityManagerService when a process died. + */ + @GuardedBy("mService") + void noteProcessDiedLocked(final ProcessRecord app) { + if (DEBUG_PROCESSES) { + Slog.i(TAG, "note: " + app + " died, saving the exit info"); + } + + mAppExitInfoTracker.scheduleNoteProcessDiedLocked(app); + } + + /** + * Called by ActivityManagerService when it decides to kill an application process. + */ + void noteAppKill(final ProcessRecord app, final @Reason int reason, + final @SubReason int subReason, final String msg) { + if (DEBUG_PROCESSES) { + Slog.i(TAG, "note: " + app + " is being killed, reason: " + reason + + ", sub-reason: " + subReason + ", message: " + msg); + } + mAppExitInfoTracker.scheduleNoteAppKill(app, reason, subReason, msg); + } + + void noteAppKill(final int pid, final int uid, final @Reason int reason, + final @SubReason int subReason, final String msg) { if (DEBUG_PROCESSES) { - Slog.i(TAG, "lmkd kill: pid=" + pid + " uid=" + uid); + Slog.i(TAG, "note: " + pid + " is being killed, reason: " + reason + + ", sub-reason: " + subReason + ", message: " + msg); } - if (mService == null) { + mAppExitInfoTracker.scheduleNoteAppKill(pid, uid, reason, subReason, msg); + } + + /** + * Schedule to kill the given pids when the device is idle + */ + void killProcessesWhenImperceptible(int[] pids, String reason, int requester) { + if (ArrayUtils.isEmpty(pids)) { return; } - // Notify any interesed party regarding the lmkd kills + synchronized (mService) { - final LmkdKillListener listener = mLmkdKillListener; - if (listener != null) { - mService.mHandler.post(()-> listener.onLmkdKillOccurred(pid, uid)); + ProcessRecord app; + for (int i = 0; i < pids.length; i++) { + synchronized (mService.mPidsSelfLocked) { + app = mService.mPidsSelfLocked.get(pids[i]); + } + if (app != null) { + mImperceptibleKillRunner.enqueueLocked(app, reason, requester); + } } } } + + private final class ImperceptibleKillRunner extends IUidObserver.Stub { + private static final String EXTRA_PID = "pid"; + private static final String EXTRA_UID = "uid"; + private static final String EXTRA_TIMESTAMP = "timestamp"; + private static final String EXTRA_REASON = "reason"; + private static final String EXTRA_REQUESTER = "requester"; + + private static final String DROPBOX_TAG_IMPERCEPTIBLE_KILL = "imperceptible_app_kill"; + + // uid -> killing information mapping + private SparseArray<List<Bundle>> mWorkItems = new SparseArray<List<Bundle>>(); + + // The last time the various processes have been killed by us. + private ProcessMap<Long> mLastProcessKillTimes = new ProcessMap<>(); + + // Device idle or not. + private volatile boolean mIdle; + private boolean mUidObserverEnabled; + private Handler mHandler; + private IdlenessReceiver mReceiver; + + private final class H extends Handler { + static final int MSG_DEVICE_IDLE = 0; + static final int MSG_UID_GONE = 1; + static final int MSG_UID_STATE_CHANGED = 2; + + H(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_DEVICE_IDLE: + handleDeviceIdle(); + break; + case MSG_UID_GONE: + handleUidGone(msg.arg1 /* uid */); + break; + case MSG_UID_STATE_CHANGED: + handleUidStateChanged(msg.arg1 /* uid */, msg.arg2 /* procState */); + break; + } + } + } + + private final class IdlenessReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + final PowerManager pm = mService.mContext.getSystemService(PowerManager.class); + switch (intent.getAction()) { + case PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED: + notifyDeviceIdleness(pm.isLightDeviceIdleMode()); + break; + case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED: + notifyDeviceIdleness(pm.isDeviceIdleMode()); + break; + } + } + } + + ImperceptibleKillRunner(Looper looper) { + mHandler = new H(looper); + } + + @GuardedBy("mService") + boolean enqueueLocked(ProcessRecord app, String reason, int requester) { + // Throttle the killing request for potential bad app to avoid cpu thrashing + Long last = app.isolated ? null : mLastProcessKillTimes.get(app.processName, app.uid); + if (last != null && SystemClock.uptimeMillis() < last + MIN_CRASH_INTERVAL) { + return false; + } + + final Bundle bundle = new Bundle(); + bundle.putInt(EXTRA_PID, app.pid); + bundle.putInt(EXTRA_UID, app.uid); + // Since the pid could be reused, let's get the actual start time of each process + bundle.putLong(EXTRA_TIMESTAMP, app.startTime); + bundle.putString(EXTRA_REASON, reason); + bundle.putInt(EXTRA_REQUESTER, requester); + List<Bundle> list = mWorkItems.get(app.uid); + if (list == null) { + list = new ArrayList<Bundle>(); + mWorkItems.put(app.uid, list); + } + list.add(bundle); + if (mReceiver == null) { + mReceiver = new IdlenessReceiver(); + IntentFilter filter = new IntentFilter( + PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED); + filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); + mService.mContext.registerReceiver(mReceiver, filter); + } + return true; + } + + void notifyDeviceIdleness(boolean idle) { + // No lock is held regarding mIdle, this function is the only updater and caller + // won't re-entry. + boolean diff = mIdle != idle; + mIdle = idle; + if (diff && idle) { + synchronized (this) { + if (mWorkItems.size() > 0) { + mHandler.sendEmptyMessage(H.MSG_DEVICE_IDLE); + } + } + } + } + + private void handleDeviceIdle() { + final DropBoxManager dbox = mService.mContext.getSystemService(DropBoxManager.class); + final boolean logToDropbox = dbox != null + && dbox.isTagEnabled(DROPBOX_TAG_IMPERCEPTIBLE_KILL); + + synchronized (mService) { + final int size = mWorkItems.size(); + for (int i = size - 1; mIdle && i >= 0; i--) { + List<Bundle> list = mWorkItems.valueAt(i); + final int len = list.size(); + for (int j = len - 1; mIdle && j >= 0; j--) { + Bundle bundle = list.get(j); + if (killProcessLocked( + bundle.getInt(EXTRA_PID), + bundle.getInt(EXTRA_UID), + bundle.getLong(EXTRA_TIMESTAMP), + bundle.getString(EXTRA_REASON), + bundle.getInt(EXTRA_REQUESTER), + dbox, logToDropbox)) { + list.remove(j); + } + } + if (list.size() == 0) { + mWorkItems.removeAt(i); + } + } + registerUidObserverIfNecessaryLocked(); + } + } + + @GuardedBy("mService") + private void registerUidObserverIfNecessaryLocked() { + // If there are still works remaining, register UID observer + if (!mUidObserverEnabled && mWorkItems.size() > 0) { + mUidObserverEnabled = true; + mService.registerUidObserver(this, + ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE, + ActivityManager.PROCESS_STATE_UNKNOWN, "android"); + } else if (mUidObserverEnabled && mWorkItems.size() == 0) { + mUidObserverEnabled = false; + mService.unregisterUidObserver(this); + } + } + + /** + * Kill the given processes, if they are not exempted. + * + * @return True if the process is killed, or it's gone already, or we are not allowed to + * kill it (one of the packages in this process is being exempted). + */ + @GuardedBy("mService") + private boolean killProcessLocked(final int pid, final int uid, final long timestamp, + final String reason, final int requester, final DropBoxManager dbox, + final boolean logToDropbox) { + ProcessRecord app = null; + synchronized (mService.mPidsSelfLocked) { + app = mService.mPidsSelfLocked.get(pid); + } + + if (app == null || app.pid != pid || app.uid != uid || app.startTime != timestamp) { + // This process record has been reused for another process, meaning the old process + // has been gone. + return true; + } + + final int pkgSize = app.pkgList.size(); + for (int ip = 0; ip < pkgSize; ip++) { + if (mService.mConstants.IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.contains( + app.pkgList.keyAt(ip))) { + // One of the packages in this process is exempted + return true; + } + } + + if (mService.mConstants.IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.contains( + app.getReportedProcState())) { + // We need to reschedule it. + return false; + } + + app.kill(reason, ApplicationExitInfo.REASON_OTHER, true); + + if (!app.isolated) { + mLastProcessKillTimes.put(app.processName, app.uid, SystemClock.uptimeMillis()); + } + + if (logToDropbox) { + final long now = SystemClock.elapsedRealtime(); + final StringBuilder sb = new StringBuilder(); + mService.appendDropBoxProcessHeaders(app, app.processName, sb); + sb.append("Reason: " + reason).append("\n"); + sb.append("Requester UID: " + requester).append("\n"); + dbox.addText(DROPBOX_TAG_IMPERCEPTIBLE_KILL, sb.toString()); + } + return true; + } + + private void handleUidStateChanged(int uid, int procState) { + final DropBoxManager dbox = mService.mContext.getSystemService(DropBoxManager.class); + final boolean logToDropbox = dbox != null + && dbox.isTagEnabled(DROPBOX_TAG_IMPERCEPTIBLE_KILL); + synchronized (mService) { + if (mIdle && !mService.mConstants + .IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.contains(procState)) { + List<Bundle> list = mWorkItems.get(uid); + if (list != null) { + final int len = list.size(); + for (int j = len - 1; mIdle && j >= 0; j--) { + Bundle bundle = list.get(j); + if (killProcessLocked( + bundle.getInt(EXTRA_PID), + bundle.getInt(EXTRA_UID), + bundle.getLong(EXTRA_TIMESTAMP), + bundle.getString(EXTRA_REASON), + bundle.getInt(EXTRA_REQUESTER), + dbox, logToDropbox)) { + list.remove(j); + } + } + if (list.size() == 0) { + mWorkItems.remove(uid); + } + registerUidObserverIfNecessaryLocked(); + } + } + } + } + + private void handleUidGone(int uid) { + synchronized (mService) { + mWorkItems.remove(uid); + registerUidObserverIfNecessaryLocked(); + } + } + + @Override + public void onUidGone(int uid, boolean disabled) { + mHandler.obtainMessage(H.MSG_UID_GONE, uid, 0).sendToTarget(); + } + + @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) { + mHandler.obtainMessage(H.MSG_UID_STATE_CHANGED, uid, procState).sendToTarget(); + } + + @Override + public void onUidCachedChanged(int uid, boolean cached) { + } + }; } + diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 1fef3538165a..cbf058700909 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -27,6 +27,9 @@ import static com.android.server.am.ActivityManagerService.MY_PID; import android.app.ActivityManager; import android.app.ApplicationErrorReport; +import android.app.ApplicationExitInfo; +import android.app.ApplicationExitInfo.Reason; +import android.app.ApplicationExitInfo.SubReason; import android.app.Dialog; import android.app.IApplicationThread; import android.content.ComponentName; @@ -776,7 +779,8 @@ class ProcessRecord implements WindowProcessListener { } catch (RemoteException e) { // If it's already dead our work is done. If it's wedged just kill it. // We won't get the crash dialog or the error reporting. - kill("scheduleCrash for '" + message + "' failed", true); + kill("scheduleCrash for '" + message + "' failed", + ApplicationExitInfo.REASON_CRASH, true); } finally { Binder.restoreCallingIdentity(ident); } @@ -784,7 +788,11 @@ class ProcessRecord implements WindowProcessListener { } } - void kill(String reason, boolean noisy) { + void kill(String reason, @Reason int reasonCode, boolean noisy) { + kill(reason, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, noisy); + } + + void kill(String reason, @Reason int reasonCode, @SubReason int subReason, boolean noisy) { if (!killedByAm) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); if (mService != null && (noisy || info.uid == mService.mCurOomAdjUid)) { @@ -793,6 +801,7 @@ class ProcessRecord implements WindowProcessListener { info.uid); } if (pid > 0) { + mService.mProcessList.noteAppKill(this, reasonCode, subReason, reason); EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason); Process.killProcessQuiet(pid); ProcessList.killProcessGroup(uid, pid); @@ -1374,9 +1383,9 @@ class ProcessRecord implements WindowProcessListener { } @Override - public void appDied() { + public void appDied(String reason) { synchronized (mService) { - mService.appDiedLocked(this); + mService.appDiedLocked(this, reason); } } @@ -1441,7 +1450,8 @@ class ProcessRecord implements WindowProcessListener { ArrayList<Integer> firstPids = new ArrayList<>(5); SparseArray<Boolean> lastPids = new SparseArray<>(20); - mWindowProcessController.appEarlyNotResponding(annotation, () -> kill("anr", true)); + mWindowProcessController.appEarlyNotResponding(annotation, () -> kill("anr", + ApplicationExitInfo.REASON_ANR, true)); long anrTime = SystemClock.uptimeMillis(); if (isMonitorCpuUsage()) { @@ -1592,7 +1602,8 @@ class ProcessRecord implements WindowProcessListener { mService.addErrorToDropBox("anr", this, processName, activityShortComponentName, parentShortComponentName, parentPr, annotation, cpuInfo, tracesFile, null); - if (mWindowProcessController.appNotResponding(info.toString(), () -> kill("anr", true), + if (mWindowProcessController.appNotResponding(info.toString(), () -> kill("anr", + ApplicationExitInfo.REASON_ANR, true), () -> { synchronized (mService) { mService.mServices.scheduleServiceTimeoutLocked(this); @@ -1609,7 +1620,7 @@ class ProcessRecord implements WindowProcessListener { } if (isSilentAnr() && !isDebugging()) { - kill("bg anr", true); + kill("bg anr", ApplicationExitInfo.REASON_ANR, true); return; } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 1d2a9059c453..0c9abae2e0fc 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -848,7 +848,11 @@ public class Vpn { } public int getNetId() { - return mNetworkAgent != null ? mNetworkAgent.network.netId : NETID_UNSET; + final NetworkAgent agent = mNetworkAgent; + if (null == agent) return NETID_UNSET; + final Network network = agent.getNetwork(); + if (null == network) return NETID_UNSET; + return network.netId; } private LinkProperties makeLinkProperties() { diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index e39d6d5389e3..58e519d1f595 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -2244,6 +2244,13 @@ public final class DisplayManagerService extends SystemService { } @Override // Binder call + public boolean isMinimalPostProcessingRequested(int displayId) { + synchronized (mSyncRoot) { + return mLogicalDisplays.get(displayId).getRequestedMinimalPostProcessingLocked(); + } + } + + @Override // Binder call public void setTemporaryBrightness(int brightness) { mContext.enforceCallingOrSelfPermission( Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS, diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 7233f3465d5b..baae4ea502d5 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -1622,7 +1622,7 @@ public class LockSettingsService extends ILockSettings.Stub { } if (credential.isNone()) { - clearUserKeyProtection(userId); + clearUserKeyProtection(userId, null); gateKeeperClearSecureUserId(userId); mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId); // Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path, @@ -1813,9 +1813,17 @@ public class LockSettingsService extends ILockSettings.Stub { addUserKeyAuth(userId, token, secretFromCredential(credential)); } - private void clearUserKeyProtection(int userId) { + private void clearUserKeyProtection(int userId, byte[] secret) { if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId); - addUserKeyAuth(userId, null, null); + final UserInfo userInfo = mUserManager.getUserInfo(userId); + final long callingId = Binder.clearCallingIdentity(); + try { + mStorageManager.clearUserKeyAuth(userId, userInfo.serialNumber, null, secret); + } catch (RemoteException e) { + throw new IllegalStateException("clearUserKeyAuth failed user=" + userId); + } finally { + Binder.restoreCallingIdentity(callingId); + } } private static byte[] secretFromCredential(LockscreenCredential credential) { @@ -2571,7 +2579,7 @@ public class LockSettingsService extends ILockSettings.Stub { setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey()); setKeystorePassword(auth.deriveKeyStorePassword(), userId); } else { - clearUserKeyProtection(userId); + clearUserKeyProtection(userId, null); setKeystorePassword(null, userId); gateKeeperClearSecureUserId(userId); } @@ -2765,7 +2773,7 @@ public class LockSettingsService extends ILockSettings.Stub { // during boot. Vold storage needs to be unlocked before manipulation of the keys can // succeed. unlockUserKey(userId, null, auth.deriveDiskEncryptionKey()); - clearUserKeyProtection(userId); + clearUserKeyProtection(userId, auth.deriveDiskEncryptionKey()); fixateNewestUserKeyAuth(userId); unlockKeystore(auth.deriveKeyStorePassword(), userId); setKeystorePassword(null, userId); diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java index b67335ab82bc..9f42c3625a51 100644 --- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java +++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java @@ -17,6 +17,7 @@ package com.android.server.media; import android.annotation.NonNull; +import android.annotation.Nullable; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -58,6 +59,7 @@ class BluetoothRouteProvider { private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver(); private final BluetoothProfileListener mProfileListener = new BluetoothProfileListener(); + // TODO: The mActiveDevice should be set when BluetoothRouteProvider is created. private BluetoothDevice mActiveDevice = null; static synchronized BluetoothRouteProvider getInstance(@NonNull Context context, @@ -125,6 +127,14 @@ class BluetoothRouteProvider { return routes; } + @Nullable String getActiveDeviceAddress() { + BluetoothDevice device = mActiveDevice; + if (device == null) { + return null; + } + return device.getAddress(); + } + private void notifyBluetoothRoutesUpdated() { if (mListener != null) { mListener.onBluetoothRoutesUpdated(getBluetoothRoutes()); @@ -281,8 +291,8 @@ class BluetoothRouteProvider { setRouteConnectionStateForDevice(device, MediaRoute2Info.CONNECTION_STATE_CONNECTED); } - notifyBluetoothRoutesUpdated(); mActiveDevice = device; + notifyBluetoothRoutesUpdated(); } break; case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED: diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 216753017010..f9169ee69d41 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -112,6 +112,30 @@ class MediaRouter2ServiceImpl { } } + @NonNull + public RoutingSessionInfo getSystemSessionInfo() { + final int uid = Binder.getCallingUid(); + final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier(); + + final long token = Binder.clearCallingIdentity(); + try { + RoutingSessionInfo systemSessionInfo = null; + synchronized (mLock) { + UserRecord userRecord = getOrCreateUserRecordLocked(userId); + List<RoutingSessionInfo> sessionInfos = + userRecord.mHandler.mSystemProvider.getSessionInfos(); + if (sessionInfos != null && !sessionInfos.isEmpty()) { + systemSessionInfo = sessionInfos.get(0); + } else { + Slog.w(TAG, "System provider does not have any session info."); + } + } + return systemSessionInfo; + } finally { + Binder.restoreCallingIdentity(token); + } + } + public void registerClient(@NonNull IMediaRouter2Client client, @NonNull String packageName) { Objects.requireNonNull(client, "client must not be null"); @@ -1351,6 +1375,16 @@ class MediaRouter2ServiceImpl { List<IMediaRouter2Manager> managers = getManagers(); notifySessionInfosChangedToManagers(managers); + // For system provider, notify all clients. + if (provider == mSystemProvider) { + MediaRouter2ServiceImpl service = mServiceRef.get(); + if (service == null) { + return; + } + notifySessionInfoChangedToClients(getClients(), sessionInfo); + return; + } + Client2Record client2Record = mSessionToClientMap.get( sessionInfo.getId()); if (client2Record == null) { @@ -1509,6 +1543,17 @@ class MediaRouter2ServiceImpl { } } + private void notifySessionInfoChangedToClients(List<IMediaRouter2Client> clients, + RoutingSessionInfo sessionInfo) { + for (IMediaRouter2Client client : clients) { + try { + client.notifySessionInfoChanged(sessionInfo); + } catch (RemoteException ex) { + Slog.w(TAG, "Failed to notify session info changed. Client probably died.", ex); + } + } + } + private void notifyRoutesToManager(IMediaRouter2Manager manager) { List<MediaRoute2Info> routes = new ArrayList<>(); for (MediaRoute2ProviderInfo providerInfo : mLastProviderInfos) { diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index 5437fadf2d74..e1d38039b955 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -444,6 +444,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override + public RoutingSessionInfo getSystemSessionInfo() { + return mService2.getSystemSessionInfo(); + } + + // Binder call + @Override public void registerClient2(IMediaRouter2Client client, String packageName) { final int uid = Binder.getCallingUid(); if (!validatePackageName(uid, packageName)) { diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index 56c33fe339ea..ebea6c3dc558 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -26,17 +26,20 @@ import android.media.IAudioRoutesObserver; import android.media.IAudioService; import android.media.MediaRoute2Info; import android.media.MediaRoute2ProviderInfo; +import android.media.RoutingSessionInfo; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; +import android.text.TextUtils; import android.util.Log; import com.android.internal.R; import java.util.Collections; import java.util.List; +import java.util.Objects; /** * Provides routes for local playbacks such as phone speaker, wired headset, or Bluetooth speakers. @@ -46,7 +49,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE"; - static final String BLUETOOTH_ROUTE_ID = "BLUETOOTH_ROUTE"; + static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION"; // TODO: Move these to a proper place public static final String TYPE_LIVE_AUDIO = "android.media.intent.route.TYPE_LIVE_AUDIO"; @@ -92,6 +95,14 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> { mBluetoothRoutes = routes; publishRoutes(); + + boolean sessionInfoChanged; + synchronized (mLock) { + sessionInfoChanged = updateSessionInfosIfNeededLocked(); + } + if (sessionInfoChanged) { + notifySessionInfoUpdated(); + } }); initializeRoutes(); } @@ -172,6 +183,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } setProviderState(builder.build()); mHandler.post(() -> notifyProviderState()); + + // Note: No lock needed when initializing. + updateSessionInfosIfNeededLocked(); } void updateAudioRoutes(AudioRoutesInfo newRoutes) { @@ -203,6 +217,35 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } /** + * Updates the mSessionInfo. Returns true if the session info is changed. + */ + boolean updateSessionInfosIfNeededLocked() { + RoutingSessionInfo oldSessionInfo = mSessionInfos.isEmpty() ? null : mSessionInfos.get(0); + + RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder( + SYSTEM_SESSION_ID, "" /* clientPackageName */) + .setSystemSession(true); + String activeBtDeviceAddress = mBtRouteProvider.getActiveDeviceAddress(); + + RoutingSessionInfo newSessionInfo; + if (!TextUtils.isEmpty(activeBtDeviceAddress)) { + // Bluetooth route. Set the route ID with the device's address. + newSessionInfo = builder.addSelectedRoute(activeBtDeviceAddress).build(); + } else { + // Default device + newSessionInfo = builder.addSelectedRoute(mDefaultRoute.getId()).build(); + } + + if (Objects.equals(oldSessionInfo, newSessionInfo)) { + return false; + } else { + mSessionInfos.clear(); + mSessionInfos.add(newSessionInfo); + return true; + } + } + + /** * The first route should be the currently selected system route. * For example, if there are two system routes (BT and device speaker), * BT will be the first route in the list. @@ -215,4 +258,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } setAndNotifyProviderState(builder.build()); } + + void notifySessionInfoUpdated() { + RoutingSessionInfo sessionInfo; + synchronized (mLock) { + sessionInfo = mSessionInfos.get(0); + } + mCallback.onSessionUpdated(this, sessionInfo); + } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 71555c98f9d2..78875da9e790 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -152,7 +152,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final int MSG_COMMIT = 1; private static final int MSG_ON_PACKAGE_INSTALLED = 2; private static final int MSG_SEAL = 3; - private static final int MSG_TRANSFER = 4; /** XML constants used for persisting a session */ static final String TAG_SESSION = "session"; @@ -388,32 +387,19 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private final Handler.Callback mHandlerCallback = new Handler.Callback() { @Override public boolean handleMessage(Message msg) { - SomeArgs args; - String packageName; - IntentSender statusReceiver; switch (msg.what) { case MSG_SEAL: - statusReceiver = (IntentSender) msg.obj; - - handleSeal(statusReceiver); + handleSeal((IntentSender) msg.obj); break; case MSG_COMMIT: handleCommit(); break; - case MSG_TRANSFER: - args = (SomeArgs) msg.obj; - packageName = (String) args.arg1; - statusReceiver = (IntentSender) args.arg2; - args.recycle(); - - handleTransfer(statusReceiver, packageName); - break; case MSG_ON_PACKAGE_INSTALLED: - args = (SomeArgs) msg.obj; - packageName = (String) args.arg1; + final SomeArgs args = (SomeArgs) msg.obj; + final String packageName = (String) args.arg1; final String message = (String) args.arg2; final Bundle extras = (Bundle) args.arg3; - statusReceiver = (IntentSender) args.arg4; + final IntentSender statusReceiver = (IntentSender) args.arg4; final int returnCode = args.argi1; args.recycle(); @@ -459,7 +445,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * Checks if the permissions still need to be confirmed. * * <p>This is dependant on the identity of the installer, hence this cannot be cached if the - * installer might still {@link #transfer(String, IntentSender) change}. + * installer might still {@link #transfer(String) change}. * * @return {@code true} iff we need to ask to confirm the permissions? */ @@ -1403,11 +1389,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - private int assertCanBeTransferredAndReturnNewOwner(String packageName) - throws PackageManager.NameNotFoundException { + @Override + public void transfer(String packageName) { + Objects.requireNonNull(packageName); + ApplicationInfo newOwnerAppInfo = mPm.getApplicationInfo(packageName, 0, userId); if (newOwnerAppInfo == null) { - throw new PackageManager.NameNotFoundException(packageName); + throw new ParcelableException(new PackageManager.NameNotFoundException(packageName)); } if (PackageManager.PERMISSION_GRANTED != mPm.checkUidPermission( @@ -1422,106 +1410,31 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { throw new SecurityException("Can only transfer sessions that use public options"); } - return newOwnerAppInfo.uid; - } - - @Override - public void transfer(String packageName, IntentSender statusReceiver) { - Objects.requireNonNull(statusReceiver); - Objects.requireNonNull(packageName); - - try { - assertCanBeTransferredAndReturnNewOwner(packageName); - } catch (PackageManager.NameNotFoundException e) { - throw new ParcelableException(e); - } + List<PackageInstallerSession> childSessions = getChildSessions(); synchronized (mLock) { assertCallerIsOwnerOrRootLocked(); assertPreparedAndNotSealedLocked("transfer"); - } - - final SomeArgs args = SomeArgs.obtain(); - args.arg1 = packageName; - args.arg2 = statusReceiver; - - mHandler.obtainMessage(MSG_TRANSFER, args).sendToTarget(); - } - - private void handleTransfer(IntentSender statusReceiver, String packageName) { - List<PackageInstallerSession> childSessions = getChildSessions(); - - try { - final int uid = assertCanBeTransferredAndReturnNewOwner(packageName); - - synchronized (mLock) { - assertPreparedAndNotSealedLocked("transfer"); - - try { - sealAndValidateLocked(childSessions); - } catch (StreamingException e) { - throw new IllegalArgumentException("Streaming failed", e); - } catch (PackageManagerException e) { - throw new IllegalArgumentException("Package is not valid", e); - } - if (!mPackageName.equals(mInstallSource.installerPackageName)) { - throw new SecurityException( - "Can only transfer sessions that update the original installer"); - } + try { + sealLocked(childSessions); + } catch (PackageManagerException e) { + throw new IllegalArgumentException("Package is not valid", e); + } - mInstallerUid = uid; - mInstallSource = InstallSource.create(packageName, null, packageName); + if (!mPackageName.equals(mInstallSource.installerPackageName)) { + throw new SecurityException("Can only transfer sessions that update the original " + + "installer"); } - } catch (PackageManager.NameNotFoundException e) { - onSessionTransferStatus(statusReceiver, packageName, - PackageInstaller.STATUS_FAILURE_NAME_NOT_FOUND, e.getMessage()); - return; - } catch (IllegalStateException e) { - onSessionTransferStatus(statusReceiver, packageName, - PackageInstaller.STATUS_FAILURE_ILLEGAL_STATE, e.getMessage()); - return; - } catch (SecurityException e) { - onSessionTransferStatus(statusReceiver, packageName, - PackageInstaller.STATUS_FAILURE_SECURITY, e.getMessage()); - return; - } catch (Throwable e) { - onSessionTransferStatus(statusReceiver, packageName, PackageInstaller.STATUS_FAILURE, - e.getMessage()); - return; + + mInstallerUid = newOwnerAppInfo.uid; + mInstallSource = InstallSource.create(packageName, null, packageName); } // Persist the fact that we've sealed ourselves to prevent // mutations of any hard links we create. We do this without holding // the session lock, since otherwise it's a lock inversion. mCallback.onSessionSealedBlocking(this); - - // Report success. - onSessionTransferStatus(statusReceiver, packageName, PackageInstaller.STATUS_SUCCESS, null); - } - - private void onSessionTransferStatus(IntentSender statusReceiver, String otherPackageName, - int status, String statusMessage) { - final String packageName; - synchronized (mLock) { - packageName = mPackageName; - } - - final Intent fillIn = new Intent(); - fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, packageName); - fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); - fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, otherPackageName); - - fillIn.putExtra(PackageInstaller.EXTRA_STATUS, status); - if (!TextUtils.isEmpty(statusMessage)) { - fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, statusMessage); - } - - try { - statusReceiver.sendIntent(mContext, 0, fillIn, null, null); - } catch (IntentSender.SendIntentException ignored) { - } - } private void handleCommit() { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 4f18cb43cc94..5d948b24256a 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -92,6 +92,8 @@ import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.JournaledFile; import com.android.internal.util.XmlUtils; +import com.android.permission.persistence.RuntimePermissionsPersistence; +import com.android.permission.persistence.RuntimePermissionsState; import com.android.server.LocalServices; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.permission.BasePermission; @@ -5096,6 +5098,9 @@ public final class Settings { private static final int UPGRADE_VERSION = -1; private static final int INITIAL_VERSION = 0; + private final RuntimePermissionsPersistence mPersistence = + RuntimePermissionsPersistence.createInstance(); + private final Handler mHandler = new MyHandler(); private final Object mPersistenceLock; @@ -5185,98 +5190,72 @@ public final class Settings { } private void writePermissionsSync(int userId) { - AtomicFile destination = new AtomicFile(getUserRuntimePermissionsFile(userId), - "package-perms-" + userId); - - ArrayMap<String, List<PermissionState>> permissionsForPackage = new ArrayMap<>(); - ArrayMap<String, List<PermissionState>> permissionsForSharedUser = new ArrayMap<>(); - + RuntimePermissionsState runtimePermissions; synchronized (mPersistenceLock) { mWriteScheduled.delete(userId); - final int packageCount = mPackages.size(); - for (int i = 0; i < packageCount; i++) { + int version = mVersions.get(userId, INITIAL_VERSION); + + String fingerprint = mFingerprints.get(userId); + + Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions = + new ArrayMap<>(); + int packagesSize = mPackages.size(); + for (int i = 0; i < packagesSize; i++) { String packageName = mPackages.keyAt(i); PackageSetting packageSetting = mPackages.valueAt(i); if (packageSetting.sharedUser == null) { - PermissionsState permissionsState = packageSetting.getPermissionsState(); - List<PermissionState> permissionsStates = permissionsState - .getRuntimePermissionStates(userId); - if (!permissionsStates.isEmpty()) { - permissionsForPackage.put(packageName, permissionsStates); + List<RuntimePermissionsState.PermissionState> permissions = + getPermissionsFromPermissionsState( + packageSetting.getPermissionsState(), userId); + if (permissions != null) { + packagePermissions.put(packageName, permissions); } } } - final int sharedUserCount = mSharedUsers.size(); - for (int i = 0; i < sharedUserCount; i++) { + Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions = + new ArrayMap<>(); + final int sharedUsersSize = mSharedUsers.size(); + for (int i = 0; i < sharedUsersSize; i++) { String sharedUserName = mSharedUsers.keyAt(i); - SharedUserSetting sharedUser = mSharedUsers.valueAt(i); - PermissionsState permissionsState = sharedUser.getPermissionsState(); - List<PermissionState> permissionsStates = permissionsState - .getRuntimePermissionStates(userId); - if (!permissionsStates.isEmpty()) { - permissionsForSharedUser.put(sharedUserName, permissionsStates); + SharedUserSetting sharedUserSetting = mSharedUsers.valueAt(i); + List<RuntimePermissionsState.PermissionState> permissions = + getPermissionsFromPermissionsState( + sharedUserSetting.getPermissionsState(), userId); + if (permissions != null) { + sharedUserPermissions.put(sharedUserName, permissions); } } - } - - FileOutputStream out = null; - try { - out = destination.startWrite(); - - XmlSerializer serializer = Xml.newSerializer(); - serializer.setOutput(out, StandardCharsets.UTF_8.name()); - serializer.setFeature( - "http://xmlpull.org/v1/doc/features.html#indent-output", true); - serializer.startDocument(null, true); - - serializer.startTag(null, TAG_RUNTIME_PERMISSIONS); - - final int version = mVersions.get(userId, INITIAL_VERSION); - serializer.attribute(null, ATTR_VERSION, Integer.toString(version)); - - String fingerprint = mFingerprints.get(userId); - if (fingerprint != null) { - serializer.attribute(null, ATTR_FINGERPRINT, fingerprint); - } - final int packageCount = permissionsForPackage.size(); - for (int i = 0; i < packageCount; i++) { - String packageName = permissionsForPackage.keyAt(i); - List<PermissionState> permissionStates = permissionsForPackage.valueAt(i); - serializer.startTag(null, TAG_PACKAGE); - serializer.attribute(null, ATTR_NAME, packageName); - writePermissions(serializer, permissionStates); - serializer.endTag(null, TAG_PACKAGE); - } + runtimePermissions = new RuntimePermissionsState(version, fingerprint, + packagePermissions, sharedUserPermissions); + } - final int sharedUserCount = permissionsForSharedUser.size(); - for (int i = 0; i < sharedUserCount; i++) { - String packageName = permissionsForSharedUser.keyAt(i); - List<PermissionState> permissionStates = permissionsForSharedUser.valueAt(i); - serializer.startTag(null, TAG_SHARED_USER); - serializer.attribute(null, ATTR_NAME, packageName); - writePermissions(serializer, permissionStates); - serializer.endTag(null, TAG_SHARED_USER); - } + mPersistence.write(runtimePermissions, UserHandle.of(userId)); + } - serializer.endTag(null, TAG_RUNTIME_PERMISSIONS); + @Nullable + private List<RuntimePermissionsState.PermissionState> getPermissionsFromPermissionsState( + @NonNull PermissionsState permissionsState, @UserIdInt int userId) { + List<PermissionState> permissionStates = permissionsState.getRuntimePermissionStates( + userId); + if (permissionStates.isEmpty()) { + return null; + } - serializer.endDocument(); - destination.finishWrite(out); + List<RuntimePermissionsState.PermissionState> permissions = + new ArrayList<>(); + int permissionStatesSize = permissionStates.size(); + for (int i = 0; i < permissionStatesSize; i++) { + PermissionState permissionState = permissionStates.get(i); - if (Build.FINGERPRINT.equals(fingerprint)) { - mDefaultPermissionsGranted.put(userId, true); - } - // Any error while writing is fatal. - } catch (Throwable t) { - Slog.wtf(PackageManagerService.TAG, - "Failed to write settings, restoring backup", t); - destination.failWrite(out); - } finally { - IoUtils.closeQuietly(out); + RuntimePermissionsState.PermissionState permission = + new RuntimePermissionsState.PermissionState(permissionState.getName(), + permissionState.isGranted(), permissionState.getFlags()); + permissions.add(permission); } + return permissions; } @GuardedBy("Settings.this.mLock") @@ -5311,11 +5290,88 @@ public final class Settings { } public void deleteUserRuntimePermissionsFile(int userId) { - getUserRuntimePermissionsFile(userId).delete(); + mPersistence.delete(UserHandle.of(userId)); } @GuardedBy("Settings.this.mLock") public void readStateForUserSyncLPr(int userId) { + RuntimePermissionsState runtimePermissions = mPersistence.read(UserHandle.of(userId)); + if (runtimePermissions == null) { + readLegacyStateForUserSyncLPr(userId); + writePermissionsForUserAsyncLPr(userId); + return; + } + + // If the runtime permissions file exists but the version is not set this is + // an upgrade from P->Q. Hence mark it with the special UPGRADE_VERSION. + int version = runtimePermissions.getVersion(); + if (version == RuntimePermissionsState.NO_VERSION) { + version = UPGRADE_VERSION; + } + mVersions.put(userId, version); + + String fingerprint = runtimePermissions.getFingerprint(); + mFingerprints.put(userId, fingerprint); + boolean defaultPermissionsGranted = Build.FINGERPRINT.equals(fingerprint); + mDefaultPermissionsGranted.put(userId, defaultPermissionsGranted); + + for (Map.Entry<String, List<RuntimePermissionsState.PermissionState>> entry + : runtimePermissions.getPackagePermissions().entrySet()) { + String packageName = entry.getKey(); + List<RuntimePermissionsState.PermissionState> permissions = entry.getValue(); + + PackageSetting packageSetting = mPackages.get(packageName); + if (packageSetting == null) { + Slog.w(PackageManagerService.TAG, "Unknown package:" + packageName); + continue; + } + readPermissionsStateLpr(permissions, packageSetting.getPermissionsState(), userId); + } + + for (Map.Entry<String, List<RuntimePermissionsState.PermissionState>> entry + : runtimePermissions.getSharedUserPermissions().entrySet()) { + String sharedUserName = entry.getKey(); + List<RuntimePermissionsState.PermissionState> permissions = entry.getValue(); + + SharedUserSetting sharedUserSetting = mSharedUsers.get(sharedUserName); + if (sharedUserSetting == null) { + Slog.w(PackageManagerService.TAG, "Unknown shared user:" + sharedUserName); + continue; + } + readPermissionsStateLpr(permissions, sharedUserSetting.getPermissionsState(), + userId); + } + } + + private void readPermissionsStateLpr( + @NonNull List<RuntimePermissionsState.PermissionState> permissions, + @NonNull PermissionsState permissionsState, @UserIdInt int userId) { + int permissionsSize = permissions.size(); + for (int i = 0; i < permissionsSize; i++) { + RuntimePermissionsState.PermissionState permission = permissions.get(i); + + String name = permission.getName(); + BasePermission basePermission = mPermissions.getPermission(name); + if (basePermission == null) { + Slog.w(PackageManagerService.TAG, "Unknown permission:" + name); + continue; + } + boolean granted = permission.isGranted(); + int flags = permission.getFlags(); + + if (granted) { + permissionsState.grantRuntimePermission(basePermission, userId); + permissionsState.updatePermissionFlags(basePermission, userId, + PackageManager.MASK_PERMISSION_FLAGS_ALL, flags); + } else { + permissionsState.updatePermissionFlags(basePermission, userId, + PackageManager.MASK_PERMISSION_FLAGS_ALL, flags); + } + } + } + + @GuardedBy("Settings.this.mLock") + private void readLegacyStateForUserSyncLPr(int userId) { File permissionsFile = getUserRuntimePermissionsFile(userId); if (!permissionsFile.exists()) { return; @@ -5435,19 +5491,6 @@ public final class Settings { } } - private void writePermissions(XmlSerializer serializer, - List<PermissionState> permissionStates) throws IOException { - for (PermissionState permissionState : permissionStates) { - serializer.startTag(null, TAG_ITEM); - serializer.attribute(null, ATTR_NAME,permissionState.getName()); - serializer.attribute(null, ATTR_GRANTED, - String.valueOf(permissionState.isGranted())); - serializer.attribute(null, ATTR_FLAGS, - Integer.toHexString(permissionState.getFlags())); - serializer.endTag(null, TAG_ITEM); - } - } - private final class MyHandler extends Handler { public MyHandler() { super(BackgroundThread.getHandler().getLooper()); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index ea83adba4d8a..ec9049ee05ee 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -46,7 +46,6 @@ import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; @@ -55,6 +54,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; @@ -1632,7 +1632,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // If a system window has focus, then it doesn't make sense // right now to interact with applications. if (info.layoutParamsType == TYPE_KEYGUARD_DIALOG - || (info.layoutParamsPrivateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { + || (info.layoutParamsType == TYPE_NOTIFICATION_SHADE + && isKeyguardShowing())) { // the "app" is keyguard, so give it the key return 0; } @@ -2205,12 +2206,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public int getMaxWallpaperLayer() { - return getWindowLayerFromTypeLw(TYPE_STATUS_BAR); + return getWindowLayerFromTypeLw(TYPE_NOTIFICATION_SHADE); } @Override public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) { - return attrs.type == TYPE_STATUS_BAR; + return attrs.type == TYPE_NOTIFICATION_SHADE; } @Override @@ -2221,6 +2222,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return false; } switch (win.getAttrs().type) { + case TYPE_NOTIFICATION_SHADE: case TYPE_STATUS_BAR: case TYPE_NAVIGATION_BAR: case TYPE_WALLPAPER: @@ -2228,7 +2230,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return false; default: // Hide only windows below the keyguard host window. - return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_STATUS_BAR); + return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_NOTIFICATION_SHADE); } } @@ -3445,7 +3447,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardOccluded = false; mKeyguardDelegate.setOccluded(false, true /* animate */); if (mKeyguardCandidate != null) { - mKeyguardCandidate.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; if (!mKeyguardDelegate.hasLockscreenWallpaper()) { mKeyguardCandidate.getAttrs().flags |= FLAG_SHOW_WALLPAPER; } @@ -3455,7 +3456,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardOccluded = true; mKeyguardDelegate.setOccluded(true, false /* animate */); if (mKeyguardCandidate != null) { - mKeyguardCandidate.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; mKeyguardCandidate.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; } return true; @@ -4658,6 +4658,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override + public boolean isKeyguardShowing() { + if (mKeyguardDelegate == null) return false; + return mKeyguardDelegate.isShowing(); + } + + @Override public boolean isKeyguardShowingAndNotOccluded() { if (mKeyguardDelegate == null) return false; return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index b014372fa7cb..c39da5fb0e99 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -39,6 +39,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_PHONE; import static android.view.WindowManager.LayoutParams.TYPE_POINTER; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; @@ -812,55 +813,57 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { return 16; case TYPE_STATUS_BAR: return 17; - case TYPE_STATUS_BAR_PANEL: + case TYPE_NOTIFICATION_SHADE: return 18; - case TYPE_STATUS_BAR_SUB_PANEL: + case TYPE_STATUS_BAR_PANEL: return 19; - case TYPE_KEYGUARD_DIALOG: + case TYPE_STATUS_BAR_SUB_PANEL: return 20; + case TYPE_KEYGUARD_DIALOG: + return 21; case TYPE_VOLUME_OVERLAY: // the on-screen volume indicator and controller shown when the user // changes the device volume - return 21; + return 22; case TYPE_SYSTEM_OVERLAY: // the on-screen volume indicator and controller shown when the user // changes the device volume - return canAddInternalSystemWindow ? 22 : 11; + return canAddInternalSystemWindow ? 23 : 11; case TYPE_NAVIGATION_BAR: // the navigation bar, if available, shows atop most things - return 23; + return 24; case TYPE_NAVIGATION_BAR_PANEL: // some panels (e.g. search) need to show on top of the navigation bar - return 24; + return 25; case TYPE_SCREENSHOT: // screenshot selection layer shouldn't go above system error, but it should cover // navigation bars at the very least. - return 25; + return 26; case TYPE_SYSTEM_ERROR: // system-level error dialogs - return canAddInternalSystemWindow ? 26 : 10; + return canAddInternalSystemWindow ? 27 : 10; case TYPE_MAGNIFICATION_OVERLAY: // used to highlight the magnified portion of a display - return 27; + return 28; case TYPE_DISPLAY_OVERLAY: // used to simulate secondary display devices - return 28; + return 29; case TYPE_DRAG: // the drag layer: input for drag-and-drop is associated with this window, // which sits above all other focusable windows - return 29; + return 30; case TYPE_ACCESSIBILITY_OVERLAY: // overlay put by accessibility services to intercept user interaction - return 30; + return 31; case TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY: - return 31; + return 32; case TYPE_SECURE_SYSTEM_OVERLAY: - return 32; - case TYPE_BOOT_PROGRESS: return 33; + case TYPE_BOOT_PROGRESS: + return 34; case TYPE_POINTER: // the (mouse) pointer layer - return 34; + return 35; default: Slog.e("WindowManager", "Unknown window type: " + type); return APPLICATION_LAYER; @@ -1195,6 +1198,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { public boolean isKeyguardOccluded(); /** + * @return true if in keyguard is on. + */ + boolean isKeyguardShowing(); + + /** * @return true if in keyguard is on and not occluded. */ public boolean isKeyguardShowingAndNotOccluded(); diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java index d33c10c99c08..9f4ca3c6c4ea 100644 --- a/services/core/java/com/android/server/role/RoleUserState.java +++ b/services/core/java/com/android/server/role/RoleUserState.java @@ -23,6 +23,7 @@ import android.annotation.UserIdInt; import android.annotation.WorkerThread; import android.os.Environment; import android.os.Handler; +import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; @@ -34,22 +35,21 @@ import com.android.internal.os.BackgroundThread; import com.android.internal.util.CollectionUtils; import com.android.internal.util.dump.DualDumpOutputStream; import com.android.internal.util.function.pooled.PooledLambda; - -import libcore.io.IoUtils; +import com.android.role.persistence.RolesPersistence; +import com.android.role.persistence.RolesState; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; /** * Stores the state of roles for a user. @@ -71,6 +71,8 @@ public class RoleUserState { private static final String ATTRIBUTE_NAME = "name"; private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash"; + private final RolesPersistence mPersistence = RolesPersistence.createInstance(); + @UserIdInt private final int mUserId; @@ -350,9 +352,7 @@ public class RoleUserState { @WorkerThread private void writeFile() { - int version; - String packagesHash; - ArrayMap<String, ArraySet<String>> roles; + RolesState roles; synchronized (mLock) { if (mDestroyed) { return; @@ -360,90 +360,45 @@ public class RoleUserState { mWriteScheduled = false; - version = mVersion; - packagesHash = mPackagesHash; - roles = snapshotRolesLocked(); + roles = new RolesState(mVersion, mPackagesHash, + (Map<String, Set<String>>) (Map<String, ?>) snapshotRolesLocked()); } - AtomicFile atomicFile = new AtomicFile(getFile(mUserId), "roles-" + mUserId); - FileOutputStream out = null; - try { - out = atomicFile.startWrite(); - - XmlSerializer serializer = Xml.newSerializer(); - serializer.setOutput(out, StandardCharsets.UTF_8.name()); - serializer.setFeature( - "http://xmlpull.org/v1/doc/features.html#indent-output", true); - serializer.startDocument(null, true); - - serializeRoles(serializer, version, packagesHash, roles); - - serializer.endDocument(); - atomicFile.finishWrite(out); - Slog.i(LOG_TAG, "Wrote roles.xml successfully"); - } catch (IllegalArgumentException | IllegalStateException | IOException e) { - Slog.wtf(LOG_TAG, "Failed to write roles.xml, restoring backup", e); - if (out != null) { - atomicFile.failWrite(out); - } - } finally { - IoUtils.closeQuietly(out); - } + mPersistence.write(roles, UserHandle.of(mUserId)); } - @WorkerThread - private void serializeRoles(@NonNull XmlSerializer serializer, int version, - @Nullable String packagesHash, @NonNull ArrayMap<String, ArraySet<String>> roles) - throws IOException { - serializer.startTag(null, TAG_ROLES); - - serializer.attribute(null, ATTRIBUTE_VERSION, Integer.toString(version)); - - if (packagesHash != null) { - serializer.attribute(null, ATTRIBUTE_PACKAGES_HASH, packagesHash); - } - - for (int i = 0, size = roles.size(); i < size; ++i) { - String roleName = roles.keyAt(i); - ArraySet<String> roleHolders = roles.valueAt(i); - - serializer.startTag(null, TAG_ROLE); - serializer.attribute(null, ATTRIBUTE_NAME, roleName); - serializeRoleHolders(serializer, roleHolders); - serializer.endTag(null, TAG_ROLE); - } + private void readFile() { + synchronized (mLock) { + RolesState roles = mPersistence.read(UserHandle.of(mUserId)); + if (roles == null) { + readLegacyFileLocked(); + scheduleWriteFileLocked(); + return; + } - serializer.endTag(null, TAG_ROLES); - } + mVersion = roles.getVersion(); + mPackagesHash = roles.getPackagesHash(); - @WorkerThread - private void serializeRoleHolders(@NonNull XmlSerializer serializer, - @NonNull ArraySet<String> roleHolders) throws IOException { - for (int i = 0, size = roleHolders.size(); i < size; ++i) { - String roleHolder = roleHolders.valueAt(i); - - serializer.startTag(null, TAG_HOLDER); - serializer.attribute(null, ATTRIBUTE_NAME, roleHolder); - serializer.endTag(null, TAG_HOLDER); + mRoles.clear(); + for (Map.Entry<String, Set<String>> entry : roles.getRoles().entrySet()) { + String roleName = entry.getKey(); + ArraySet<String> roleHolders = new ArraySet<>(entry.getValue()); + mRoles.put(roleName, roleHolders); + } } } - /** - * Read the state from file. - */ - private void readFile() { - synchronized (mLock) { - File file = getFile(mUserId); - try (FileInputStream in = new AtomicFile(file).openRead()) { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(in, null); - parseXmlLocked(parser); - Slog.i(LOG_TAG, "Read roles.xml successfully"); - } catch (FileNotFoundException e) { - Slog.i(LOG_TAG, "roles.xml not found"); - } catch (XmlPullParserException | IOException e) { - throw new IllegalStateException("Failed to parse roles.xml: " + file, e); - } + private void readLegacyFileLocked() { + File file = getFile(mUserId); + try (FileInputStream in = new AtomicFile(file).openRead()) { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(in, null); + parseXmlLocked(parser); + Slog.i(LOG_TAG, "Read roles.xml successfully"); + } catch (FileNotFoundException e) { + Slog.i(LOG_TAG, "roles.xml not found"); + } catch (XmlPullParserException | IOException e) { + throw new IllegalStateException("Failed to parse roles.xml: " + file, e); } } @@ -590,7 +545,7 @@ public class RoleUserState { throw new IllegalStateException("This RoleUserState has already been destroyed"); } mWriteHandler.removeCallbacksAndMessages(null); - getFile(mUserId).delete(); + mPersistence.delete(UserHandle.of(mUserId)); mDestroyed = true; } } 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 1e856884eeed..b11ec6fd97fb 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -168,6 +168,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.MissingResourceException; import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -198,9 +199,16 @@ public class StatsPullAtomService extends SystemService { private final Object mThermalLock = new Object(); @GuardedBy("mThermalLock") private IThermalService mThermalService; + private final Object mStoragedLock = new Object(); + @GuardedBy("mStoragedLock") + private IStoraged mStorageService; + private final Object mNotificationStatsLock = new Object(); + @GuardedBy("mNotificationStatsLock") + private INotificationManager mNotificationManagerService; private final Context mContext; private StatsManager mStatsManager; + private StorageManager mStorageManager; public StatsPullAtomService(Context context) { super(context); @@ -212,6 +220,7 @@ public class StatsPullAtomService extends SystemService { mStatsManager = (StatsManager) mContext.getSystemService(Context.STATS_MANAGER); mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); mTelephony = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class); // Used to initialize the CPU Frequency atom. PowerProfile powerProfile = new PowerProfile(mContext); @@ -224,6 +233,10 @@ public class StatsPullAtomService extends SystemService { numSpeedSteps); firstCpuOfCluster += powerProfile.getNumCoresInCpuCluster(i); } + + // Used for CPU_TIME_PER_THREAD_FREQ + mKernelCpuThreadReader = + KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext); } @Override @@ -291,7 +304,6 @@ public class StatsPullAtomService extends SystemService { registerDebugFailingElapsedClock(); registerBuildInformation(); registerRoleHolder(); - registerDangerousPermissionState(); registerTimeZoneDataInfo(); registerExternalStorageInfo(); registerAppsOnExternalStorageInfo(); @@ -346,6 +358,51 @@ public class StatsPullAtomService extends SystemService { return mThermalService; } } + + private IStoraged getIStoragedService() { + synchronized (mStoragedLock) { + if (mStorageService == null) { + mStorageService = IStoraged.Stub.asInterface( + ServiceManager.getService("storaged")); + } + if (mStorageService != null) { + try { + mStorageService.asBinder().linkToDeath(() -> { + synchronized (mStoragedLock) { + mStorageService = null; + } + }, /* flags */ 0); + } catch (RemoteException e) { + Slog.e(TAG, "linkToDeath with storagedService failed", e); + mStorageService = null; + } + } + } + return mStorageService; + } + + private INotificationManager getINotificationManagerService() { + synchronized (mNotificationStatsLock) { + if (mNotificationManagerService == null) { + mNotificationManagerService = INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE)); + } + if (mNotificationManagerService != null) { + try { + mNotificationManagerService.asBinder().linkToDeath(() -> { + synchronized (mNotificationStatsLock) { + mNotificationManagerService = null; + } + }, /* flags */ 0); + } catch (RemoteException e) { + Slog.e(TAG, "linkToDeath with notificationManager failed", e); + mNotificationManagerService = null; + } + } + } + return mNotificationManagerService; + } + private void registerWifiBytesTransfer() { int tagId = StatsLog.WIFI_BYTES_TRANSFER; PullAtomMetadata metadata = new PullAtomMetadata.Builder() @@ -935,12 +992,29 @@ public class StatsPullAtomService extends SystemService { return StatsManager.PULL_SUCCESS; } + private static final long NS_PER_SEC = 1000000000; + private void registerSystemElapsedRealtime() { - // No op. + int tagId = StatsLog.SYSTEM_ELAPSED_REALTIME; + PullAtomMetadata metadata = PullAtomMetadata.newBuilder() + .setCoolDownNs(NS_PER_SEC) + .setTimeoutNs(NS_PER_SEC / 2) + .build(); + mStatsManager.registerPullAtomCallback( + tagId, + metadata, + (atomTag, data) -> pullSystemElapsedRealtime(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullSystemElapsedRealtime() { - // No op. + private int pullSystemElapsedRealtime(int atomTag, List<StatsEvent> pulledData) { + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeLong(SystemClock.elapsedRealtime()) + .build(); + pulledData.add(e); + return StatsManager.PULL_SUCCESS; } private void registerSystemUptime() { @@ -1426,59 +1500,372 @@ public class StatsPullAtomService extends SystemService { } private void registerLooperStats() { - // No op. + int tagId = StatsLog.LOOPER_STATS; + PullAtomMetadata metadata = PullAtomMetadata.newBuilder() + .setAdditiveFields(new int[] {5, 6, 7, 8, 9}) + .build(); + mStatsManager.registerPullAtomCallback( + tagId, + metadata, + (atomTag, data) -> pullLooperStats(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullLooperStats() { - // No op. + private int pullLooperStats(int atomTag, List<StatsEvent> pulledData) { + LooperStats looperStats = LocalServices.getService(LooperStats.class); + if (looperStats == null) { + return StatsManager.PULL_SKIP; + } + + List<LooperStats.ExportedEntry> entries = looperStats.getEntries(); + looperStats.reset(); + for (LooperStats.ExportedEntry entry : entries) { + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(entry.workSourceUid) + .writeString(entry.handlerClassName) + .writeString(entry.threadName) + .writeString(entry.messageName) + .writeLong(entry.messageCount) + .writeLong(entry.exceptionCount) + .writeLong(entry.recordedMessageCount) + .writeLong(entry.totalLatencyMicros) + .writeLong(entry.cpuUsageMicros) + .writeBoolean(entry.isInteractive) + .writeLong(entry.maxCpuUsageMicros) + .writeLong(entry.maxLatencyMicros) + .writeLong(entry.recordedDelayMessageCount) + .writeLong(entry.delayMillis) + .writeLong(entry.maxDelayMillis) + .build(); + pulledData.add(e); + } + return StatsManager.PULL_SUCCESS; } private void registerDiskStats() { - // No op. + int tagId = StatsLog.DISK_STATS; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullDiskStats(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullDiskStats() { - // No op. + private int pullDiskStats(int atomTag, List<StatsEvent> pulledData) { + // Run a quick-and-dirty performance test: write 512 bytes + byte[] junk = new byte[512]; + for (int i = 0; i < junk.length; i++) junk[i] = (byte) i; // Write nonzero bytes + + File tmp = new File(Environment.getDataDirectory(), "system/statsdperftest.tmp"); + FileOutputStream fos = null; + IOException error = null; + + long before = SystemClock.elapsedRealtime(); + try { + fos = new FileOutputStream(tmp); + fos.write(junk); + } catch (IOException e) { + error = e; + } finally { + try { + if (fos != null) fos.close(); + } catch (IOException e) { + // Do nothing. + } + } + + long latency = SystemClock.elapsedRealtime() - before; + if (tmp.exists()) tmp.delete(); + + if (error != null) { + Slog.e(TAG, "Error performing diskstats latency test"); + latency = -1; + } + // File based encryption. + boolean fileBased = StorageManager.isFileEncryptedNativeOnly(); + + //Recent disk write speed. Binder call to storaged. + int writeSpeed = -1; + IStoraged storaged = getIStoragedService(); + if (storaged == null) { + return StatsManager.PULL_SKIP; + } + try { + writeSpeed = storaged.getRecentPerf(); + } catch (RemoteException e) { + Slog.e(TAG, "storaged not found"); + } + + // Add info pulledData. + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeLong(latency) + .writeBoolean(fileBased) + .writeInt(writeSpeed) + .build(); + pulledData.add(e); + return StatsManager.PULL_SUCCESS; } private void registerDirectoryUsage() { - // No op. + int tagId = StatsLog.DIRECTORY_USAGE; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullDirectoryUsage(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullDirectoryUsage() { - // No op. + private int pullDirectoryUsage(int atomTag, List<StatsEvent> pulledData) { + StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath()); + StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath()); + StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath()); + + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__DATA) + .writeLong(statFsData.getAvailableBytes()) + .writeLong(statFsData.getTotalBytes()) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE) + .writeLong(statFsCache.getAvailableBytes()) + .writeLong(statFsCache.getTotalBytes()) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM) + .writeLong(statFsSystem.getAvailableBytes()) + .writeLong(statFsSystem.getTotalBytes()) + .build(); + pulledData.add(e); + return StatsManager.PULL_SUCCESS; } private void registerAppSize() { - // No op. + int tagId = StatsLog.APP_SIZE; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullAppSize(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullAppSize() { - // No op. + private int pullAppSize(int atomTag, List<StatsEvent> pulledData) { + try { + String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH); + JSONObject json = new JSONObject(jsonStr); + long cache_time = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L); + JSONArray pkg_names = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY); + JSONArray app_sizes = json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY); + JSONArray app_data_sizes = json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY); + JSONArray app_cache_sizes = json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY); + // Sanity check: Ensure all 4 lists have the same length. + int length = pkg_names.length(); + if (app_sizes.length() != length || app_data_sizes.length() != length + || app_cache_sizes.length() != length) { + Slog.e(TAG, "formatting error in diskstats cache file!"); + return StatsManager.PULL_SKIP; + } + for (int i = 0; i < length; i++) { + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeString(pkg_names.getString(i)) + .writeLong(app_sizes.optLong(i, /* fallback */ -1L)) + .writeLong(app_data_sizes.optLong(i, /* fallback */ -1L)) + .writeLong(app_cache_sizes.optLong(i, /* fallback */ -1L)) + .writeLong(cache_time) + .build(); + pulledData.add(e); + } + } catch (IOException | JSONException e) { + Slog.e(TAG, "exception reading diskstats cache file", e); + return StatsManager.PULL_SKIP; + } + return StatsManager.PULL_SUCCESS; } private void registerCategorySize() { - // No op. + int tagId = StatsLog.CATEGORY_SIZE; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullCategorySize(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullCategorySize() { - // No op. - } + private int pullCategorySize(int atomTag, List<StatsEvent> pulledData) { + try { + String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH); + JSONObject json = new JSONObject(jsonStr); + long cacheTime = json.optLong( + DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, /* fallback */ -1L); - private void registerNumFingerprintsEnrolled() { - // No op. + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE) + .writeLong(json.optLong( + DiskStatsFileLogger.APP_SIZE_AGG_KEY, /* fallback */ -1L)) + .writeLong(cacheTime) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE) + .writeLong(json.optLong( + DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY, /* fallback */ -1L)) + .writeLong(cacheTime) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE) + .writeLong(json.optLong( + DiskStatsFileLogger.APP_CACHE_AGG_KEY, /* fallback */ -1L)) + .writeLong(cacheTime) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS) + .writeLong(json.optLong( + DiskStatsFileLogger.PHOTOS_KEY, /* fallback */ -1L)) + .writeLong(cacheTime) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS) + .writeLong( + json.optLong(DiskStatsFileLogger.VIDEOS_KEY, /* fallback */ -1L)) + .writeLong(cacheTime) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__AUDIO) + .writeLong(json.optLong( + DiskStatsFileLogger.AUDIO_KEY, /* fallback */ -1L)) + .writeLong(cacheTime) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS) + .writeLong( + json.optLong(DiskStatsFileLogger.DOWNLOADS_KEY, /* fallback */ -1L)) + .writeLong(cacheTime) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM) + .writeLong(json.optLong( + DiskStatsFileLogger.SYSTEM_KEY, /* fallback */ -1L)) + .writeLong(cacheTime) + .build(); + pulledData.add(e); + + e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__OTHER) + .writeLong(json.optLong( + DiskStatsFileLogger.MISC_KEY, /* fallback */ -1L)) + .writeLong(cacheTime) + .build(); + pulledData.add(e); + } catch (IOException | JSONException e) { + Slog.e(TAG, "exception reading diskstats cache file", e); + return StatsManager.PULL_SKIP; + } + return StatsManager.PULL_SUCCESS; } - private void pullNumFingerprintsEnrolled() { - // No op. + private void registerNumFingerprintsEnrolled() { + int tagId = StatsLog.NUM_FINGERPRINTS_ENROLLED; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullNumBiometricsEnrolled( + BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data), + BackgroundThread.getExecutor() + ); } private void registerNumFacesEnrolled() { - // No op. + int tagId = StatsLog.NUM_FACES_ENROLLED; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullNumBiometricsEnrolled( + BiometricsProtoEnums.MODALITY_FACE, atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullNumFacesEnrolled() { - // No op. + private int pullNumBiometricsEnrolled(int modality, int atomTag, List<StatsEvent> pulledData) { + final PackageManager pm = mContext.getPackageManager(); + FingerprintManager fingerprintManager = null; + FaceManager faceManager = null; + + if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { + fingerprintManager = mContext.getSystemService(FingerprintManager.class); + } + if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) { + faceManager = mContext.getSystemService(FaceManager.class); + } + + if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT && fingerprintManager == null) { + return StatsManager.PULL_SKIP; + } + if (modality == BiometricsProtoEnums.MODALITY_FACE && faceManager == null) { + return StatsManager.PULL_SKIP; + } + UserManager userManager = mContext.getSystemService(UserManager.class); + if (userManager == null) { + return StatsManager.PULL_SKIP; + } + + final long token = Binder.clearCallingIdentity(); + try { + for (UserInfo user : userManager.getUsers()) { + final int userId = user.getUserHandle().getIdentifier(); + int numEnrolled = 0; + if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT) { + numEnrolled = fingerprintManager.getEnrolledFingerprints(userId).size(); + } else if (modality == BiometricsProtoEnums.MODALITY_FACE) { + numEnrolled = faceManager.getEnrolledFaces(userId).size(); + } else { + return StatsManager.PULL_SKIP; + } + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(userId) + .writeInt(numEnrolled) + .build(); + pulledData.add(e); + } + } finally { + Binder.restoreCallingIdentity(token); + } + return StatsManager.PULL_SUCCESS; } private void registerProcStats() { @@ -1497,12 +1884,44 @@ public class StatsPullAtomService extends SystemService { // No op. } + private StoragedUidIoStatsReader mStoragedUidIoStatsReader = + new StoragedUidIoStatsReader(); + private void registerDiskIO() { - // No op. + int tagId = StatsLog.DISK_IO; + PullAtomMetadata metadata = PullAtomMetadata.newBuilder() + .setAdditiveFields(new int[] {2, 3, 4, 5, 6, 7, 8, 9, 10, 11}) + .setCoolDownNs(3 * NS_PER_SEC) + .build(); + mStatsManager.registerPullAtomCallback( + tagId, + metadata, + (atomTag, data) -> pullDiskIO(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullDiskIO() { - // No op. + private int pullDiskIO(int atomTag, List<StatsEvent> pulledData) { + mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead, + fgBytesWrite, bgCharsRead, bgCharsWrite, bgBytesRead, bgBytesWrite, + fgFsync, bgFsync) -> { + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(uid) + .writeLong(fgCharsRead) + .writeLong(fgCharsWrite) + .writeLong(fgBytesRead) + .writeLong(fgBytesWrite) + .writeLong(bgCharsRead) + .writeLong(bgCharsWrite) + .writeLong(bgBytesRead) + .writeLong(bgBytesWrite) + .writeLong(fgFsync) + .writeLong(bgFsync) + .build(); + pulledData.add(e); + }); + return StatsManager.PULL_SUCCESS; } private void registerPowerProfile() { @@ -1528,20 +1947,118 @@ public class StatsPullAtomService extends SystemService { return StatsManager.PULL_SUCCESS; } + private final Object mCpuTrackerLock = new Object(); + @GuardedBy("mCpuTrackerLock") + private ProcessCpuTracker mProcessCpuTracker; + private void registerProcessCpuTime() { - // No op. + int tagId = StatsLog.PROCESS_CPU_TIME; + // Min cool-down is 5 sec, inline with what ActivityManagerService uses. + PullAtomMetadata metadata = PullAtomMetadata.newBuilder() + .setCoolDownNs(5 * NS_PER_SEC) + .build(); + mStatsManager.registerPullAtomCallback( + tagId, + metadata, + (atomTag, data) -> pullProcessCpuTime(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullProcessCpuTime() { - // No op. + private int pullProcessCpuTime(int atomTag, List<StatsEvent> pulledData) { + synchronized (mCpuTrackerLock) { + if (mProcessCpuTracker == null) { + mProcessCpuTracker = new ProcessCpuTracker(false); + mProcessCpuTracker.init(); + } + mProcessCpuTracker.update(); + for (int i = 0; i < mProcessCpuTracker.countStats(); i++) { + ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(st.uid) + .writeString(st.name) + .writeLong(st.base_utime) + .writeLong(st.base_stime) + .build(); + pulledData.add(e); + } + } + return StatsManager.PULL_SUCCESS; } + @Nullable + private KernelCpuThreadReaderDiff mKernelCpuThreadReader; + private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8; + private void registerCpuTimePerThreadFreq() { - // No op. + int tagId = StatsLog.CPU_TIME_PER_THREAD_FREQ; + PullAtomMetadata metadata = PullAtomMetadata.newBuilder() + .setAdditiveFields(new int[] {7, 9, 11, 13, 15, 17, 19, 21}) + .build(); + mStatsManager.registerPullAtomCallback( + tagId, + metadata, + (atomTag, data) -> pullCpuTimePerThreadFreq(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullCpuTimePerThreadFreq() { - // No op. + private int pullCpuTimePerThreadFreq(int atomTag, List<StatsEvent> pulledData) { + if (this.mKernelCpuThreadReader == null) { + Slog.e(TAG, "mKernelCpuThreadReader is null"); + return StatsManager.PULL_SKIP; + } + ArrayList<KernelCpuThreadReader.ProcessCpuUsage> processCpuUsages = + this.mKernelCpuThreadReader.getProcessCpuUsageDiffed(); + if (processCpuUsages == null) { + Slog.e(TAG, "processCpuUsages is null"); + return StatsManager.PULL_SKIP; + } + int[] cpuFrequencies = mKernelCpuThreadReader.getCpuFrequenciesKhz(); + if (cpuFrequencies.length > CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES) { + String message = "Expected maximum " + CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES + + " frequencies, but got " + cpuFrequencies.length; + Slog.w(TAG, message); + return StatsManager.PULL_SKIP; + } + for (int i = 0; i < processCpuUsages.size(); i++) { + KernelCpuThreadReader.ProcessCpuUsage processCpuUsage = processCpuUsages.get(i); + ArrayList<KernelCpuThreadReader.ThreadCpuUsage> threadCpuUsages = + processCpuUsage.threadCpuUsages; + for (int j = 0; j < threadCpuUsages.size(); j++) { + KernelCpuThreadReader.ThreadCpuUsage threadCpuUsage = threadCpuUsages.get(j); + if (threadCpuUsage.usageTimesMillis.length != cpuFrequencies.length) { + String message = "Unexpected number of usage times," + + " expected " + cpuFrequencies.length + + " but got " + threadCpuUsage.usageTimesMillis.length; + Slog.w(TAG, message); + return StatsManager.PULL_SKIP; + } + + StatsEvent.Builder e = StatsEvent.newBuilder(); + e.setAtomId(atomTag); + e.writeInt(processCpuUsage.uid); + e.writeInt(processCpuUsage.processId); + e.writeInt(threadCpuUsage.threadId); + e.writeString(processCpuUsage.processName); + e.writeString(threadCpuUsage.threadName); + for (int k = 0; k < CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES; k++) { + if (k < cpuFrequencies.length) { + e.writeInt(cpuFrequencies[k]); + e.writeInt(threadCpuUsage.usageTimesMillis[k]); + } else { + // If we have no more frequencies to write, we still must write empty data. + // We know that this data is empty (and not just zero) because all + // frequencies are expected to be greater than zero + e.writeInt(0); + e.writeInt(0); + } + } + pulledData.add(e.build()); + } + } + return StatsManager.PULL_SUCCESS; } // TODO: move to top of file when all migrations are complete @@ -1703,43 +2220,280 @@ public class StatsPullAtomService extends SystemService { } private void registerRoleHolder() { - // No op. + int tagId = StatsLog.ROLE_HOLDER; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullRoleHolder(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullRoleHolder() { - // No op. + // Add a RoleHolder atom for each package that holds a role. + private int pullRoleHolder(int atomTag, List<StatsEvent> pulledData) { + long callingToken = Binder.clearCallingIdentity(); + try { + PackageManager pm = mContext.getPackageManager(); + RoleManagerInternal rmi = LocalServices.getService(RoleManagerInternal.class); + + List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); + + int numUsers = users.size(); + for (int userNum = 0; userNum < numUsers; userNum++) { + int userId = users.get(userNum).getUserHandle().getIdentifier(); + + ArrayMap<String, ArraySet<String>> roles = rmi.getRolesAndHolders(userId); + + int numRoles = roles.size(); + for (int roleNum = 0; roleNum < numRoles; roleNum++) { + String roleName = roles.keyAt(roleNum); + ArraySet<String> holders = roles.valueAt(roleNum); + + int numHolders = holders.size(); + for (int holderNum = 0; holderNum < numHolders; holderNum++) { + String holderName = holders.valueAt(holderNum); + + PackageInfo pkg; + try { + pkg = pm.getPackageInfoAsUser(holderName, 0, userId); + } catch (PackageManager.NameNotFoundException e) { + Slog.w(TAG, "Role holder " + holderName + " not found"); + return StatsManager.PULL_SKIP; + } + + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(pkg.applicationInfo.uid) + .writeString(holderName) + .writeString(roleName) + .build(); + pulledData.add(e); + } + } + } + } finally { + Binder.restoreCallingIdentity(callingToken); + } + return StatsManager.PULL_SUCCESS; } private void registerDangerousPermissionState() { - // No op. + int tagId = StatsLog.DANGEROUS_PERMISSION_STATE; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullDangerousPermissionState(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullDangerousPermissionState() { - // No op. + private int pullDangerousPermissionState(int atomTag, List<StatsEvent> pulledData) { + final long token = Binder.clearCallingIdentity(); + Set<Integer> reportedUids = new HashSet<>(); + try { + PackageManager pm = mContext.getPackageManager(); + + List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); + + int numUsers = users.size(); + for (int userNum = 0; userNum < numUsers; userNum++) { + UserHandle user = users.get(userNum).getUserHandle(); + + List<PackageInfo> pkgs = pm.getInstalledPackagesAsUser( + PackageManager.GET_PERMISSIONS, user.getIdentifier()); + + int numPkgs = pkgs.size(); + for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) { + PackageInfo pkg = pkgs.get(pkgNum); + + if (pkg.requestedPermissions == null) { + continue; + } + + if (reportedUids.contains(pkg.applicationInfo.uid)) { + // do not report same uid twice + continue; + } + reportedUids.add(pkg.applicationInfo.uid); + + if (atomTag == StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED + && ThreadLocalRandom.current().nextFloat() > 0.2f) { + continue; + } + + int numPerms = pkg.requestedPermissions.length; + for (int permNum = 0; permNum < numPerms; permNum++) { + String permName = pkg.requestedPermissions[permNum]; + + PermissionInfo permissionInfo; + int permissionFlags = 0; + try { + permissionInfo = pm.getPermissionInfo(permName, 0); + permissionFlags = + pm.getPermissionFlags(permName, pkg.packageName, user); + } catch (PackageManager.NameNotFoundException ignored) { + continue; + } + + if (permissionInfo.getProtection() != PROTECTION_DANGEROUS) { + continue; + } + + StatsEvent.Builder e = StatsEvent.newBuilder(); + e.setAtomId(atomTag); + e.writeString(permName); + e.writeInt(pkg.applicationInfo.uid); + if (atomTag == StatsLog.DANGEROUS_PERMISSION_STATE) { + e.writeString(""); + } + e.writeBoolean((pkg.requestedPermissionsFlags[permNum] + & REQUESTED_PERMISSION_GRANTED) != 0); + e.writeInt(permissionFlags); + + pulledData.add(e.build()); + } + } + } + } catch (Throwable t) { + Log.e(TAG, "Could not read permissions", t); + return StatsManager.PULL_SKIP; + } finally { + Binder.restoreCallingIdentity(token); + } + return StatsManager.PULL_SUCCESS; } private void registerTimeZoneDataInfo() { - // No op. + int tagId = StatsLog.TIME_ZONE_DATA_INFO; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullTimeZoneDataInfo(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullTimeZoneDataInfo() { - // No op. + private int pullTimeZoneDataInfo(int atomTag, List<StatsEvent> pulledData) { + String tzDbVersion = "Unknown"; + try { + tzDbVersion = android.icu.util.TimeZone.getTZDataVersion(); + } catch (MissingResourceException e) { + Slog.e(TAG, "Getting tzdb version failed: ", e); + return StatsManager.PULL_SKIP; + } + + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeString(tzDbVersion) + .build(); + pulledData.add(e); + return StatsManager.PULL_SUCCESS; } private void registerExternalStorageInfo() { - // No op. + int tagId = StatsLog.EXTERNAL_STORAGE_INFO; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullExternalStorageInfo(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullExternalStorageInfo() { - // No op. + private int pullExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) { + if (mStorageManager == null) { + return StatsManager.PULL_SKIP; + } + + List<VolumeInfo> volumes = mStorageManager.getVolumes(); + for (VolumeInfo vol : volumes) { + final String envState = VolumeInfo.getEnvironmentForState(vol.getState()); + final DiskInfo diskInfo = vol.getDisk(); + if (diskInfo != null && envState.equals(Environment.MEDIA_MOUNTED)) { + // Get the type of the volume, if it is adoptable or portable. + int volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__OTHER; + if (vol.getType() == TYPE_PUBLIC) { + volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PUBLIC; + } else if (vol.getType() == TYPE_PRIVATE) { + volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PRIVATE; + } + + // Get the type of external storage inserted in the device (sd cards, usb, etc.) + int externalStorageType; + if (diskInfo.isSd()) { + externalStorageType = StorageEnums.SD_CARD; + } else if (diskInfo.isUsb()) { + externalStorageType = StorageEnums.USB; + } else { + externalStorageType = StorageEnums.OTHER; + } + + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(externalStorageType) + .writeInt(volumeType) + .writeLong(diskInfo.size) + .build(); + pulledData.add(e); + } + } + return StatsManager.PULL_SUCCESS; } private void registerAppsOnExternalStorageInfo() { - // No op. + int tagId = StatsLog.APPS_ON_EXTERNAL_STORAGE_INFO; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullAppsOnExternalStorageInfo(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullAppsOnExternalStorageInfo() { - // No op. + private int pullAppsOnExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) { + if (mStorageManager == null) { + return StatsManager.PULL_SKIP; + } + + PackageManager pm = mContext.getPackageManager(); + List<ApplicationInfo> apps = pm.getInstalledApplications(/*flags=*/ 0); + for (ApplicationInfo appInfo : apps) { + UUID storageUuid = appInfo.storageUuid; + if (storageUuid == null) { + continue; + } + + VolumeInfo volumeInfo = mStorageManager.findVolumeByUuid( + appInfo.storageUuid.toString()); + if (volumeInfo == null) { + continue; + } + + DiskInfo diskInfo = volumeInfo.getDisk(); + if (diskInfo == null) { + continue; + } + + int externalStorageType = -1; + if (diskInfo.isSd()) { + externalStorageType = StorageEnums.SD_CARD; + } else if (diskInfo.isUsb()) { + externalStorageType = StorageEnums.USB; + } else if (appInfo.isExternal()) { + externalStorageType = StorageEnums.OTHER; + } + + // App is installed on external storage. + if (externalStorageType != -1) { + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(externalStorageType) + .writeString(appInfo.packageName) + .build(); + pulledData.add(e); + } + } + return StatsManager.PULL_SUCCESS; } private void registerFaceSettings() { @@ -1751,26 +2505,167 @@ public class StatsPullAtomService extends SystemService { } private void registerAppOps() { - // No op. + int tagId = StatsLog.APP_OPS; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullAppOps(atomTag, data), + BackgroundThread.getExecutor() + ); + } - private void pullAppOps() { - // No op. + private int pullAppOps(int atomTag, List<StatsEvent> pulledData) { + long token = Binder.clearCallingIdentity(); + try { + AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); + + CompletableFuture<HistoricalOps> ops = new CompletableFuture<>(); + HistoricalOpsRequest histOpsRequest = + new HistoricalOpsRequest.Builder(0, Long.MAX_VALUE).build(); + appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete); + + HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS, + TimeUnit.MILLISECONDS); + + for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) { + final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx); + final int uid = uidOps.getUid(); + for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) { + final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx); + for (int opIdx = 0; opIdx < packageOps.getOpCount(); opIdx++) { + final AppOpsManager.HistoricalOp op = packageOps.getOpAt(opIdx); + + StatsEvent.Builder e = StatsEvent.newBuilder(); + e.setAtomId(atomTag); + e.writeInt(uid); + e.writeString(packageOps.getPackageName()); + e.writeInt(op.getOpCode()); + e.writeLong(op.getForegroundAccessCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getForegroundRejectCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_ALL_TRUSTED)); + + String perm = AppOpsManager.opToPermission(op.getOpCode()); + if (perm == null) { + e.writeBoolean(false); + } else { + PermissionInfo permInfo; + try { + permInfo = mContext.getPackageManager().getPermissionInfo(perm, 0); + e.writeBoolean(permInfo.getProtection() == PROTECTION_DANGEROUS); + } catch (PackageManager.NameNotFoundException exception) { + e.writeBoolean(false); + } + } + + pulledData.add(e.build()); + } + } + } + } catch (Throwable t) { + // TODO: catch exceptions at a more granular level + Slog.e(TAG, "Could not read appops", t); + return StatsManager.PULL_SKIP; + } finally { + Binder.restoreCallingIdentity(token); + } + return StatsManager.PULL_SUCCESS; } - private void registerNotificationRemoteViews() { - // No op. + static void unpackStreamedData(int atomTag, List<StatsEvent> pulledData, + List<ParcelFileDescriptor> statsFiles) throws IOException { + InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(statsFiles.get(0)); + int[] len = new int[1]; + byte[] stats = readFully(stream, len); + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeByteArray(Arrays.copyOf(stats, len[0])) + .build(); + pulledData.add(e); } - private void pullNotificationRemoteViews() { - // No op. + static byte[] readFully(InputStream stream, int[] outLen) throws IOException { + int pos = 0; + final int initialAvail = stream.available(); + byte[] data = new byte[initialAvail > 0 ? (initialAvail + 1) : 16384]; + while (true) { + int amt = stream.read(data, pos, data.length - pos); + if (DEBUG) { + Slog.i(TAG, "Read " + amt + " bytes at " + pos + " of avail " + data.length); + } + if (amt < 0) { + if (DEBUG) { + Slog.i(TAG, "**** FINISHED READING: pos=" + pos + " len=" + data.length); + } + outLen[0] = pos; + return data; + } + pos += amt; + if (pos >= data.length) { + byte[] newData = new byte[pos + 16384]; + if (DEBUG) { + Slog.i(TAG, "Copying " + pos + " bytes to new array len " + newData.length); + } + System.arraycopy(data, 0, newData, 0, pos); + data = newData; + } + } } - private void registerDangerousPermissionStateSampled() { - // No op. + private void registerNotificationRemoteViews() { + int tagId = StatsLog.NOTIFICATION_REMOTE_VIEWS; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullNotificationRemoteViews(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullDangerousPermissionStateSampled() { - // No op. + private int pullNotificationRemoteViews(int atomTag, List<StatsEvent> pulledData) { + INotificationManager notificationManagerService = getINotificationManagerService(); + if (notificationManagerService == null) { + return StatsManager.PULL_SKIP; + } + final long callingToken = Binder.clearCallingIdentity(); + try { + // determine last pull tine. Copy file trick from pullProcessStats? + long wallClockNanos = SystemClock.currentTimeMicro() * 1000L; + long lastNotificationStatsNs = wallClockNanos - + TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS); + + List<ParcelFileDescriptor> statsFiles = new ArrayList<>(); + notificationManagerService.pullStats(lastNotificationStatsNs, + NotificationManagerService.REPORT_REMOTE_VIEWS, true, statsFiles); + if (statsFiles.size() != 1) { + return StatsManager.PULL_SKIP; + } + unpackStreamedData(atomTag, pulledData, statsFiles); + } catch (IOException e) { + Slog.e(TAG, "Getting notistats failed: ", e); + return StatsManager.PULL_SKIP; + } catch (RemoteException e) { + Slog.e(TAG, "Getting notistats failed: ", e); + return StatsManager.PULL_SKIP; + } catch (SecurityException e) { + Slog.e(TAG, "Getting notistats failed: ", e); + return StatsManager.PULL_SKIP; + } finally { + Binder.restoreCallingIdentity(callingToken); + } + return StatsManager.PULL_SUCCESS; + } + + private void registerDangerousPermissionStateSampled() { + int tagId = StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullDangerousPermissionState(atomTag, data), + BackgroundThread.getExecutor() + ); } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index b596d2a207f0..8bc8ff4fb492 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4089,11 +4089,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, - boolean isVoiceInteraction) { + boolean isVoiceInteraction, @Nullable Runnable animationFinishedCallback) { if (mUseTransferredAnimation) { return false; } - return super.applyAnimation(lp, transit, enter, isVoiceInteraction); + return super.applyAnimation(lp, transit, enter, isVoiceInteraction, + animationFinishedCallback); } /** diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index f5fba8e85d64..9e32ea085135 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -4946,18 +4946,6 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn } } - @Override - protected void onAnimationFinished() { - super.onAnimationFinished(); - // TODO(b/142617871): we may need to add animation type parameter on onAnimationFinished to - // identify if the callback is for launch animation finish and then calling - // activity#onAnimationFinished. - final ActivityRecord activity = getTopMostActivity(); - if (activity != null) { - activity.onAnimationFinished(); - } - } - /** * Sets the current picture-in-picture aspect ratio. */ diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 0a68408d49a5..8ef01e3f4776 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -946,7 +946,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // This is the second time we failed -- finish activity and give up. Slog.e(TAG, "Second failure launching " + r.intent.getComponent().flattenToShortString() + ", giving up", e); - proc.appDied(); + proc.appDied("2nd-crash"); r.finishIfPossible("2nd-crash", false /* oomAdj */); return false; } diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 369dde665068..3927d5fa2604 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -352,6 +352,7 @@ public class AppTransitionController { * Apply animation to the set of window containers. * * @param wcs The list of {@link WindowContainer}s to which an app transition animation applies. + * @param apps The list of {@link ActivityRecord}s being transitioning. * @param transit The current transition type. * @param visible {@code true} if the apps becomes visible, {@code false} if the apps becomes * invisible. @@ -359,12 +360,28 @@ public class AppTransitionController { * @param voiceInteraction {@code true} if one of the apps in this transition belongs to a voice * interaction session driving task. */ - private void applyAnimations(ArraySet<WindowContainer> wcs, @TransitionType int transit, - boolean visible, LayoutParams animLp, boolean voiceInteraction) { - final int appsCount = wcs.size(); - for (int i = 0; i < appsCount; i++) { + private void applyAnimations(ArraySet<WindowContainer> wcs, ArraySet<ActivityRecord> apps, + @TransitionType int transit, boolean visible, LayoutParams animLp, + boolean voiceInteraction) { + final int wcsCount = wcs.size(); + for (int i = 0; i < wcsCount; i++) { final WindowContainer wc = wcs.valueAt(i); - wc.applyAnimation(animLp, transit, visible, voiceInteraction); + // If app transition animation target is promoted to higher level, SurfaceAnimator + // triggers WC#onAnimationFinished only on the promoted target. So we need to take care + // of triggering AR#onAnimationFinished on each ActivityRecord which is a part of the + // app transition. + final ArrayList<ActivityRecord> transitioningDecendants = new ArrayList<>(); + for (int j = 0; j < apps.size(); ++j) { + final ActivityRecord app = apps.valueAt(j); + if (app.isDescendantOf(wc)) { + transitioningDecendants.add(app); + } + } + wc.applyAnimation(animLp, transit, visible, voiceInteraction, () -> { + for (int j = 0; j < transitioningDecendants.size(); ++j) { + transitioningDecendants.get(j).onAnimationFinished(); + } + }); } } @@ -495,8 +512,10 @@ public class AppTransitionController { openingApps, closingApps, true /* visible */); final ArraySet<WindowContainer> closingWcs = getAnimationTargets( openingApps, closingApps, false /* visible */); - applyAnimations(openingWcs, transit, true /* visible */, animLp, voiceInteraction); - applyAnimations(closingWcs, transit, false /* visible */, animLp, voiceInteraction); + applyAnimations(openingWcs, openingApps, transit, true /* visible */, animLp, + voiceInteraction); + applyAnimations(closingWcs, closingApps, transit, false /* visible */, animLp, + voiceInteraction); final AccessibilityController accessibilityController = mDisplayContent.mWmService.mAccessibilityController; @@ -575,7 +594,8 @@ public class AppTransitionController { ActivityRecord activity = apps.valueAt(i); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", activity); activity.cancelAnimationOnly(); - activity.applyAnimation(null, transit, true, false); + activity.applyAnimation(null, transit, true, false, + null /* animationFinishedCallback */); activity.updateReportedVisibilityLocked(); mService.openSurfaceTransaction(); try { diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java index af859d3beab2..16aff9c10c7d 100644 --- a/services/core/java/com/android/server/wm/Dimmer.java +++ b/services/core/java/com/android/server/wm/Dimmer.java @@ -21,6 +21,7 @@ import static com.android.server.wm.AlphaAnimationSpecProto.FROM; import static com.android.server.wm.AlphaAnimationSpecProto.TO; import static com.android.server.wm.AnimationSpecProto.ALPHA; +import android.annotation.Nullable; import android.graphics.Rect; import android.util.Log; import android.util.proto.ProtoOutputStream; @@ -156,7 +157,8 @@ class Dimmer { @VisibleForTesting interface SurfaceAnimatorStarter { void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t, - AnimationAdapter anim, boolean hidden); + AnimationAdapter anim, boolean hidden, + @Nullable Runnable animationFinishedCallback); } Dimmer(WindowContainer host) { @@ -342,7 +344,8 @@ class Dimmer { SurfaceControl.Transaction t, float startAlpha, float endAlpha) { mSurfaceAnimatorStarter.startAnimation(animator, t, new LocalAnimationAdapter( new AlphaAnimationSpec(startAlpha, endAlpha, getDimDuration(container)), - mHost.mWmService.mSurfaceAnimationRunner), false /* hidden */); + mHost.mWmService.mSurfaceAnimationRunner), false /* hidden */, + null /* animationFinishedCallback */); } private long getDimDuration(WindowContainer container) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 908c4f1ddd66..f93309a84466 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -65,7 +65,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; @@ -75,7 +74,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; -import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; @@ -875,7 +874,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (w.mHasSurface && isDisplayed) { final int type = w.mAttrs.type; if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR - || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { + || mWmService.mPolicy.isKeyguardShowing()) { mTmpApplySurfaceChangesTransactionState.syswin = true; } if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0 @@ -3557,7 +3556,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final SparseBooleanArray drawnWindowTypes = new SparseBooleanArray(); // Presuppose keyguard is drawn because if its window isn't attached, we don't know if it // wants to be shown or hidden, then it should not delay enabling the screen. - drawnWindowTypes.put(TYPE_STATUS_BAR, true); + drawnWindowTypes.put(TYPE_NOTIFICATION_SHADE, true); final WindowState visibleNotDrawnWindow = getWindow(w -> { if (w.mViewVisibility == View.VISIBLE && !w.mObscured && !w.isDrawnLw()) { @@ -3568,8 +3567,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (type == TYPE_BOOT_PROGRESS || type == TYPE_BASE_APPLICATION || type == TYPE_WALLPAPER) { drawnWindowTypes.put(type, true); - } else if (type == TYPE_STATUS_BAR) { - drawnWindowTypes.put(TYPE_STATUS_BAR, mWmService.mPolicy.isKeyguardDrawnLw()); + } else if (type == TYPE_NOTIFICATION_SHADE) { + drawnWindowTypes.put(TYPE_NOTIFICATION_SHADE, + mWmService.mPolicy.isKeyguardDrawnLw()); } } return false; @@ -3591,7 +3591,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final boolean haveBootMsg = drawnWindowTypes.get(TYPE_BOOT_PROGRESS); final boolean haveApp = drawnWindowTypes.get(TYPE_BASE_APPLICATION); final boolean haveWallpaper = drawnWindowTypes.get(TYPE_WALLPAPER); - final boolean haveKeyguard = drawnWindowTypes.get(TYPE_STATUS_BAR); + final boolean haveKeyguard = drawnWindowTypes.get(TYPE_NOTIFICATION_SHADE); ProtoLog.i(WM_DEBUG_SCREEN_ON, "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b " @@ -5445,7 +5445,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY; final boolean stickyHideNav = (sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags; - return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_STATUS_BAR + return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_NOTIFICATION_SHADE && win.getActivityType() != ACTIVITY_TYPE_HOME; } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 9c62e9970b48..2c325e56cebe 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -58,11 +58,11 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; @@ -77,6 +77,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; @@ -289,6 +290,7 @@ public class DisplayPolicy { private final ArraySet<WindowState> mScreenDecorWindows = new ArraySet<>(); private WindowState mStatusBar = null; + private WindowState mNotificationShade = null; private final int[] mStatusBarHeightForRotation = new int[4]; private WindowState mNavigationBar = null; @NavigationBarPosition @@ -368,8 +370,6 @@ public class DisplayPolicy { private WindowState mTopDockedOpaqueOrDimmingWindowState; private boolean mTopIsFullscreen; private boolean mForceStatusBar; - private boolean mForceStatusBarFromKeyguard; - private boolean mForceStatusBarTransparent; private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED; private boolean mForcingShowNavBar; private int mForcingShowNavBarLayer; @@ -851,15 +851,13 @@ public class DisplayPolicy { // letterboxed. Hence always let them extend under the cutout. attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; break; - case TYPE_STATUS_BAR: - + case TYPE_NOTIFICATION_SHADE: // If the Keyguard is in a hidden state (occluded by another window), we force to // remove the wallpaper and keyguard flag so that any change in-flight after setting // the keyguard as occluded wouldn't set these flags again. // See {@link #processKeyguardSetHiddenResultLw}. if (mService.mPolicy.isKeyguardOccluded()) { attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; - attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; } break; @@ -891,11 +889,6 @@ public class DisplayPolicy { attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; break; } - - if (attrs.type != TYPE_STATUS_BAR) { - // The status bar is the only window allowed to exhibit keyguard behavior. - attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; - } } /** @@ -914,6 +907,7 @@ public class DisplayPolicy { * Currently enforces that two window types are singletons per display: * <ul> * <li>{@link WindowManager.LayoutParams#TYPE_STATUS_BAR}</li> + * <li>{@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}</li> * <li>{@link WindowManager.LayoutParams#TYPE_NAVIGATION_BAR}</li> * </ul> * @@ -940,6 +934,16 @@ public class DisplayPolicy { } } break; + case TYPE_NOTIFICATION_SHADE: + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.STATUS_BAR_SERVICE, + "DisplayPolicy"); + if (mNotificationShade != null) { + if (mNotificationShade.isAlive()) { + return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; + } + } + break; case TYPE_NAVIGATION_BAR: mContext.enforceCallingOrSelfPermission( android.Manifest.permission.STATUS_BAR_SERVICE, @@ -974,12 +978,15 @@ public class DisplayPolicy { } switch (attrs.type) { - case TYPE_STATUS_BAR: - mStatusBar = win; - mStatusBarController.setWindow(win); + case TYPE_NOTIFICATION_SHADE: + mNotificationShade = win; if (mDisplayContent.isDefaultDisplay) { mService.mPolicy.setKeyguardCandidateLw(win); } + break; + case TYPE_STATUS_BAR: + mStatusBar = win; + mStatusBarController.setWindow(win); final TriConsumer<DisplayFrames, WindowState, Rect> frameProvider = (displayFrames, windowState, rect) -> { rect.top = 0; @@ -1036,14 +1043,16 @@ public class DisplayPolicy { if (mStatusBar == win) { mStatusBar = null; mStatusBarController.setWindow(null); - if (mDisplayContent.isDefaultDisplay) { - mService.mPolicy.setKeyguardCandidateLw(null); - } mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, null, null); } else if (mNavigationBar == win) { mNavigationBar = null; mNavigationBarController.setWindow(null); mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, null, null); + } else if (mNotificationShade == win) { + mNotificationShade = null; + if (mDisplayContent.isDefaultDisplay) { + mService.mPolicy.setKeyguardCandidateLw(null); + } } if (mLastFocusedWindow == win) { mLastFocusedWindow = null; @@ -1060,6 +1069,10 @@ public class DisplayPolicy { return mStatusBar; } + WindowState getNotificationShade() { + return mNotificationShade; + } + WindowState getNavigationBar() { return mNavigationBar; } @@ -1082,12 +1095,6 @@ public class DisplayPolicy { if (DEBUG_ANIM) Slog.i(TAG, "selectAnimation in " + win + ": transit=" + transit); if (win == mStatusBar) { - final boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; - final boolean expanded = win.getAttrs().height == MATCH_PARENT - && win.getAttrs().width == MATCH_PARENT; - if (isKeyguard || expanded) { - return ANIMATION_NONE; - } if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) { return R.anim.dock_top_exit; @@ -1425,10 +1432,10 @@ public class DisplayPolicy { || (behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0; boolean navAllowedHidden = immersive || immersiveSticky; navTranslucent &= !immersiveSticky; // transient trumps translucent - boolean isKeyguardShowing = isStatusBarKeyguard() - && !mService.mPolicy.isKeyguardOccluded(); - boolean statusBarForcesShowingNavigation = !isKeyguardShowing && mStatusBar != null - && (mStatusBar.getAttrs().privateFlags + boolean isKeyguardShowing = isKeyguardShowing() && !isKeyguardOccluded(); + boolean notificationShadeForcesShowingNavigation = + !isKeyguardShowing && mNotificationShade != null + && (mNotificationShade.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0; // When the navigation bar isn't visible, we put up a fake input window to catch all @@ -1455,7 +1462,7 @@ public class DisplayPolicy { navVisible |= !canHideNavigationBar(); boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, navVisible, - navTranslucent, navAllowedHidden, statusBarForcesShowingNavigation); + navTranslucent, navAllowedHidden, notificationShadeForcesShowingNavigation); if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock); updateSysUiVisibility |= layoutStatusBar(displayFrames, sysui, isKeyguardShowing); if (updateSysUiVisibility) { @@ -2104,7 +2111,7 @@ public class DisplayPolicy { df.set(displayFrames.mUnrestricted); pf.set(displayFrames.mUnrestricted); } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 - && (type == TYPE_STATUS_BAR + && (type == TYPE_NOTIFICATION_SHADE || type == TYPE_TOAST || type == TYPE_DOCK_DIVIDER || type == TYPE_VOICE_INTERACTION_STARTING @@ -2210,7 +2217,8 @@ public class DisplayPolicy { // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in // the cutout safe zone. - if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) { + if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT + || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER) { final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect; displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe); if (layoutInScreen && layoutInsetDecor && !requestedFullscreen @@ -2355,8 +2363,6 @@ public class DisplayPolicy { mTopDockedOpaqueWindowState = null; mTopDockedOpaqueOrDimmingWindowState = null; mForceStatusBar = false; - mForceStatusBarFromKeyguard = false; - mForceStatusBarTransparent = false; mForcingShowNavBar = false; mForcingShowNavBarLayer = -1; @@ -2384,14 +2390,6 @@ public class DisplayPolicy { mForcingShowNavBar = true; mForcingShowNavBarLayer = win.getSurfaceLayer(); } - if (attrs.type == TYPE_STATUS_BAR) { - if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { - mForceStatusBarFromKeyguard = true; - } - if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { - mForceStatusBarTransparent = true; - } - } boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type < FIRST_SYSTEM_WINDOW; @@ -2513,32 +2511,25 @@ public class DisplayPolicy { if (mStatusBar != null) { if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar - + " forcefkg=" + mForceStatusBarFromKeyguard + " top=" + mTopFullscreenOpaqueWindowState); - boolean shouldBeTransparent = mForceStatusBarTransparent - && !mForceStatusBar - && !mForceStatusBarFromKeyguard; - if (!shouldBeTransparent) { - mStatusBarController.setShowTransparent(false /* transparent */); - } else if (!mStatusBar.isVisibleLw()) { - mStatusBarController.setShowTransparent(true /* transparent */); - } - - boolean statusBarForcesShowingNavigation = - (mStatusBar.getAttrs().privateFlags + final boolean forceShowStatusBar = (mStatusBar.getAttrs().privateFlags + & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0; + final boolean notificationShadeForcesShowingNavigation = + mNotificationShade != null + && (mNotificationShade.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0; + boolean topAppHidesStatusBar = topAppHidesStatusBar(); - if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent - || statusBarForcesShowingNavigation) { + if (mForceStatusBar || forceShowStatusBar) { if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); if (mStatusBarController.setBarShowingLw(true)) { changes |= FINISH_LAYOUT_REDO_LAYOUT; } // Maintain fullscreen layout until incoming animation is complete. topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); - // Transient status bar is not allowed if status bar is on lockscreen or status bar - // is expecting the navigation keys from the user. - if ((mForceStatusBarFromKeyguard || statusBarForcesShowingNavigation) + // Transient status bar is not allowed if notification shade is expecting the + // navigation keys from the user. + if (notificationShadeForcesShowingNavigation && mStatusBarController.isTransientShowing()) { mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, mLastSystemUiFlags, mLastSystemUiFlags); @@ -3102,11 +3093,9 @@ public class DisplayPolicy { } } - private boolean isStatusBarKeyguard() { - return mStatusBar != null - && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; + boolean isKeyguardShowing() { + return mService.mPolicy.isKeyguardShowing(); } - private boolean isKeyguardOccluded() { // TODO (b/113840485): Handle per display keyguard. return mService.mPolicy.isKeyguardOccluded(); @@ -3139,7 +3128,7 @@ public class DisplayPolicy { // keys, we let it keep controlling the visibility. final boolean lastFocusCanReceiveKeys = (mLastFocusedWindow != null && mLastFocusedWindow.canReceiveKeys()); - winCandidate = isStatusBarKeyguard() ? mStatusBar + winCandidate = isKeyguardShowing() ? mNotificationShade : lastFocusCanReceiveKeys ? mLastFocusedWindow : mTopFullscreenOpaqueWindowState; if (winCandidate == null) { @@ -3147,7 +3136,8 @@ public class DisplayPolicy { } } final WindowState win = winCandidate; - if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && isKeyguardOccluded()) { + if (win.getAttrs().type == TYPE_NOTIFICATION_SHADE && isKeyguardShowing() + && isKeyguardOccluded()) { // We are updating at a point where the keyguard has gotten // focus, but we were last in a state where the top window is // hiding it. This is probably because the keyguard as been @@ -3281,8 +3271,8 @@ public class DisplayPolicy { private int updateLightStatusBarAppearanceLw(@Appearance int appearance, WindowState opaque, WindowState opaqueOrDimming) { - final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded(); - final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming; + final boolean onKeyguard = isKeyguardShowing() && !isKeyguardOccluded(); + final WindowState statusColorWin = onKeyguard ? mNotificationShade : opaqueOrDimming; if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) { // If the top fullscreen-or-dimming window is also the top fullscreen, respect // its light flag. @@ -3370,11 +3360,11 @@ public class DisplayPolicy { // visibility changes. mForceShowSystemBars = dockedStackVisible || win.inFreeformWindowingMode() || resizing || mForceShowSystemBarsFromExternal; - final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; + final boolean forceOpaqueStatusBar = mForceShowSystemBars && !isKeyguardShowing(); // apply translucent bar vis flags - WindowState fullscreenTransWin = isStatusBarKeyguard() && !isKeyguardOccluded() - ? mStatusBar + WindowState fullscreenTransWin = isKeyguardShowing() && !isKeyguardOccluded() + ? mNotificationShade : mTopFullscreenOpaqueWindowState; vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); @@ -3394,8 +3384,8 @@ public class DisplayPolicy { // prevent status bar interaction from clearing certain flags int type = win.getAttrs().type; - boolean statusBarHasFocus = type == TYPE_STATUS_BAR; - if (statusBarHasFocus && !isStatusBarKeyguard()) { + boolean notificationShadeHasFocus = type == TYPE_NOTIFICATION_SHADE; + if (notificationShadeHasFocus && !isKeyguardShowing()) { int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE @@ -3430,7 +3420,7 @@ public class DisplayPolicy { (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; final boolean transientStatusBarAllowed = mStatusBar != null - && (statusBarHasFocus || (!mForceShowSystemBars + && (notificationShadeHasFocus || (!mForceShowSystemBars && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); final boolean transientNavBarAllowed = mNavigationBar != null @@ -3441,7 +3431,7 @@ public class DisplayPolicy { && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; final DisplayPolicy defaultDisplayPolicy = mService.getDefaultDisplayContentLocked().getDisplayPolicy(); - if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() + if (pendingPanic && hideNavBarSysui && !isKeyguardShowing() // TODO (b/111955725): Show keyguard presentation on all external displays && defaultDisplayPolicy.isKeyguardDrawComplete()) { // The user performed the panic gesture recently, we're about to hide the bars, @@ -3703,8 +3693,11 @@ public class DisplayPolicy { pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); if (mStatusBar != null) { pw.print(prefix); pw.print("mStatusBar="); pw.print(mStatusBar); - pw.print(" isStatusBarKeyguard="); pw.println(isStatusBarKeyguard()); } + if (mNotificationShade != null) { + pw.print(prefix); pw.print("mExpandedPanel="); pw.print(mNotificationShade); + } + pw.print(" isKeyguardShowing="); pw.println(isKeyguardShowing()); if (mNavigationBar != null) { pw.print(prefix); pw.print("mNavigationBar="); pw.println(mNavigationBar); pw.print(prefix); pw.print("mNavBarOpacityMode="); pw.println(mNavBarOpacityMode); @@ -3733,7 +3726,6 @@ public class DisplayPolicy { } pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen); pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); - pw.print(" mForceStatusBarFromKeyguard="); pw.println(mForceStatusBarFromKeyguard); pw.print(prefix); pw.print("mForceShowSystemBarsFromExternal="); pw.print(mForceShowSystemBarsFromExternal); pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn); diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 091f66c0b19a..4c5914bfd8c2 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -23,7 +23,6 @@ import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; @@ -527,7 +526,7 @@ final class InputMonitor { mDisableWallpaperTouchEvents = true; } final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w) - && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0 + && !mService.mPolicy.isKeyguardShowing() && !mDisableWallpaperTouchEvents; // If there's a drag in progress and 'child' is a potential drop target, diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index a0089639bce6..fa764e3dfc18 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -22,8 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; import android.annotation.Nullable; @@ -188,7 +187,7 @@ class InsetsPolicy { if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) { return mTransientControlTarget; } - if (areSystemBarsForciblyVisible() || isStatusBarForciblyVisible()) { + if (areSystemBarsForciblyVisible() || isKeyguardOrStatusBarForciblyVisible()) { return null; } return focusedWin; @@ -204,29 +203,27 @@ class InsetsPolicy { return focusedWin; } - private boolean isStatusBarForciblyVisible() { - final WindowState statusBar = mPolicy.getStatusBar(); - if (statusBar == null) { - return false; - } - final int privateFlags = statusBar.mAttrs.privateFlags; - - // TODO(b/118118435): Pretend to the app that it's still able to control it? - if ((privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { + private boolean isKeyguardOrStatusBarForciblyVisible() { + if (mPolicy.isKeyguardShowing()) { return true; } - if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { - return true; + final WindowState statusBar = mPolicy.getStatusBar(); + if (statusBar != null) { + // TODO(b/118118435): Pretend to the app that it's still able to control it? + if ((statusBar.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0) { + return true; + } } return false; } private boolean isNavBarForciblyVisible() { - final WindowState statusBar = mPolicy.getStatusBar(); - if (statusBar == null) { + final WindowState notificationShade = mPolicy.getNotificationShade(); + if (notificationShade == null) { return false; } - if ((statusBar.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0) { + if ((notificationShade.mAttrs.privateFlags + & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0) { return true; } return false; diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 2f726e9999eb..8b1005e2e847 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -35,7 +35,6 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE; import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; @@ -1147,7 +1146,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // While a dream or keyguard is showing, obscure ordinary application content on // secondary displays (by forcibly enabling mirroring unless there is other content // we want to show) but still allow opaque keyguard dialogs to be shown. - if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { + if (type == TYPE_DREAM || mWmService.mPolicy.isKeyguardShowing()) { mObscureApplicationContentOnSecondaryDisplays = true; } displayHasContent = true; diff --git a/services/core/java/com/android/server/wm/StatusBarController.java b/services/core/java/com/android/server/wm/StatusBarController.java index f4260d32a77d..cac992a67541 100644 --- a/services/core/java/com/android/server/wm/StatusBarController.java +++ b/services/core/java/com/android/server/wm/StatusBarController.java @@ -17,7 +17,6 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; -import static android.view.WindowManager.LayoutParams.MATCH_PARENT; import static com.android.server.wm.WindowManagerInternal.AppTransitionListener; @@ -102,11 +101,6 @@ public class StatusBarController extends BarController { } } - @Override - protected boolean skipAnimation() { - return mWin.getAttrs().height == MATCH_PARENT; - } - AppTransitionListener getAppTransitionListener() { return mAppTransitionListener; } diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index 5286a6e32958..cb1676f3a7b1 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -55,7 +55,9 @@ class SurfaceAnimator { private final OnAnimationFinishedCallback mInnerAnimationFinishedCallback; @VisibleForTesting @Nullable - final Runnable mAnimationFinishedCallback; + final Runnable mStaticAnimationFinishedCallback; + @Nullable + private Runnable mAnimationFinishedCallback; private boolean mAnimationStartDelayed; /** @@ -66,7 +68,7 @@ class SurfaceAnimator { WindowManagerService service) { mAnimatable = animatable; mService = service; - mAnimationFinishedCallback = animationFinishedCallback; + mStaticAnimationFinishedCallback = animationFinishedCallback; mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback); } @@ -89,10 +91,14 @@ class SurfaceAnimator { if (anim != mAnimation) { return; } + final Runnable animationFinishCallback = mAnimationFinishedCallback; reset(mAnimatable.getPendingTransaction(), true /* destroyLeash */); if (animationFinishedCallback != null) { animationFinishedCallback.run(); } + if (animationFinishCallback != null) { + animationFinishCallback.run(); + } }; if (!mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)) { resetAndInvokeFinish.run(); @@ -111,10 +117,13 @@ class SurfaceAnimator { * @param hidden Whether the container holding the child surfaces is currently visible or not. * This is important as it will start with the leash hidden or visible before * handing it to the component that is responsible to run the animation. + * @param animationFinishedCallback The callback being triggered when the animation finishes. */ - void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) { + void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, + @Nullable Runnable animationFinishedCallback) { cancelAnimation(t, true /* restarting */, true /* forwardCancel */); mAnimation = anim; + mAnimationFinishedCallback = animationFinishedCallback; final SurfaceControl surface = mAnimatable.getSurfaceControl(); if (surface == null) { Slog.w(TAG, "Unable to start animation, surface is null or no children."); @@ -131,6 +140,10 @@ class SurfaceAnimator { mAnimation.startAnimation(mLeash, t, mInnerAnimationFinishedCallback); } + void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) { + startAnimation(t, anim, hidden, null /* animationFinishedCallback */); + } + /** * Begins with delaying all animations to start. Any subsequent call to {@link #startAnimation} * will not start the animation until {@link #endDelayingAnimationStart} is called. When an @@ -232,6 +245,7 @@ class SurfaceAnimator { cancelAnimation(t, true /* restarting */, true /* forwardCancel */); mLeash = from.mLeash; mAnimation = from.mAnimation; + mAnimationFinishedCallback = from.mAnimationFinishedCallback; // Cancel source animation, but don't let animation runner cancel the animation. from.cancelAnimation(t, false /* restarting */, false /* forwardCancel */); @@ -258,13 +272,19 @@ class SurfaceAnimator { if (DEBUG_ANIM) Slog.i(TAG, "Cancelling animation restarting=" + restarting); final SurfaceControl leash = mLeash; final AnimationAdapter animation = mAnimation; + final Runnable animationFinishedCallback = mAnimationFinishedCallback; reset(t, false); if (animation != null) { if (!mAnimationStartDelayed && forwardCancel) { animation.onAnimationCancelled(leash); } - if (!restarting && mAnimationFinishedCallback != null) { - mAnimationFinishedCallback.run(); + if (!restarting) { + if (mStaticAnimationFinishedCallback != null) { + mStaticAnimationFinishedCallback.run(); + } + if (animationFinishedCallback != null) { + animationFinishedCallback.run(); + } } } @@ -304,6 +324,7 @@ class SurfaceAnimator { } mLeash = null; mAnimation = null; + mAnimationFinishedCallback = null; if (reparent) { // Make sure to inform the animatable after the surface was reparented (or reparent diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 5cb7091bbed0..b7201b4dbde5 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -121,7 +121,6 @@ import android.graphics.Point; import android.graphics.Rect; import android.os.Debug; import android.os.IBinder; -import android.os.Parcel; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; @@ -2616,18 +2615,6 @@ class Task extends WindowContainer<WindowContainer> { } @Override - protected void onAnimationFinished() { - super.onAnimationFinished(); - // TODO(b/142617871): we may need to add animation type parameter on onAnimationFinished to - // identify if the callback is for launch animation finish and then calling - // activity#onAnimationFinished. - final ActivityRecord activity = getTopMostActivity(); - if (activity != null) { - activity.onAnimationFinished(); - } - } - - @Override SurfaceControl.Builder makeSurface() { return super.makeSurface().setMetadata(METADATA_TASK_ID, mTaskId); } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 3b2d51985a39..a43f595e4a9f 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -562,6 +562,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return false; } + /** @return true if this window container is a descendant of the input container. */ + boolean isDescendantOf(WindowContainer ancestor) { + final WindowContainer parent = getParent(); + if (parent == ancestor) return true; + return (parent != null) && parent.isDescendantOf(ancestor); + } + /** * Move a child from it's current place in siblings list to the specified position, * with an option to move all its parents to top. @@ -1832,13 +1839,19 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * @param anim The animation to run. * @param hidden Whether our container is currently hidden. TODO This should use isVisible at * some point but the meaning is too weird to work for all containers. + * @param animationFinishedCallback The callback being triggered when the animation finishes. */ - void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) { + void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, + @Nullable Runnable animationFinishedCallback) { if (DEBUG_ANIM) Slog.v(TAG, "Starting animation on " + this + ": " + anim); // TODO: This should use isVisible() but because isVisible has a really weird meaning at // the moment this doesn't work for all animatable window containers. - mSurfaceAnimator.startAnimation(t, anim, hidden); + mSurfaceAnimator.startAnimation(t, anim, hidden, animationFinishedCallback); + } + + void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) { + startAnimation(t, anim, hidden, null /* animationFinishedCallback */); } void transferAnimation(WindowContainer from) { @@ -1891,7 +1904,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * @see #getAnimationAdapter */ boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, - boolean isVoiceInteraction) { + boolean isVoiceInteraction, @Nullable Runnable animationFinishedCallback) { if (mWmService.mDisableTransitionAnimation) { ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: transition animation is disabled or skipped. " @@ -1911,7 +1924,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< AnimationAdapter adapter = adapters.first; AnimationAdapter thumbnailAdapter = adapters.second; if (adapter != null) { - startAnimation(getPendingTransaction(), adapter, !isVisible()); + startAnimation(getPendingTransaction(), adapter, !isVisible(), + animationFinishedCallback); if (adapter.getShowWallpaper()) { getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; } diff --git a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java index 8e070f19cc30..8948f6fc2ab1 100644 --- a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java +++ b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java @@ -85,7 +85,8 @@ class WindowContainerThumbnail implements Animatable { // We can't use a delegating constructor since we need to // reference this::onAnimationFinished mSurfaceAnimator = - new SurfaceAnimator(this, this::onAnimationFinished, container.mWmService); + new SurfaceAnimator(this, null /* animationFinishedCallback */, + container.mWmService); } mWidth = thumbnailHeader.getWidth(); mHeight = thumbnailHeader.getHeight(); @@ -139,9 +140,6 @@ class WindowContainerThumbnail implements Animatable { mSurfaceAnimator.startAnimation(t, anim, hidden); } - private void onAnimationFinished() { - } - void setShowing(Transaction pendingTransaction, boolean show) { // TODO: Not needed anymore once thumbnail is attached to the app. if (show) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e3b593e90fa5..77d755d6f36d 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -63,6 +63,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; @@ -1283,6 +1284,7 @@ public class WindowManagerService extends IWindowManager.Stub static boolean excludeWindowTypeFromTapOutTask(int windowType) { switch (windowType) { case TYPE_STATUS_BAR: + case TYPE_NOTIFICATION_SHADE: case TYPE_NAVIGATION_BAR: case TYPE_INPUT_METHOD_DIALOG: return true; diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index ceb38f7d9789..c755e60ec977 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -971,11 +971,11 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio mAtm.mH.sendMessageAtFrontOfQueue(m); } - public void appDied() { + void appDied(String reason) { if (mListener == null) return; // Posting on handler so WM lock isn't held when we call into AM. final Message m = PooledLambda.obtainMessage( - WindowProcessListener::appDied, mListener); + WindowProcessListener::appDied, mListener, reason); mAtm.mH.sendMessage(m); } @@ -1136,6 +1136,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio } public void appEarlyNotResponding(String annotation, Runnable killAppCallback) { + Runnable targetRunnable = null; synchronized (mAtm.mGlobalLock) { if (mAtm.mController == null) { return; @@ -1145,13 +1146,16 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio // 0 == continue, -1 = kill process immediately int res = mAtm.mController.appEarlyNotResponding(mName, mPid, annotation); if (res < 0 && mPid != MY_PID) { - killAppCallback.run(); + targetRunnable = killAppCallback; } } catch (RemoteException e) { mAtm.mController = null; Watchdog.getInstance().setActivityController(null); } } + if (targetRunnable != null) { + targetRunnable.run(); + } } public boolean appNotResponding(String info, Runnable killAppCallback, @@ -1179,6 +1183,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio } } if (targetRunnable != null) { + // Execute runnable outside WM lock since the runnable will hold AM lock targetRunnable.run(); return true; } diff --git a/services/core/java/com/android/server/wm/WindowProcessListener.java b/services/core/java/com/android/server/wm/WindowProcessListener.java index 870cbb00dff8..9505191d5eb3 100644 --- a/services/core/java/com/android/server/wm/WindowProcessListener.java +++ b/services/core/java/com/android/server/wm/WindowProcessListener.java @@ -59,7 +59,7 @@ public interface WindowProcessListener { long versionCode); /** App died :(...oh well */ - void appDied(); + void appDied(String reason); void dumpDebug(ProtoOutputStream proto, long fieldId); /** diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index a429741607e4..2965764e8961 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -73,6 +73,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_PHONE; import static android.view.WindowManager.LayoutParams.TYPE_POINTER; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; @@ -3210,6 +3211,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP case TYPE_PRIORITY_PHONE: case TYPE_SEARCH_BAR: case TYPE_STATUS_BAR: + case TYPE_NOTIFICATION_SHADE: case TYPE_STATUS_BAR_PANEL: case TYPE_STATUS_BAR_SUB_PANEL: case TYPE_SYSTEM_DIALOG: @@ -5011,7 +5013,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } private void startAnimation(Transaction t, AnimationAdapter adapter) { - startAnimation(t, adapter, mWinAnimator.mLastHidden); + startAnimation(t, adapter, mWinAnimator.mLastHidden, null /* animationFinishedCallback */); } @Override diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 486616df6f11..6189fbdbfb78 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -272,7 +272,8 @@ class WindowStateAnimator { mWin.checkPolicyVisibilityChange(); final DisplayContent displayContent = mWin.getDisplayContent(); - if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.isVisibleByPolicy()) { + if ((mAttrType == LayoutParams.TYPE_STATUS_BAR + || mAttrType == LayoutParams.TYPE_NOTIFICATION_SHADE) && mWin.isVisibleByPolicy()) { // Upon completion of a not-visible to visible status bar animation a relayout is // required. displayContent.setLayoutNeeded(); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java new file mode 100644 index 000000000000..8d2a152dba83 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java @@ -0,0 +1,954 @@ +/* + * 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.server.am; + +import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; +import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; +import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; +import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY; +import static android.app.ActivityManager.PROCESS_STATE_RECEIVER; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static com.android.server.am.ActivityManagerService.Injector; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.app.ApplicationExitInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManagerInternal; +import android.os.Debug; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Process; +import android.os.UserHandle; +import android.platform.test.annotations.Presubmit; +import android.system.OsConstants; +import android.text.TextUtils; +import android.util.Pair; + +import com.android.server.ServiceThread; +import com.android.server.appop.AppOpsService; +import com.android.server.wm.ActivityTaskManagerService; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; + +/** + * Test class for {@link android.app.ApplicationExitInfo}. + * + * Build/Install/Run: + * atest ApplicationExitInfoTest + */ +@Presubmit +public class ApplicationExitInfoTest { + private static final String TAG = ApplicationExitInfoTest.class.getSimpleName(); + + @Rule public ServiceThreadRule mServiceThreadRule = new ServiceThreadRule(); + @Mock private AppOpsService mAppOpsService; + @Mock private PackageManagerInternal mPackageManagerInt; + + private Context mContext = getInstrumentation().getTargetContext(); + private TestInjector mInjector; + private ActivityManagerService mAms; + private ProcessList mProcessList; + private AppExitInfoTracker mAppExitInfoTracker; + private Handler mHandler; + private HandlerThread mHandlerThread; + + @BeforeClass + public static void setUpOnce() { + System.setProperty("dexmaker.share_classloader", "true"); + } + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mHandlerThread = new HandlerThread(TAG); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); + mProcessList = spy(new ProcessList()); + mAppExitInfoTracker = spy(new AppExitInfoTracker()); + setFieldValue(AppExitInfoTracker.class, mAppExitInfoTracker, "mIsolatedUidRecords", + spy(mAppExitInfoTracker.new IsolatedUidRecords())); + setFieldValue(AppExitInfoTracker.class, mAppExitInfoTracker, "mAppExitInfoSourceZygote", + spy(mAppExitInfoTracker.new AppExitInfoExternalSource("zygote", null))); + setFieldValue(AppExitInfoTracker.class, mAppExitInfoTracker, "mAppExitInfoSourceLmkd", + spy(mAppExitInfoTracker.new AppExitInfoExternalSource("lmkd", + ApplicationExitInfo.REASON_LOW_MEMORY))); + setFieldValue(ProcessList.class, mProcessList, "mAppExitInfoTracker", mAppExitInfoTracker); + mInjector = new TestInjector(mContext); + mAms = new ActivityManagerService(mInjector, mServiceThreadRule.getThread()); + mAms.mActivityTaskManager = new ActivityTaskManagerService(mContext); + mAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper()); + mAms.mAtmInternal = spy(mAms.mActivityTaskManager.getAtmInternal()); + mAms.mPackageManagerInt = mPackageManagerInt; + } + + @After + public void tearDown() { + mHandlerThread.quit(); + } + + private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + Field mfield = Field.class.getDeclaredField("accessFlags"); + mfield.setAccessible(true); + mfield.setInt(field, mfield.getInt(field) & ~(Modifier.FINAL | Modifier.PRIVATE)); + field.set(obj, val); + } catch (NoSuchFieldException | IllegalAccessException e) { + } + } + + private void updateExitInfo(ProcessRecord app) { + ApplicationExitInfo raw = mAppExitInfoTracker.obtainRawRecordLocked(app); + mAppExitInfoTracker.handleNoteProcessDiedLocked(raw); + mAppExitInfoTracker.recycleRawRecordLocked(raw); + } + + private void noteAppKill(ProcessRecord app, int reason, int subReason, String msg) { + ApplicationExitInfo raw = mAppExitInfoTracker.obtainRawRecordLocked(app); + raw.setReason(reason); + raw.setSubReason(subReason); + raw.setDescription(msg); + mAppExitInfoTracker.handleNoteAppKillLocked(raw); + mAppExitInfoTracker.recycleRawRecordLocked(raw); + } + + @Test + public void testApplicationExitInfo() throws Exception { + mAppExitInfoTracker.clearProcessExitInfo(true); + mAppExitInfoTracker.mAppExitInfoLoaded = true; + + // Test application calls System.exit() + doNothing().when(mAppExitInfoTracker).schedulePersistProcessExitInfo(anyBoolean()); + + final int app1Uid = 10123; + final int app1Pid1 = 12345; + final int app1Pid2 = 12346; + final int app1DefiningUid = 23456; + final int app1ConnectiongGroup = 10; + final int app1UidUser2 = 1010123; + final int app1PidUser2 = 12347; + final int app1Pss1 = 34567; + final int app1Rss1 = 45678; + final int app1Pss2 = 34568; + final int app1Rss2 = 45679; + final int app1Pss3 = 34569; + final int app1Rss3 = 45680; + final String app1ProcessName = "com.android.test.stub1:process"; + final String app1PackageName = "com.android.test.stub1"; + + final long now1 = System.currentTimeMillis(); + ProcessRecord app = makeProcessRecord( + app1Pid1, // pid + app1Uid, // uid + app1Uid, // packageUid + null, // definingUid + 0, // connectionGroup + PROCESS_STATE_LAST_ACTIVITY, // procstate + app1Pss1, // pss + app1Rss1, // rss + app1ProcessName, // processName + app1PackageName); // packageName + + // Case 1: basic System.exit() test + int exitCode = 5; + doReturn(new Pair<Long, Object>(now1, Integer.valueOf(makeExitStatus(exitCode)))) + .when(mAppExitInfoTracker.mAppExitInfoSourceZygote) + .remove(anyInt(), anyInt()); + doReturn(null) + .when(mAppExitInfoTracker.mAppExitInfoSourceLmkd) + .remove(anyInt(), anyInt()); + updateExitInfo(app); + + ArrayList<ApplicationExitInfo> list = new ArrayList<ApplicationExitInfo>(); + mAppExitInfoTracker.getExitInfo(app1PackageName, app1Uid, app1Pid1, 0, list); + assertEquals(1, list.size()); + + ApplicationExitInfo info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now1, // timestamp + app1Pid1, // pid + app1Uid, // uid + app1Uid, // packageUid + null, // definingUid + app1ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_EXIT_SELF, // reason + null, // subReason + exitCode, // status + app1Pss1, // pss + app1Rss1, // rss + IMPORTANCE_CACHED, // importance + null); // description + + // Case 2: create another app1 process record with a different pid + sleep(1); + final long now2 = System.currentTimeMillis(); + app = makeProcessRecord( + app1Pid2, // pid + app1Uid, // uid + app1Uid, // packageUid + app1DefiningUid, // definingUid + app1ConnectiongGroup, // connectionGroup + PROCESS_STATE_RECEIVER, // procstate + app1Pss2, // pss + app1Rss2, // rss + app1ProcessName, // processName + app1PackageName); // packageName + exitCode = 6; + doReturn(new Pair<Long, Object>(now2, Integer.valueOf(makeExitStatus(exitCode)))) + .when(mAppExitInfoTracker.mAppExitInfoSourceZygote) + .remove(anyInt(), anyInt()); + updateExitInfo(app); + list.clear(); + + // Get all the records for app1Uid + mAppExitInfoTracker.getExitInfo(app1PackageName, app1Uid, 0, 0, list); + assertEquals(2, list.size()); + + info = list.get(0); + + // Verify the most recent one + verifyApplicationExitInfo( + info, // info + now2, // timestamp + app1Pid2, // pid + app1Uid, // uid + app1Uid, // packageUid + app1DefiningUid, // definingUid + app1ProcessName, // processName + app1ConnectiongGroup, // connectionGroup + ApplicationExitInfo.REASON_EXIT_SELF, // reason + null, // subReason + exitCode, // status + app1Pss2, // pss + app1Rss2, // rss + IMPORTANCE_SERVICE, // importance + null); // description + + // Case 3: Create an instance of app1 with different user, and died because of SIGKILL + sleep(1); + final long now3 = System.currentTimeMillis(); + int sigNum = OsConstants.SIGKILL; + app = makeProcessRecord( + app1PidUser2, // pid + app1UidUser2, // uid + app1UidUser2, // packageUid + null, // definingUid + 0, // connectionGroup + PROCESS_STATE_BOUND_FOREGROUND_SERVICE, // procstate + app1Pss3, // pss + app1Rss3, // rss + app1ProcessName, // processName + app1PackageName); // packageName + doReturn(new Pair<Long, Object>(now3, Integer.valueOf(makeSignalStatus(sigNum)))) + .when(mAppExitInfoTracker.mAppExitInfoSourceZygote) + .remove(anyInt(), anyInt()); + updateExitInfo(app); + list.clear(); + mAppExitInfoTracker.getExitInfo(app1PackageName, app1UidUser2, app1PidUser2, 0, list); + + assertEquals(1, list.size()); + + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now3, // timestamp + app1PidUser2, // pid + app1UidUser2, // uid + app1UidUser2, // packageUid + null, // definingUid + app1ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_SIGNALED, // reason + null, // subReason + sigNum, // status + app1Pss3, // pss + app1Rss3, // rss + IMPORTANCE_FOREGROUND_SERVICE, // importance + null); // description + + // try go get all from app1UidUser2 + list.clear(); + mAppExitInfoTracker.getExitInfo(app1PackageName, app1UidUser2, 0, 0, list); + assertEquals(1, list.size()); + + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now3, // timestamp + app1PidUser2, // pid + app1UidUser2, // uid + app1UidUser2, // packageUid + null, // definingUid + app1ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_SIGNALED, // reason + null, // subReason + sigNum, // status + app1Pss3, // pss + app1Rss3, // rss + IMPORTANCE_FOREGROUND_SERVICE, // importance + null); // description + + // Case 4: Create a process from another package with kill from lmkd + final int app2UidUser2 = 1010234; + final int app2PidUser2 = 12348; + final int app2Pss1 = 54321; + final int app2Rss1 = 65432; + final String app2ProcessName = "com.android.test.stub2:process"; + final String app2PackageName = "com.android.test.stub2"; + + sleep(1); + final long now4 = System.currentTimeMillis(); + doReturn(new Pair<Long, Object>(now4, Integer.valueOf(0))) + .when(mAppExitInfoTracker.mAppExitInfoSourceZygote) + .remove(anyInt(), anyInt()); + doReturn(new Pair<Long, Object>(now4, null)) + .when(mAppExitInfoTracker.mAppExitInfoSourceLmkd) + .remove(anyInt(), anyInt()); + + app = makeProcessRecord( + app2PidUser2, // pid + app2UidUser2, // uid + app2UidUser2, // packageUid + null, // definingUid + 0, // connectionGroup + PROCESS_STATE_CACHED_EMPTY, // procstate + app2Pss1, // pss + app2Rss1, // rss + app2ProcessName, // processName + app2PackageName); // packageName + updateExitInfo(app); + list.clear(); + mAppExitInfoTracker.getExitInfo(app2PackageName, app2UidUser2, app2PidUser2, 0, list); + assertEquals(1, list.size()); + + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now4, // timestamp + app2PidUser2, // pid + app2UidUser2, // uid + app2UidUser2, // packageUid + null, // definingUid + app2ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_LOW_MEMORY, // reason + null, // subReason + 0, // status + app2Pss1, // pss + app2Rss1, // rss + IMPORTANCE_CACHED, // importance + null); // description + + // Verify to get all from User2 regarding app2 + list.clear(); + mAppExitInfoTracker.getExitInfo(null, app2UidUser2, 0, 0, list); + assertEquals(1, list.size()); + + // Case 5: App native crash + final int app3UidUser2 = 1010345; + final int app3PidUser2 = 12349; + final int app3ConnectiongGroup = 4; + final int app3Pss1 = 54320; + final int app3Rss1 = 65430; + final String app3ProcessName = "com.android.test.stub3:process"; + final String app3PackageName = "com.android.test.stub3"; + final String app3Description = "native crash"; + + sleep(1); + final long now5 = System.currentTimeMillis(); + sigNum = OsConstants.SIGABRT; + doReturn(new Pair<Long, Object>(now5, Integer.valueOf(makeSignalStatus(sigNum)))) + .when(mAppExitInfoTracker.mAppExitInfoSourceZygote) + .remove(anyInt(), anyInt()); + doReturn(null) + .when(mAppExitInfoTracker.mAppExitInfoSourceLmkd) + .remove(anyInt(), anyInt()); + app = makeProcessRecord( + app3PidUser2, // pid + app3UidUser2, // uid + app3UidUser2, // packageUid + null, // definingUid + app3ConnectiongGroup, // connectionGroup + PROCESS_STATE_BOUND_TOP, // procstate + app3Pss1, // pss + app3Rss1, // rss + app3ProcessName, // processName + app3PackageName); // packageName + noteAppKill(app, ApplicationExitInfo.REASON_CRASH_NATIVE, + ApplicationExitInfo.SUBREASON_UNKNOWN, app3Description); + + updateExitInfo(app); + list.clear(); + mAppExitInfoTracker.getExitInfo(app3PackageName, app3UidUser2, app3PidUser2, 0, list); + assertEquals(1, list.size()); + + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now5, // timestamp + app3PidUser2, // pid + app3UidUser2, // uid + app3UidUser2, // packageUid + null, // definingUid + app3ProcessName, // processName + app3ConnectiongGroup, // connectionGroup + ApplicationExitInfo.REASON_CRASH_NATIVE, // reason + null, // subReason + sigNum, // status + app3Pss1, // pss + app3Rss1, // rss + IMPORTANCE_FOREGROUND, // importance + app3Description); // description + + // Verify the most recent kills, sorted by timestamp + int maxNum = 3; + list.clear(); + mAppExitInfoTracker.getExitInfo(null, app3UidUser2, 0, maxNum, list); + assertEquals(1, list.size()); + + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now5, // timestamp + app3PidUser2, // pid + app3UidUser2, // uid + app3UidUser2, // packageUid + null, // definingUid + app3ProcessName, // processName + app3ConnectiongGroup, // connectionGroup + ApplicationExitInfo.REASON_CRASH_NATIVE, // reason + null, // subReason + sigNum, // status + app3Pss1, // pss + app3Rss1, // rss + IMPORTANCE_FOREGROUND, // importance + app3Description); // description + + list.clear(); + mAppExitInfoTracker.getExitInfo(null, app2UidUser2, 0, maxNum, list); + assertEquals(1, list.size()); + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now4, // timestamp + app2PidUser2, // pid + app2UidUser2, // uid + app2UidUser2, // packageUid + null, // definingUid + app2ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_LOW_MEMORY, // reason + null, // subReason + 0, // status + app2Pss1, // pss + app2Rss1, // rss + IMPORTANCE_CACHED, // importance + null); // description + + list.clear(); + mAppExitInfoTracker.getExitInfo(null, app1UidUser2, 0, maxNum, list); + assertEquals(1, list.size()); + info = list.get(0); + + sigNum = OsConstants.SIGKILL; + verifyApplicationExitInfo( + info, // info + now3, // timestamp + app1PidUser2, // pid + app1UidUser2, // uid + app1UidUser2, // packageUid + null, // definingUid + app1ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_SIGNALED, // reason + null, // subReason + sigNum, // status + app1Pss3, // pss + app1Rss3, // rss + IMPORTANCE_FOREGROUND_SERVICE, // importance + null); // description + + // Case 6: App Java crash + final int app3Uid = 10345; + final int app3IsolatedUid = 99001; // it's an isolated process + final int app3Pid = 12350; + final int app3Pss2 = 23232; + final int app3Rss2 = 32323; + final String app3Description2 = "force close"; + + sleep(1); + final long now6 = System.currentTimeMillis(); + doReturn(null) + .when(mAppExitInfoTracker.mAppExitInfoSourceZygote) + .remove(anyInt(), anyInt()); + doReturn(null) + .when(mAppExitInfoTracker.mAppExitInfoSourceLmkd) + .remove(anyInt(), anyInt()); + app = makeProcessRecord( + app3Pid, // pid + app3IsolatedUid, // uid + app3Uid, // packageUid + null, // definingUid + 0, // connectionGroup + PROCESS_STATE_CACHED_EMPTY, // procstate + app3Pss2, // pss + app3Rss2, // rss + app3ProcessName, // processName + app3PackageName); // packageName + mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(app3IsolatedUid, app3Uid); + noteAppKill(app, ApplicationExitInfo.REASON_CRASH, + ApplicationExitInfo.SUBREASON_UNKNOWN, app3Description2); + + assertEquals(app3Uid, mAppExitInfoTracker.mIsolatedUidRecords + .getUidByIsolatedUid(app3IsolatedUid).longValue()); + updateExitInfo(app); + assertNull(mAppExitInfoTracker.mIsolatedUidRecords.getUidByIsolatedUid(app3IsolatedUid)); + + list.clear(); + mAppExitInfoTracker.getExitInfo(app3PackageName, app3Uid, 0, 1, list); + assertEquals(1, list.size()); + + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now6, // timestamp + app3Pid, // pid + app3IsolatedUid, // uid + app3Uid, // packageUid + null, // definingUid + app3ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_CRASH, // reason + null, // subReason + 0, // status + app3Pss2, // pss + app3Rss2, // rss + IMPORTANCE_CACHED, // importance + app3Description2); // description + + // Case 7: App1 is "uninstalled" from User2 + mAppExitInfoTracker.onPackageRemoved(app1PackageName, app1UidUser2, false); + list.clear(); + mAppExitInfoTracker.getExitInfo(app1PackageName, app1UidUser2, 0, 0, list); + assertEquals(0, list.size()); + + list.clear(); + mAppExitInfoTracker.getExitInfo(app1PackageName, app1Uid, 0, 0, list); + assertEquals(2, list.size()); + + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now2, // timestamp + app1Pid2, // pid + app1Uid, // uid + app1Uid, // packageUid + app1DefiningUid, // definingUid + app1ProcessName, // processName + app1ConnectiongGroup, // connectionGroup + ApplicationExitInfo.REASON_EXIT_SELF, // reason + null, // subReason + exitCode, // status + app1Pss2, // pss + app1Rss2, // rss + IMPORTANCE_SERVICE, // importance + null); // description + + // Case 8: App1 gets "remove task" + final String app1Description = "remove task"; + + sleep(1); + final int app1IsolatedUidUser2 = 1099002; // isolated uid + final int app1Pss4 = 34343; + final int app1Rss4 = 43434; + final long now8 = System.currentTimeMillis(); + sigNum = OsConstants.SIGKILL; + doReturn(new Pair<Long, Object>(now8, makeSignalStatus(sigNum))) + .when(mAppExitInfoTracker.mAppExitInfoSourceZygote) + .remove(anyInt(), anyInt()); + doReturn(null) + .when(mAppExitInfoTracker.mAppExitInfoSourceLmkd) + .remove(anyInt(), anyInt()); + app = makeProcessRecord( + app1PidUser2, // pid + app1IsolatedUidUser2, // uid + app1UidUser2, // packageUid + null, // definingUid + 0, // connectionGroup + PROCESS_STATE_CACHED_EMPTY, // procstate + app1Pss4, // pss + app1Rss4, // rss + app1ProcessName, // processName + app1PackageName); // packageName + + mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(app1IsolatedUidUser2, app1UidUser2); + noteAppKill(app, ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_UNKNOWN, app1Description); + + updateExitInfo(app); + list.clear(); + mAppExitInfoTracker.getExitInfo(app1PackageName, app1UidUser2, app1PidUser2, 1, list); + assertEquals(1, list.size()); + + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now8, // timestamp + app1PidUser2, // pid + app1IsolatedUidUser2, // uid + app1UidUser2, // packageUid + null, // definingUid + app1ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_OTHER, // reason + ApplicationExitInfo.SUBREASON_UNKNOWN, // subReason + 0, // status + app1Pss4, // pss + app1Rss4, // rss + IMPORTANCE_CACHED, // importance + app1Description); // description + + // App1 gets "too many empty" + final String app1Description2 = "too many empty"; + sleep(1); + final int app1Pid2User2 = 56565; + final int app1IsolatedUid2User2 = 1099003; // isolated uid + final int app1Pss5 = 34344; + final int app1Rss5 = 43435; + final long now9 = System.currentTimeMillis(); + sigNum = OsConstants.SIGKILL; + doReturn(new Pair<Long, Object>(now9, makeSignalStatus(sigNum))) + .when(mAppExitInfoTracker.mAppExitInfoSourceZygote) + .remove(anyInt(), anyInt()); + doReturn(null) + .when(mAppExitInfoTracker.mAppExitInfoSourceLmkd) + .remove(anyInt(), anyInt()); + app = makeProcessRecord( + app1Pid2User2, // pid + app1IsolatedUid2User2, // uid + app1UidUser2, // packageUid + null, // definingUid + 0, // connectionGroup + PROCESS_STATE_CACHED_EMPTY, // procstate + app1Pss5, // pss + app1Rss5, // rss + app1ProcessName, // processName + app1PackageName); // packageName + + mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(app1IsolatedUid2User2, app1UidUser2); + noteAppKill(app, ApplicationExitInfo.REASON_OTHER, + ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY, app1Description2); + + updateExitInfo(app); + list.clear(); + mAppExitInfoTracker.getExitInfo(app1PackageName, app1UidUser2, app1Pid2User2, 1, list); + assertEquals(1, list.size()); + + info = list.get(0); + + verifyApplicationExitInfo( + info, // info + now9, // timestamp + app1Pid2User2, // pid + app1IsolatedUid2User2, // uid + app1UidUser2, // packageUid + null, // definingUid + app1ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_OTHER, // reason + ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY, // subReason + 0, // status + app1Pss5, // pss + app1Rss5, // rss + IMPORTANCE_CACHED, // importance + app1Description2); // description + + + // Case 9: User2 gets removed + sleep(1); + mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(app1IsolatedUidUser2, app1UidUser2); + mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(app3IsolatedUid, app3Uid); + + mAppExitInfoTracker.onUserRemoved(UserHandle.getUserId(app1UidUser2)); + + assertNull(mAppExitInfoTracker.mIsolatedUidRecords.getUidByIsolatedUid( + app1IsolatedUidUser2)); + assertNotNull(mAppExitInfoTracker.mIsolatedUidRecords.getUidByIsolatedUid( + app3IsolatedUid)); + mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid( + app1IsolatedUidUser2, app1UidUser2); + mAppExitInfoTracker.mIsolatedUidRecords.removeAppUid(app1UidUser2, false); + assertNull(mAppExitInfoTracker.mIsolatedUidRecords.getUidByIsolatedUid( + app1IsolatedUidUser2)); + mAppExitInfoTracker.mIsolatedUidRecords.removeAppUid(app3Uid, true); + assertNull(mAppExitInfoTracker.mIsolatedUidRecords.getUidByIsolatedUid(app3IsolatedUid)); + + list.clear(); + mAppExitInfoTracker.getExitInfo(null, app1UidUser2, 0, 0, list); + assertEquals(0, list.size()); + + list.clear(); + mAppExitInfoTracker.getExitInfo(null, app1Uid, 0, 0, list); + assertEquals(2, list.size()); + + info = list.get(0); + + exitCode = 6; + verifyApplicationExitInfo( + info, // info + now2, // timestamp + app1Pid2, // pid + app1Uid, // uid + app1Uid, // packageUid + app1DefiningUid, // definingUid + app1ProcessName, // processName + app1ConnectiongGroup, // connectionGroup + ApplicationExitInfo.REASON_EXIT_SELF, // reason + null, // subReason + exitCode, // status + app1Pss2, // pss + app1Rss2, // rss + IMPORTANCE_SERVICE, // importance + null); // description + + info = list.get(1); + exitCode = 5; + verifyApplicationExitInfo( + info, // info + now1, // timestamp + app1Pid1, // pid + app1Uid, // uid + app1Uid, // packageUid + null, // definingUid + app1ProcessName, // processName + 0, // connectionGroup + ApplicationExitInfo.REASON_EXIT_SELF, // reason + null, // subReason + exitCode, // status + app1Pss1, // pss + app1Rss1, // rss + IMPORTANCE_CACHED, // importance + null); // description + + // Case 10: Save the info and load them again + ArrayList<ApplicationExitInfo> original = new ArrayList<ApplicationExitInfo>(); + mAppExitInfoTracker.getExitInfo(null, app1Uid, 0, 0, original); + assertTrue(original.size() > 0); + + mAppExitInfoTracker.mProcExitInfoFile = new File(mContext.getFilesDir(), + AppExitInfoTracker.APP_EXIT_INFO_FILE); + mAppExitInfoTracker.persistProcessExitInfo(); + assertTrue(mAppExitInfoTracker.mProcExitInfoFile.exists()); + + mAppExitInfoTracker.clearProcessExitInfo(false); + list.clear(); + mAppExitInfoTracker.getExitInfo(null, app1Uid, 0, 0, list); + assertEquals(0, list.size()); + + mAppExitInfoTracker.loadExistingProcessExitInfo(); + list.clear(); + mAppExitInfoTracker.getExitInfo(null, app1Uid, 0, 0, list); + assertEquals(original.size(), list.size()); + + for (int i = list.size() - 1; i >= 0; i--) { + assertTrue(list.get(i).equals(original.get(i))); + } + } + + private static int makeExitStatus(int exitCode) { + return (exitCode << 8) & 0xff00; + } + + private static int makeSignalStatus(int sigNum) { + return sigNum & 0x7f; + } + + private void sleep(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + } + } + + private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, Integer definingUid, + int connectionGroup, int procState, int pss, int rss, + String processName, String packageName) { + ApplicationInfo ai = new ApplicationInfo(); + ai.packageName = packageName; + ProcessRecord app = new ProcessRecord(mAms, ai, processName, uid); + app.pid = pid; + app.info.uid = packageUid; + if (definingUid != null) { + final String dummyPackageName = "com.android.test"; + final String dummyClassName = ".Foo"; + app.hostingRecord = HostingRecord.byAppZygote(new ComponentName( + dummyPackageName, dummyClassName), "", definingUid); + } + app.connectionGroup = connectionGroup; + app.setProcState = procState; + app.lastMemInfo = spy(new Debug.MemoryInfo()); + doReturn(pss).when(app.lastMemInfo).getTotalPss(); + doReturn(rss).when(app.lastMemInfo).getTotalRss(); + return app; + } + + private void verifyApplicationExitInfo(ApplicationExitInfo info, + Long timestamp, Integer pid, Integer uid, Integer packageUid, + Integer definingUid, String processName, Integer connectionGroup, + Integer reason, Integer subReason, Integer status, + Integer pss, Integer rss, Integer importance, String description) { + assertNotNull(info); + + if (timestamp != null) { + final long tolerance = 1000; // ms + assertTrue(timestamp - tolerance <= info.getTimestamp()); + assertTrue(timestamp + tolerance >= info.getTimestamp()); + } + if (pid != null) { + assertEquals(pid.intValue(), info.getPid()); + } + if (uid != null) { + assertEquals(uid.intValue(), info.getRealUid()); + } + if (packageUid != null) { + assertEquals(packageUid.intValue(), info.getPackageUid()); + } + if (definingUid != null) { + assertEquals(definingUid.intValue(), info.getDefiningUid()); + } + if (processName != null) { + assertTrue(TextUtils.equals(processName, info.getProcessName())); + } + if (connectionGroup != null) { + assertEquals(connectionGroup.intValue(), info.getConnectionGroup()); + } + if (reason != null) { + assertEquals(reason.intValue(), info.getReason()); + } + if (subReason != null) { + assertEquals(subReason.intValue(), info.getSubReason()); + } + if (status != null) { + assertEquals(status.intValue(), info.getStatus()); + } + if (pss != null) { + assertEquals(pss.intValue(), info.getPss()); + } + if (rss != null) { + assertEquals(rss.intValue(), info.getRss()); + } + if (importance != null) { + assertEquals(importance.intValue(), info.getImportance()); + } + if (description != null) { + assertTrue(TextUtils.equals(description, info.getDescription())); + } + } + + private class TestInjector extends Injector { + TestInjector(Context context) { + super(context); + } + + @Override + public AppOpsService getAppOpsService(File file, Handler handler) { + return mAppOpsService; + } + + @Override + public Handler getUiHandler(ActivityManagerService service) { + return mHandler; + } + + @Override + public ProcessList getProcessList(ActivityManagerService service) { + return mProcessList; + } + } + + static class ServiceThreadRule implements TestRule { + + private ServiceThread mThread; + + ServiceThread getThread() { + return mThread; + } + + @Override + public Statement apply(Statement base, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + mThread = new ServiceThread("TestServiceThread", + Process.THREAD_PRIORITY_DEFAULT, true /* allowIo */); + mThread.start(); + try { + base.evaluate(); + } finally { + mThread.getThreadHandler().runWithScissors(mThread::quit, 0 /* timeout */); + } + } + }; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/appsearch/impl/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/impl/AppSearchImplTest.java index 41956794aaf2..34ade818f062 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/impl/AppSearchImplTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/impl/AppSearchImplTest.java @@ -101,7 +101,9 @@ public class AppSearchImplTest { IllegalStateException e = expectThrows( IllegalStateException.class, () -> impl.setSchema( - /*callingUid=*/Integer.MAX_VALUE, SchemaProto.getDefaultInstance())); + /*callingUid=*/Integer.MAX_VALUE, + SchemaProto.getDefaultInstance(), + /*forceOverride=*/false)); assertThat(e).hasMessageThat().contains("Failed to look up package name"); } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index a3d15dd7de3b..1b5c56a4b4c9 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -230,6 +230,18 @@ public abstract class BaseLockSettingsServiceTests { } }).when(sm).addUserKeyAuth(anyInt(), anyInt(), any(), any()); + doAnswer(new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + Object[] args = invocation.getArguments(); + mStorageManager.clearUserKeyAuth((int) args[0] /* userId */, + (int) args[1] /* serialNumber */, + (byte[]) args[2] /* token */, + (byte[]) args[3] /* secret */); + return null; + } + }).when(sm).clearUserKeyAuth(anyInt(), anyInt(), any(), any()); + doAnswer( new Answer<Void>() { @Override diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java index 1ae1fa65ddf2..102bac111ada 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java @@ -36,6 +36,15 @@ public class FakeStorageManager { getUserAuth(userId).add(new Pair<>(token, secret)); } + public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) { + ArrayList<Pair<byte[], byte[]>> auths = getUserAuth(userId); + if (token == null && secret == null) { + return; + } + auths.remove(new Pair<>(token, secret)); + auths.add(new Pair<>(null, null)); + } + public void fixateNewestUserKeyAuth(int userId) { ArrayList<Pair<byte[], byte[]>> auths = mAuth.get(userId); Pair<byte[], byte[]> latest = auths.get(auths.size() - 1); diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java index e8f7849ef96a..7344fa42016c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java @@ -27,8 +27,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.when; +import android.annotation.Nullable; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.SurfaceControl; @@ -111,8 +114,12 @@ public class DimmerTests extends WindowTestsBase { private static class SurfaceAnimatorStarterImpl implements Dimmer.SurfaceAnimatorStarter { @Override public void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t, - AnimationAdapter anim, boolean hidden) { - surfaceAnimator.mAnimationFinishedCallback.run(); + AnimationAdapter anim, boolean hidden, + @Nullable Runnable animationFinishedCallback) { + surfaceAnimator.mStaticAnimationFinishedCallback.run(); + if (animationFinishedCallback != null) { + animationFinishedCallback.run(); + } } } @@ -216,7 +223,8 @@ public class DimmerTests extends WindowTestsBase { mDimmer.updateDims(mTransaction, new Rect()); verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any( - SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean()); + SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean(), + isNull()); verify(mHost.getPendingTransaction()).remove(dimLayer); } @@ -273,7 +281,8 @@ public class DimmerTests extends WindowTestsBase { mDimmer.resetDimStates(); mDimmer.updateDims(mTransaction, new Rect()); verify(mSurfaceAnimatorStarter, never()).startAnimation(any(SurfaceAnimator.class), any( - SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean()); + SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean(), + isNull()); verify(mTransaction).remove(dimLayer); } 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 f2ba97c269d5..1637370df0f7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -39,6 +39,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; @@ -139,6 +140,7 @@ public class DisplayContentTests extends WindowTestsBase { mChildAppWindowAbove, mDockedDividerWindow, mStatusBarWindow, + mNotificationShadeWindow, mNavBarWindow, mImeWindow, mImeDialogWindow)); @@ -161,6 +163,7 @@ public class DisplayContentTests extends WindowTestsBase { mImeDialogWindow, mDockedDividerWindow, mStatusBarWindow, + mNotificationShadeWindow, mNavBarWindow)); } @@ -177,6 +180,7 @@ public class DisplayContentTests extends WindowTestsBase { mImeDialogWindow, mDockedDividerWindow, mStatusBarWindow, + mNotificationShadeWindow, mNavBarWindow)); } @@ -193,6 +197,24 @@ public class DisplayContentTests extends WindowTestsBase { mStatusBarWindow, mImeWindow, mImeDialogWindow, + mNotificationShadeWindow, + mNavBarWindow)); + } + + @Test + public void testForAllWindows_WithNotificationShadeImeTarget() throws Exception { + mDisplayContent.mInputMethodTarget = mNotificationShadeWindow; + + assertForAllWindowsOrder(Arrays.asList( + mWallpaperWindow, + mChildAppWindowBelow, + mAppWindow, + mChildAppWindowAbove, + mDockedDividerWindow, + mStatusBarWindow, + mNotificationShadeWindow, + mImeWindow, + mImeDialogWindow, mNavBarWindow)); } @@ -211,6 +233,7 @@ public class DisplayContentTests extends WindowTestsBase { mDockedDividerWindow, voiceInteractionWindow, mStatusBarWindow, + mNotificationShadeWindow, mNavBarWindow, mImeWindow, mImeDialogWindow)); @@ -585,7 +608,7 @@ public class DisplayContentTests extends WindowTestsBase { final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w"); window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); - final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard"); + final WindowState keyguard = createWindow(null, TYPE_NOTIFICATION_SHADE , dc, "keyguard"); keyguard.mHasSurface = true; keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED; diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index df34c7c00b51..c3bead7162e6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -22,13 +22,16 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -118,11 +121,11 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_keyguard() { - addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |= PRIVATE_FLAG_KEYGUARD; + addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade"); addWindow(TYPE_NAVIGATION_BAR, "navBar"); + mockKeyguardShowing(); final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); - // The app must not control the top bar. assertNotNull(controls); assertEquals(1, controls.length); @@ -130,9 +133,9 @@ public class InsetsPolicyTest extends WindowTestsBase { // TODO: adjust this test if we pretend to the app that it's still able to control it. @Test - public void testControlsForDispatch_forceStatusBarVisibleTransparent() { - addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |= - PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; + public void testControlsForDispatch_forceStatusBarVisible() { + addWindow(TYPE_STATUS_BAR, "topBar").mAttrs.privateFlags |= + PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; addWindow(TYPE_NAVIGATION_BAR, "navBar"); final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); @@ -144,7 +147,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_statusBarForceShowNavigation() { - addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |= + addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.privateFlags |= PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; addWindow(TYPE_NAVIGATION_BAR, "navBar"); @@ -257,4 +260,10 @@ public class InsetsPolicyTest extends WindowTestsBase { mDisplayContent.getInsetsPolicy().updateBarControlTarget(win); return mDisplayContent.getInsetsStateController().getControlsForDispatch(win); } + + private void mockKeyguardShowing() { + final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); + spyOn(displayPolicy); + doReturn(true).when(displayPolicy).isKeyguardShowing(); + } } 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 894890a2d0f1..277bc41cf34e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; @@ -85,9 +86,12 @@ public class RootWindowContainerTests extends WindowTestsBase { public void testIsAnyNonToastWindowVisibleForUid_aFewNonToastButNoneVisible() { final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar", FAKE_CALLING_UID); + final WindowState notificationShade = createWindow(null, TYPE_NOTIFICATION_SHADE, + "notificationShade", FAKE_CALLING_UID); final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID); assertFalse(statusBar.isVisibleNow()); + assertFalse(notificationShade.isVisibleNow()); assertFalse(app.isVisibleNow()); assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID)); } 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 08ee0eb30d6b..9f45044c6a60 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -17,7 +17,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; -import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; @@ -91,7 +91,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { @Override public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) { - return attrs.type == TYPE_STATUS_BAR; + return attrs.type == TYPE_NOTIFICATION_SHADE; } @Override @@ -263,6 +263,11 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override + public boolean isKeyguardShowing() { + return mKeyguardShowingAndNotOccluded; + } + + @Override public boolean isKeyguardShowingAndNotOccluded() { return mKeyguardShowingAndNotOccluded; } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java index d3cd3cbb42ca..05d048d360ea 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java @@ -829,12 +829,15 @@ public class WindowContainerTests extends WindowTestsBase { wc.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(adapter); spyOn(wc); doReturn(true).when(wc).okToAnimate(); + final Runnable onAnimationFinishedCallback = mock(Runnable.class); // Make sure animating state is as expected after applied animation. - assertTrue(wc.applyAnimation(null, TRANSIT_TASK_OPEN, true, false)); + assertTrue(wc.applyAnimation(null, TRANSIT_TASK_OPEN, true, false, + onAnimationFinishedCallback)); assertEquals(wc.getTopMostActivity(), act); assertTrue(wc.isAnimating()); assertTrue(act.isAnimating(PARENTS)); + verify(onAnimationFinishedCallback, times(0)).run(); // Make sure animation finish callback will be received and reset animating state after // animation finish. @@ -843,6 +846,7 @@ public class WindowContainerTests extends WindowTestsBase { verify(wc).onAnimationFinished(); assertFalse(wc.isAnimating()); assertFalse(act.isAnimating(PARENTS)); + verify(onAnimationFinishedCallback, times(1)).run(); } /* Used so we can gain access to some protected members of the {@link WindowContainer} class */ 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 7e248f854dcf..6d0b54fd2ccd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -545,7 +545,7 @@ public class WindowStateTests extends WindowTestsBase { final WindowState startingWindow = createWindow(null /* parent */, TYPE_APPLICATION_STARTING, startingApp.mToken, "starting"); startingApp.mActivityRecord.startingWindow = startingWindow; - final WindowState keyguardHostWindow = mStatusBarWindow; + final WindowState keyguardHostWindow = mNotificationShadeWindow; final WindowState allDrawnApp = mAppWindow; allDrawnApp.mActivityRecord.allDrawn = true; 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 31a7f2437536..20eab5a45ff1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -31,6 +31,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; @@ -76,6 +77,7 @@ class WindowTestsBase extends SystemServiceTestsBase { WindowState mImeWindow; WindowState mImeDialogWindow; WindowState mStatusBarWindow; + WindowState mNotificationShadeWindow; WindowState mDockedDividerWindow; WindowState mNavBarWindow; WindowState mAppWindow; @@ -119,6 +121,8 @@ class WindowTestsBase extends SystemServiceTestsBase { mImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG, "mImeDialogWindow"); mStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "mStatusBarWindow"); + mNotificationShadeWindow = createCommonWindow(null, TYPE_NOTIFICATION_SHADE, + "mNotificationShadeWindow"); mNavBarWindow = createCommonWindow(null, TYPE_NAVIGATION_BAR, "mNavBarWindow"); mDockedDividerWindow = createCommonWindow(null, TYPE_DOCK_DIVIDER, "mDockedDividerWindow"); diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index c4c1e21e7c41..c3fb51076bba 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -849,6 +849,17 @@ public class TelecomManager { */ public static final int PRESENTATION_PAYPHONE = 4; + + /* + * Values for the adb property "persist.radio.videocall.audio.output" + */ + /** @hide */ + public static final int AUDIO_OUTPUT_ENABLE_SPEAKER = 0; + /** @hide */ + public static final int AUDIO_OUTPUT_DISABLE_SPEAKER = 1; + /** @hide */ + public static final int AUDIO_OUTPUT_DEFAULT = AUDIO_OUTPUT_ENABLE_SPEAKER; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef( diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java index f39981fdf25d..f3e9de0d2688 100644 --- a/telephony/common/android/telephony/LocationAccessPolicy.java +++ b/telephony/common/android/telephony/LocationAccessPolicy.java @@ -24,20 +24,16 @@ import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; -import android.content.pm.UserInfo; import android.location.LocationManager; import android.os.Binder; import android.os.Build; import android.os.Process; import android.os.UserHandle; -import android.os.UserManager; import android.util.Log; import android.widget.Toast; import com.android.internal.telephony.util.TelephonyUtils; -import java.util.List; - /** * Helper for performing location access checks. * @hide @@ -309,7 +305,7 @@ public final class LocationAccessPolicy { } private static boolean checkSystemLocationAccess(@NonNull Context context, int uid, int pid) { - if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))) { + if (!isLocationModeEnabled(context, UserHandle.getUserHandleForUid(uid).getIdentifier())) { if (DBG) Log.w(TAG, "Location disabled, failed, (" + uid + ")"); return false; } @@ -336,20 +332,17 @@ public final class LocationAccessPolicy { private static boolean isCurrentProfile(@NonNull Context context, int uid) { long token = Binder.clearCallingIdentity(); try { - final int currentUser = ActivityManager.getCurrentUser(); - final int callingUserId = UserHandle.getUserId(uid); - if (callingUserId == currentUser) { + if (UserHandle.getUserHandleForUid(uid).getIdentifier() + == ActivityManager.getCurrentUser()) { return true; + } + ActivityManager activityManager = context.getSystemService(ActivityManager.class); + if (activityManager != null) { + return activityManager.isProfileForeground( + UserHandle.getUserHandleForUid(ActivityManager.getCurrentUser())); } else { - List<UserInfo> userProfiles = context.getSystemService( - UserManager.class).getProfiles(currentUser); - for (UserInfo user : userProfiles) { - if (user.id == callingUserId) { - return true; - } - } + return false; } - return false; } finally { Binder.restoreCallingIdentity(token); } diff --git a/telephony/java/android/telephony/PinResult.java b/telephony/java/android/telephony/PinResult.java new file mode 100644 index 000000000000..c14bd91d022c --- /dev/null +++ b/telephony/java/android/telephony/PinResult.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.telephony.PhoneConstants; + +import java.util.Objects; + +/** + * Holds the result from a pin attempt. + * + * @hide + */ +@SystemApi +public final class PinResult implements Parcelable { + /** @hide */ + @IntDef({ + PIN_RESULT_TYPE_SUCCESS, + PIN_RESULT_TYPE_INCORRECT, + PIN_RESULT_TYPE_FAILURE, + }) + public @interface PinResultType {} + + /** + * Indicates that the pin attempt was a success. + */ + public static final int PIN_RESULT_TYPE_SUCCESS = PhoneConstants.PIN_RESULT_SUCCESS; + + /** + * Indicates that the pin attempt was incorrect. + */ + public static final int PIN_RESULT_TYPE_INCORRECT = PhoneConstants.PIN_PASSWORD_INCORRECT; + + /** + * Indicates that the pin attempt was a failure. + */ + public static final int PIN_RESULT_TYPE_FAILURE = PhoneConstants.PIN_GENERAL_FAILURE; + + private static final PinResult sFailedResult = + new PinResult(PinResult.PIN_RESULT_TYPE_FAILURE, -1); + + private final @PinResultType int mType; + + private final int mAttemptsRemaining; + + /** + * Returns either success, incorrect or failure. + * + * @see #PIN_RESULT_TYPE_SUCCESS + * @see #PIN_RESULT_TYPE_INCORRECT + * @see #PIN_RESULT_TYPE_FAILURE + * @return The result type of the pin attempt. + */ + public @PinResultType int getType() { + return mType; + } + + /** + * The number of pin attempts remaining. + * + * @return Number of attempts remaining. + */ + public int getAttemptsRemaining() { + return mAttemptsRemaining; + } + + @NonNull + public static PinResult getDefaultFailedResult() { + return sFailedResult; + } + + /** + * PinResult constructor + * + * @param type The type of pin result. + * @see #PIN_RESULT_TYPE_SUCCESS + * @see #PIN_RESULT_TYPE_INCORRECT + * @see #PIN_RESULT_TYPE_FAILURE + * @param attemptsRemaining Number of pin attempts remaining. + */ + public PinResult(@PinResultType int type, int attemptsRemaining) { + mType = type; + mAttemptsRemaining = attemptsRemaining; + } + + /** + * Construct a PinResult object from the given parcel. + * + * @hide + */ + private PinResult(Parcel in) { + mType = in.readInt(); + mAttemptsRemaining = in.readInt(); + } + + /** + * String representation of the Pin Result. + */ + @NonNull + @Override + public String toString() { + return "type: " + getType() + ", attempts remaining: " + getAttemptsRemaining(); + } + + /** + * Required to be Parcelable + */ + @Override + public int describeContents() { + return 0; + } + + /** + * Required to be Parcelable + */ + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeInt(mType); + out.writeInt(mAttemptsRemaining); + } + + /** Required to be Parcelable */ + public static final @NonNull Parcelable.Creator<PinResult> CREATOR = new Creator<PinResult>() { + public PinResult createFromParcel(Parcel in) { + return new PinResult(in); + } + public PinResult[] newArray(int size) { + return new PinResult[size]; + } + }; + + @Override + public int hashCode() { + return Objects.hash(mAttemptsRemaining, mType); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + PinResult other = (PinResult) obj; + return (mType == other.mType + && mAttemptsRemaining == other.mAttemptsRemaining); + } +} diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index b42ce35aa79c..8de5b8541f56 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -782,6 +782,12 @@ public class SubscriptionManager { public static final String UICC_APPLICATIONS_ENABLED = SimInfo.UICC_APPLICATIONS_ENABLED; /** + * Indicate which network type is allowed. By default it's enabled. + * @hide + */ + public static final String ALLOWED_NETWORK_TYPES = SimInfo.ALLOWED_NETWORK_TYPES; + + /** * Broadcast Action: The user has changed one of the default subs related to * data, phone calls, or sms</p> * @@ -2434,7 +2440,28 @@ public class SubscriptionManager { try { return Integer.parseInt(result); } catch (NumberFormatException err) { - logd("getBooleanSubscriptionProperty NumberFormat exception"); + logd("getIntegerSubscriptionProperty NumberFormat exception"); + } + } + return defValue; + } + + /** + * Returns long value corresponding to query result. + * @param subId Subscription Id of Subscription + * @param propKey Column name in SubscriptionInfo database + * @param defValue Default long value to be returned + * @return long result value to be returned + * @hide + */ + public static long getLongSubscriptionProperty(int subId, String propKey, long defValue, + Context context) { + String result = getSubscriptionProperty(subId, propKey, context); + if (result != null) { + try { + return Long.parseLong(result); + } catch (NumberFormatException err) { + logd("getLongSubscriptionProperty NumberFormat exception"); } } return defValue; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index dd5c0659fd69..c9d5006946aa 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -7687,7 +7687,9 @@ public class TelephonyManager { * * @return the preferred network type. * @hide + * @deprecated Use {@link #getPreferredNetworkTypeBitmask} instead. */ + @Deprecated @RequiresPermission((android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) @UnsupportedAppUsage public @PrefNetworkMode int getPreferredNetworkType(int subId) { @@ -7732,6 +7734,30 @@ public class TelephonyManager { } /** + * Get the allowed network types. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE} + * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). + * + * @return the allowed network type bitmask + * @hide + */ + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + public @NetworkTypeBitMask long getAllowedNetworkTypes() { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getAllowedNetworkTypes(getSubId()); + } + } catch (RemoteException ex) { + Rlog.e(TAG, "getAllowedNetworkTypes RemoteException", ex); + } + return -1; + } + + /** * Sets the network selection mode to automatic. * * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the @@ -7982,7 +8008,9 @@ public class TelephonyManager { * @param networkType the preferred network type * @return true on success; false on any failure. * @hide + * @deprecated Use {@link #setPreferredNetworkTypeBitmask} instead. */ + @Deprecated @UnsupportedAppUsage public boolean setPreferredNetworkType(int subId, @PrefNetworkMode int networkType) { try { @@ -7997,7 +8025,8 @@ public class TelephonyManager { } /** - * Set the preferred network type bitmask. + * Set the preferred network type bitmask but if {@link #setAllowedNetworkTypes} has been set, + * only the allowed network type will set to the modem. * * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()} @@ -8027,6 +8056,29 @@ public class TelephonyManager { } /** + * Set the allowed network types of the device. This is for carrier or privileged apps to + * enable/disable certain network types on the device. The user preferred network types should + * be set through {@link #setPreferredNetworkTypeBitmask}. + * + * @param allowedNetworkTypes The bitmask of allowed network types. + * @return true on success; false on any failure. + * @hide + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @SystemApi + public boolean setAllowedNetworkTypes(@NetworkTypeBitMask long allowedNetworkTypes) { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.setAllowedNetworkTypes(getSubId(), allowedNetworkTypes); + } + } catch (RemoteException ex) { + Rlog.e(TAG, "setAllowedNetworkTypes RemoteException", ex); + } + return false; + } + + /** * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA. * * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). @@ -8547,9 +8599,13 @@ public class TelephonyManager { return false; } - /** @hide */ + /** + * @deprecated use {@link #supplyPinReportPinResult(String pin)} instead. + * + * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @Deprecated public int[] supplyPinReportResult(String pin) { try { ITelephony telephony = getITelephony(); @@ -8561,9 +8617,13 @@ public class TelephonyManager { return new int[0]; } - /** @hide */ + /** + * @deprecated use {@link #supplyPukReportPinResult(String puk, String pin)} instead. + * + * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @Deprecated public int[] supplyPukReportResult(String puk, String pin) { try { ITelephony telephony = getITelephony(); @@ -8576,6 +8636,55 @@ public class TelephonyManager { } /** + * Used when the user attempts to enter their pin. + * + * @param pin The user entered pin. + * @return The result of the pin. + * + * @hide + */ + @SystemApi + @Nullable + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public PinResult supplyPinReportPinResult(@NonNull String pin) { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + int[] result = telephony.supplyPinReportResultForSubscriber(getSubId(), pin); + return new PinResult(result[0], result[1]); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#supplyPinReportResultForSubscriber", e); + } + return null; + } + + /** + * Used when the user attempts to enter the puk or their pin. + * + * @param puk The product unblocking key. + * @param pin The user entered pin. + * @return The result of the pin. + * + * @hide + */ + @SystemApi + @Nullable + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public PinResult supplyPukReportPinResult(@NonNull String puk, @NonNull String pin) { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + int[] result = telephony.supplyPukReportResultForSubscriber(getSubId(), puk, pin); + return new PinResult(result[0], result[1]); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#]", e); + } + return null; + } + + /** * Used to notify callers of * {@link TelephonyManager#sendUssdRequest(String, UssdResponseCallback, Handler)} when the * network either successfully executes a USSD request, or if there was a failure while @@ -10982,9 +11091,15 @@ public class TelephonyManager { } /** - * Checks if FEATURE_TELEPHONY_DATA is enabled. - * - * @hide + * @return true if the current device is "data capable" over a radio on the device. + * <p> + * "Data capable" means that this device supports packet-switched + * data connections over the telephony network. + * <p> + * Note: the meaning of this flag is subtly different from the + * PackageManager.FEATURE_TELEPHONY system feature, which is available + * on any device with a telephony radio, even if the device is + * voice-only. */ public boolean isDataCapable() { if (mContext == null) return true; @@ -12417,15 +12532,21 @@ public class TelephonyManager { } /** - * Set allowing mobile data during voice call. + * Set allowing mobile data during voice call. This is used for allowing data on the non-default + * data SIM. When a voice call is placed on the non-default data SIM on DSDS devices, users will + * not be able to use mobile data. By calling this API, data will be temporarily enabled on the + * non-default data SIM during the life cycle of the voice call. * * @param allow {@code true} if allowing using data during voice call, {@code false} if - * disallowed + * disallowed. + * + * @return {@code true} if operation is successful. otherwise {@code false}. * - * @return {@code false} if the setting is changed. + * @throws SecurityException if the caller doesn't have the permission. * * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setDataAllowedDuringVoiceCall(boolean allow) { try { @@ -12434,6 +12555,7 @@ public class TelephonyManager { return service.setDataAllowedDuringVoiceCall(getSubId(), allow); } } catch (RemoteException ex) { + // This could happen if binder process crashes. if (!isSystemProcess()) { ex.rethrowAsRuntimeException(); } @@ -12442,13 +12564,18 @@ public class TelephonyManager { } /** - * Check whether data is allowed during voice call. Note this is for dual sim device that - * data might be disabled on non-default data subscription but explicitly turned on by settings. + * Check whether data is allowed during voice call. This is used for allowing data on the + * non-default data SIM. When a voice call is placed on the non-default data SIM on DSDS + * devices, users will not be able to use mobile data. By calling this API, data will be + * temporarily enabled on the non-default data SIM during the life cycle of the voice call. * * @return {@code true} if data is allowed during voice call. * + * @throws SecurityException if the caller doesn't have the permission. + * * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataAllowedInVoiceCall() { try { @@ -12457,6 +12584,7 @@ public class TelephonyManager { return service.isDataAllowedInVoiceCall(getSubId()); } } catch (RemoteException ex) { + // This could happen if binder process crashes. if (!isSystemProcess()) { ex.rethrowAsRuntimeException(); } @@ -12489,4 +12617,108 @@ public class TelephonyManager { } return false; } + + /** + * The IccLock state or password was changed successfully. + * @hide + */ + @SystemApi + public static final int CHANGE_ICC_LOCK_SUCCESS = Integer.MAX_VALUE; + + /** + * Check whether ICC pin lock is enabled. + * This is a sync call which returns the cached pin enabled state. + * + * @return {@code true} if ICC lock enabled, {@code false} if ICC lock disabled. + * + * @throws SecurityException if the caller doesn't have the permission. + * + * @hide + */ + @SystemApi + @WorkerThread + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public boolean isIccLockEnabled() { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.isIccLockEnabled(getSubId()); + } + } catch (RemoteException e) { + Log.e(TAG, "isIccLockEnabled RemoteException", e); + } + return false; + } + + /** + * Set the ICC pin lock enabled or disabled. + * + * If enable/disable ICC pin lock successfully, a value of {@link Integer#MAX_VALUE} is + * returned. + * If an incorrect old password is specified, the return value will indicate how many more + * attempts the user can make to change the password before the SIM is locked. + * Using PUK code to unlock SIM if enter the incorrect old password 3 times. + * + * @param enabled "true" for locked, "false" for unlocked. + * @param password needed to change the ICC pin state, aka. Pin1 + * @return an integer representing the status of IccLock enabled or disabled in the following + * three cases: + * - {@link TelephonyManager#CHANGE_ICC_LOCK_SUCCESS} if enabled or disabled IccLock + * successfully. + * - Positive number and zero for remaining password attempts. + * - Negative number for other failure cases (such like enabling/disabling PIN failed). + * + * @throws SecurityException if the caller doesn't have the permission. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public int setIccLockEnabled(boolean enabled, @NonNull String password) { + checkNotNull(password, "setIccLockEnabled password can't be null."); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.setIccLockEnabled(getSubId(), enabled, password); + } + } catch (RemoteException e) { + Log.e(TAG, "setIccLockEnabled RemoteException", e); + } + return 0; + } + + /** + * Change the ICC password used in ICC pin lock. + * + * If the password was changed successfully, a value of {@link Integer#MAX_VALUE} is returned. + * If an incorrect old password is specified, the return value will indicate how many more + * attempts the user can make to change the password before the SIM is locked. + * Using PUK code to unlock SIM if enter the incorrect old password 3 times. + * + * @param oldPassword is the old password + * @param newPassword is the new password + * @return an integer representing the status of IccLock changed in the following three cases: + * - {@link TelephonyManager#CHANGE_ICC_LOCK_SUCCESS} if changed IccLock successfully. + * - Positive number and zero for remaining password attempts. + * - Negative number for other failure cases (such like enabling/disabling PIN failed). + * + * @throws SecurityException if the caller doesn't have the permission. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public int changeIccLockPassword(@NonNull String oldPassword, @NonNull String newPassword) { + checkNotNull(oldPassword, "changeIccLockPassword oldPassword can't be null."); + checkNotNull(newPassword, "changeIccLockPassword newPassword can't be null."); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.changeIccLockPassword(getSubId(), oldPassword, newPassword); + } + } catch (RemoteException e) { + Log.e(TAG, "changeIccLockPassword RemoteException", e); + } + return 0; + } } diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index fab1bf2215af..6e630e3a7024 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -18,6 +18,7 @@ package android.telephony.data; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.content.ContentValues; import android.database.Cursor; import android.hardware.radio.V1_5.ApnTypes; @@ -28,13 +29,14 @@ import android.provider.Telephony; import android.provider.Telephony.Carriers; import android.telephony.Annotation.ApnType; import android.telephony.Annotation.NetworkType; -import com.android.telephony.Rlog; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; +import com.android.telephony.Rlog; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.InetAddress; @@ -123,6 +125,122 @@ public class ApnSetting implements Parcelable { /** Authentication type for PAP or CHAP. */ public static final int AUTH_TYPE_PAP_OR_CHAP = 3; + /** + * APN types for data connections. These are usage categories for an APN + * entry. One APN entry may support multiple APN types, eg, a single APN + * may service regular internet traffic ("default") as well as MMS-specific + * connections.<br/> + * APN_TYPE_ALL is a special type to indicate that this APN entry can + * service all data connections. + * <p> + * Note: The goal is to deprecate this. Due to the Carrier Table being used + * directly, this isn't feasible right now. + * + * @hide + */ + @SystemApi + public static final String TYPE_ALL_STRING = "*"; + + /** + * APN type for default data traffic + * + * @hide + */ + @SystemApi + public static final String TYPE_DEFAULT_STRING = "default"; + + + /** + * APN type for MMS traffic + * + * @hide + */ + @SystemApi + public static final String TYPE_MMS_STRING = "mms"; + + + /** + * APN type for SUPL assisted GPS + * + * @hide + */ + @SystemApi + public static final String TYPE_SUPL_STRING = "supl"; + + /** + * APN type for DUN traffic + * + * @hide + */ + @SystemApi + public static final String TYPE_DUN_STRING = "dun"; + + /** + * APN type for HiPri traffic + * + * @hide + */ + @SystemApi + public static final String TYPE_HIPRI_STRING = "hipri"; + + /** + * APN type for FOTA + * + * @hide + */ + @SystemApi + public static final String TYPE_FOTA_STRING = "fota"; + + /** + * APN type for IMS + * + * @hide + */ + @SystemApi + public static final String TYPE_IMS_STRING = "ims"; + + /** + * APN type for CBS + * + * @hide + */ + @SystemApi + public static final String TYPE_CBS_STRING = "cbs"; + + /** + * APN type for IA Initial Attach APN + * + * @hide + */ + @SystemApi + public static final String TYPE_IA_STRING = "ia"; + + /** + * APN type for Emergency PDN. This is not an IA apn, but is used + * for access to carrier services in an emergency call situation. + * + * @hide + */ + @SystemApi + public static final String TYPE_EMERGENCY_STRING = "emergency"; + + /** + * APN type for Mission Critical Services + * + * @hide + */ + @SystemApi + public static final String TYPE_MCX_STRING = "mcx"; + + /** + * APN type for XCAP + * + * @hide + */ + @SystemApi + public static final String TYPE_XCAP_STRING = "xcap"; + + /** @hide */ @IntDef(prefix = { "AUTH_TYPE_" }, value = { AUTH_TYPE_NONE, @@ -1289,10 +1407,13 @@ public class ApnSetting implements Parcelable { } /** + * Converts the integer value of an APN type to the string version. * @param apnTypeBitmask bitmask of APN types. * @return comma delimited list of APN types. * @hide */ + @SystemApi + @NonNull public static String getApnTypesStringFromBitmask(int apnTypeBitmask) { List<String> types = new ArrayList<>(); for (Integer type : APN_TYPE_INT_MAP.keySet()) { diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index bc60d81cdc47..3f260eb7d80f 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -18,6 +18,7 @@ package android.telephony.ims; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; @@ -40,10 +41,11 @@ import java.util.ArrayList; import java.util.List; /** - * Parcelable object to handle IMS call profile. - * It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111. - * It provides the service and call type, the additional information related to the call. - * + * A Parcelable object to handle the IMS call profile, which provides the service, call type, and + * additional information related to the call. + * <p> + * See the following specifications for more information about this class: GSMA IR.92/IR.94, + * 3GPP TS 24.229/TS 26.114/TS26.111. * @hide */ @SystemApi @@ -151,12 +153,13 @@ public final class ImsCallProfile implements Parcelable { */ public static final String EXTRA_CONFERENCE_AVAIL = "conference_avail"; - // Extra string for internal use only. OEMs should not use - // this for packing extras. /** + * Extra key used to store a Bundle containing proprietary extras to send to the ImsService. + * Use {@link #getProprietaryCallExtras()} instead. * @hide */ - public static final String EXTRA_OEM_EXTRAS = "OemCallExtras"; + @TestApi + public static final String EXTRA_OEM_EXTRAS = "android.telephony.ims.extra.OEM_EXTRAS"; /** * Rule for originating identity (number) presentation, MO/MT. @@ -687,6 +690,18 @@ public final class ImsCallProfile implements Parcelable { return mCallExtras; } + /** + * Get the proprietary extras set for this ImsCallProfile. + * @return A {@link Bundle} containing proprietary call extras that were not set by the + * platform. + */ + public @Nullable Bundle getProprietaryCallExtras() { + if (mCallExtras == null) { + return null; + } + return mCallExtras.getBundle(EXTRA_OEM_EXTRAS); + } + public ImsStreamMediaProfile getMediaProfile() { return mMediaProfile; } diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java index 39af2e770882..cb3f0f92625e 100644 --- a/telephony/java/android/telephony/ims/ImsException.java +++ b/telephony/java/android/telephony/ims/ImsException.java @@ -30,10 +30,7 @@ import java.lang.annotation.RetentionPolicy; /** * This class defines an IMS-related exception that has been thrown while interacting with a * device or carrier provided ImsService implementation. - * @hide */ -@SystemApi -@TestApi public final class ImsException extends Exception { /** @@ -83,7 +80,10 @@ public final class ImsException extends Exception { /** * A new {@link ImsException} with an unspecified {@link ImsErrorCode} code. * @param message an optional message to detail the error condition more specifically. + * @hide */ + @SystemApi + @TestApi public ImsException(@Nullable String message) { super(getMessage(message, CODE_ERROR_UNSPECIFIED)); } @@ -91,7 +91,10 @@ public final class ImsException extends Exception { /** * A new {@link ImsException} that includes an {@link ImsErrorCode} error code. * @param message an optional message to detail the error condition more specifically. + * @hide */ + @SystemApi + @TestApi public ImsException(@Nullable String message, @ImsErrorCode int code) { super(getMessage(message, code)); mCode = code; @@ -102,7 +105,10 @@ public final class ImsException extends Exception { * {@link Throwable} that contains the original error that was thrown to lead to this Exception. * @param message an optional message to detail the error condition more specifically. * @param cause the {@link Throwable} that caused this {@link ImsException} to be created. + * @hide */ + @SystemApi + @TestApi public ImsException(@Nullable String message, @ImsErrorCode int code, @Nullable Throwable cause) { super(getMessage(message, code), cause); diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index 91514e9ebe28..5fdef8307d42 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -23,6 +23,8 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressAutoDoc; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Binder; @@ -55,10 +57,7 @@ import java.util.function.Consumer; * associated subscription. * * @see #createForSubscriptionId(int) - * @hide */ -@SystemApi -@TestApi public class ImsMmTelManager implements RegistrationManager { /** @@ -93,9 +92,11 @@ public class ImsMmTelManager implements RegistrationManager { * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback) * @see #unregisterImsRegistrationCallback(RegistrationCallback) * @deprecated Use {@link RegistrationManager.RegistrationCallback} instead. + * @hide */ // Do not add to this class, add to RegistrationManager.RegistrationCallback instead. @Deprecated + @SystemApi @TestApi public static class RegistrationCallback extends RegistrationManager.RegistrationCallback { /** @@ -140,7 +141,7 @@ public class ImsMmTelManager implements RegistrationManager { /** * Receives IMS capability status updates from the ImsService. This information is also - * available via the {@link #isAvailable(int, int)} method below. + * available via the {@see #isAvailable(int, int)} method below. * * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback) * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) @@ -193,7 +194,7 @@ public class ImsMmTelManager implements RegistrationManager { * If unavailable, the feature is not able to support the unavailable capability at this * time. * - * This information can also be queried using the {@link #isAvailable(int, int)} API. + * This information can also be queried using the {@see #isAvailable(int, int)} API. * * @param capabilities The new availability of the capabilities. */ @@ -221,8 +222,20 @@ public class ImsMmTelManager implements RegistrationManager { * * @param subId The ID of the subscription that this ImsMmTelManager will use. * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList() + * + * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE + * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges + * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). + * * @throws IllegalArgumentException if the subscription is invalid. + * */ + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE + }) + @SuppressLint("ManagerLookup") public static @NonNull ImsMmTelManager createForSubscriptionId(int subId) { if (!SubscriptionManager.isValidSubscriptionId(subId)) { throw new IllegalArgumentException("Invalid subscription ID"); @@ -261,8 +274,10 @@ public class ImsMmTelManager implements RegistrationManager { * reason. * @deprecated Use {@link RegistrationManager#registerImsRegistrationCallback(Executor, * RegistrationManager.RegistrationCallback)} instead. + * @hide */ @Deprecated + @SystemApi @TestApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor, @NonNull RegistrationCallback c) throws ImsException { @@ -287,9 +302,20 @@ public class ImsMmTelManager implements RegistrationManager { } } - /**{@inheritDoc}*/ + /** + * + * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE + * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges + * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). + * + * {@inheritDoc} + * + */ @Override - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor, @NonNull RegistrationManager.RegistrationCallback c) throws ImsException { if (c == null) { @@ -320,8 +346,10 @@ public class ImsMmTelManager implements RegistrationManager { * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) * @deprecated Use {@link #unregisterImsRegistrationCallback( * RegistrationManager.RegistrationCallback)}. + * @hide */ @Deprecated + @SystemApi @TestApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) { if (c == null) { @@ -334,9 +362,20 @@ public class ImsMmTelManager implements RegistrationManager { } } - /**{@inheritDoc}*/ + /** + * + * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE + * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges + * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). + * Access by profile owners is deprecated and will be removed in a future release. + * + *{@inheritDoc} + */ @Override - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void unregisterImsRegistrationCallback( @NonNull RegistrationManager.RegistrationCallback c) { if (c == null) { @@ -349,9 +388,13 @@ public class ImsMmTelManager implements RegistrationManager { } } - /**{@inheritDoc}*/ + /** + * {@inheritDoc} + * @hide + */ @Override - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi @TestApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull @CallbackExecutor Executor executor, @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) { if (stateCallback == null) { @@ -372,9 +415,19 @@ public class ImsMmTelManager implements RegistrationManager { } } - /**{@inheritDoc}*/ + /** + * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE + * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges + * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). + * Access by profile owners is deprecated and will be removed in a future release. + * + *{@inheritDoc} + */ @Override - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor, @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback) { @@ -400,12 +453,25 @@ public class ImsMmTelManager implements RegistrationManager { /** * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service * availability updates for the subscription specified in - * {@link #createForSubscriptionId(int)}. The method {@link #isAvailable(int, int)} + * {@link #createForSubscriptionId(int)}. The method {@see #isAvailable(int, int)} * can also be used to query this information at any time. * * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to * subscription changed events and call * {@link #unregisterMmTelCapabilityCallback(CapabilityCallback)} to clean up. + * <p>This API requires one of the following: + * <ul> + * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> + * <li>If the caller is the device or profile owner, the caller holds the + * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> + * <li>The caller has carrier privileges (see + * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any + * active subscription.</li> + * <li>The caller is the default SMS app for the device.</li> + * </ul> + * <p>The profile owner is an app that owns a managed profile on the device; for more details + * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. + * Access by profile owners is deprecated and will be removed in a future release. * * When the callback is registered, it will initiate the callback c to be called with the * current capabilities. @@ -421,7 +487,10 @@ public class ImsMmTelManager implements RegistrationManager { * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed * reason. */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor, @NonNull CapabilityCallback c) throws ImsException { if (c == null) { @@ -453,10 +522,27 @@ public class ImsMmTelManager implements RegistrationManager { * When the subscription associated with this callback is removed (SIM removed, ESIM swap, * etc...), this callback will automatically be removed. If this method is called for an * inactive subscription, it will result in a no-op. + * <p>This API requires one of the following: + * <ul> + * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> + * <li>If the caller is the device or profile owner, the caller holds the + * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> + * <li>The caller has carrier privileges (see + * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any + * active subscription.</li> + * <li>The caller is the default SMS app for the device.</li> + * </ul> + * <p>The profile owner is an app that owns a managed profile on the device; for more details + * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. + * Access by profile owners is deprecated and will be removed in a future release. + * * @param c The MmTel {@link CapabilityCallback} to be removed. * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) { if (c == null) { throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); @@ -478,6 +564,19 @@ public class ImsMmTelManager implements RegistrationManager { * <p> * Note: If the carrier configuration for advanced calling is not editable or hidden, this * method will always return the default value. + * <p>This API requires one of the following: + * <ul> + * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> + * <li>If the caller is the device or profile owner, the caller holds the + * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> + * <li>The caller has carrier privileges (see + * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any + * active subscription.</li> + * <li>The caller is the default SMS app for the device.</li> + * </ul> + * <p>The profile owner is an app that owns a managed profile on the device; for more details + * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. + * Access by profile owners is deprecated and will be removed in a future release. * * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL * @see android.telephony.CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL @@ -489,7 +588,10 @@ public class ImsMmTelManager implements RegistrationManager { * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user's setting for advanced calling is enabled, false otherwise. */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isAdvancedCallingSettingEnabled() { try { return getITelephony().isAdvancedCallingSettingEnabled(mSubId); @@ -527,8 +629,10 @@ public class ImsMmTelManager implements RegistrationManager { * @see #isAdvancedCallingSettingEnabled() * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. + * @hide */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + @SystemApi @TestApi public void setAdvancedCallingSettingEnabled(boolean isEnabled) { try { getITelephony().setAdvancedCallingSettingEnabled(mSubId, isEnabled); @@ -559,13 +663,15 @@ public class ImsMmTelManager implements RegistrationManager { * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} * @param capability The IMS MmTel capability to query, can be one of the following: * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO, + * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}, * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS} * @return {@code true} if the MmTel IMS capability is capable for this subscription, false * otherwise. + * @hide */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi @TestApi public boolean isCapable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) { try { @@ -586,12 +692,14 @@ public class ImsMmTelManager implements RegistrationManager { * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} * @param capability The IMS MmTel capability to query, can be one of the following: * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO, + * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}, * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS} * @return {@code true} if the MmTel IMS capability is available for this subscription, false * otherwise. + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) { @@ -616,7 +724,9 @@ public class ImsMmTelManager implements RegistrationManager { * capability is supported on this carrier network for the transport specified. * @throws ImsException if the subscription is no longer valid or the IMS service is not * available. + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability, @AccessNetworkConstants.TransportType int transportType, @@ -645,12 +755,32 @@ public class ImsMmTelManager implements RegistrationManager { /** * The user's setting for whether or not they have enabled the "Video Calling" setting. * + * <p> + * Note: If the carrier configuration for advanced calling is not editable or hidden, this + * method will always return the default value. + * <p>This API requires one of the following: + * <ul> + * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> + * <li>If the caller is the device or profile owner, the caller holds the + * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> + * <li>The caller has carrier privileges (see + * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any + * active subscription.</li> + * <li>The caller is the default SMS app for the device.</li> + * </ul> + * <p>The profile owner is an app that owns a managed profile on the device; for more details + * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. + * Access by profile owners is deprecated and will be removed in a future release. + * * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user’s “Video Calling” setting is currently enabled. * @see #setVtSettingEnabled(boolean) */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). public boolean isVtSettingEnabled() { try { return getITelephony().isVtSettingEnabled(mSubId); @@ -672,7 +802,9 @@ public class ImsMmTelManager implements RegistrationManager { * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @see #isVtSettingEnabled() + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean isEnabled) { try { @@ -692,11 +824,28 @@ public class ImsMmTelManager implements RegistrationManager { /** * @return true if the user's setting for Voice over WiFi is enabled and false if it is not. * + * <p>This API requires one of the following: + * <ul> + * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> + * <li>If the caller is the device or profile owner, the caller holds the + * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> + * <li>The caller has carrier privileges (see + * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any + * active subscription.</li> + * <li>The caller is the default SMS app for the device.</li> + * </ul> + * <p>The profile owner is an app that owns a managed profile on the device; for more details + * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. + * Access by profile owners is deprecated and will be removed in a future release. + * * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @see #setVoWiFiSettingEnabled(boolean) */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVoWiFiSettingEnabled() { try { return getITelephony().isVoWiFiSettingEnabled(mSubId); @@ -719,7 +868,9 @@ public class ImsMmTelManager implements RegistrationManager { * active (SIM is not inserted, ESIM inactive) or invalid. * @param isEnabled true if the user's setting for Voice over WiFi is enabled, false otherwise= * @see #isVoWiFiSettingEnabled() + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean isEnabled) { try { @@ -739,13 +890,30 @@ public class ImsMmTelManager implements RegistrationManager { /** * Returns the user's voice over WiFi roaming setting associated with the current subscription. * + * <p>This API requires one of the following: + * <ul> + * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> + * <li>If the caller is the device or profile owner, the caller holds the + * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> + * <li>The caller has carrier privileges (see + * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any + * active subscription.</li> + * <li>The caller is the default SMS app for the device.</li> + * </ul> + * <p>The profile owner is an app that owns a managed profile on the device; for more details + * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. + * Access by profile owners is deprecated and will be removed in a future release. + * * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user's setting for Voice over WiFi while roaming is enabled, false * if disabled. * @see #setVoWiFiRoamingSettingEnabled(boolean) */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVoWiFiRoamingSettingEnabled() { try { return getITelephony().isVoWiFiRoamingSettingEnabled(mSubId); @@ -769,7 +937,9 @@ public class ImsMmTelManager implements RegistrationManager { * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @see #isVoWiFiRoamingSettingEnabled() + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) { try { @@ -799,7 +969,9 @@ public class ImsMmTelManager implements RegistrationManager { * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @see #setVoWiFiSettingEnabled(boolean) + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean isCapable, int mode) { try { @@ -819,6 +991,20 @@ public class ImsMmTelManager implements RegistrationManager { /** * Returns the user's voice over WiFi Roaming mode setting associated with the device. * + * <p>This API requires one of the following: + * <ul> + * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> + * <li>If the caller is the device or profile owner, the caller holds the + * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> + * <li>The caller has carrier privileges (see + * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any + * active subscription.</li> + * <li>The caller is the default SMS app for the device.</li> + * </ul> + * <p>The profile owner is an app that owns a managed profile on the device; for more details + * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. + * Access by profile owners is deprecated and will be removed in a future release. + * * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @return The Voice over WiFi Mode preference set by the user, which can be one of the @@ -828,7 +1014,10 @@ public class ImsMmTelManager implements RegistrationManager { * - {@link #WIFI_MODE_WIFI_PREFERRED} * @see #setVoWiFiSettingEnabled(boolean) */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public @WiFiCallingMode int getVoWiFiModeSetting() { try { return getITelephony().getVoWiFiModeSetting(mSubId); @@ -854,7 +1043,9 @@ public class ImsMmTelManager implements RegistrationManager { * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @see #getVoWiFiModeSetting() + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(@WiFiCallingMode int mode) { try { @@ -883,7 +1074,9 @@ public class ImsMmTelManager implements RegistrationManager { * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @see #setVoWiFiRoamingSettingEnabled(boolean) + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @WiFiCallingMode int getVoWiFiRoamingModeSetting() { try { @@ -912,7 +1105,9 @@ public class ImsMmTelManager implements RegistrationManager { * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @see #getVoWiFiRoamingModeSetting() + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(@WiFiCallingMode int mode) { try { @@ -939,7 +1134,9 @@ public class ImsMmTelManager implements RegistrationManager { * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @param isEnabled if true RTT should be enabled during calls made on this subscription. + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean isEnabled) { try { @@ -959,12 +1156,29 @@ public class ImsMmTelManager implements RegistrationManager { /** * @return true if TTY over VoLTE is supported * + * <p>This API requires one of the following: + * <ul> + * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li> + * <li>If the caller is the device or profile owner, the caller holds the + * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li> + * <li>The caller has carrier privileges (see + * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any + * active subscription.</li> + * <li>The caller is the default SMS app for the device.</li> + * </ul> + * <p>The profile owner is an app that owns a managed profile on the device; for more details + * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. + * Access by profile owners is deprecated and will be removed in a future release. + * * @throws IllegalArgumentException if the subscription associated with this operation is not * active (SIM is not inserted, ESIM inactive) or invalid. * @see android.telecom.TelecomManager#getCurrentTtyMode * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isTtyOverVolteEnabled() { try { return getITelephony().isTtyOverVolteEnabled(mSubId); @@ -991,7 +1205,9 @@ public class ImsMmTelManager implements RegistrationManager { * specified when the service state has been retrieved from the IMS service. * @throws ImsException if the IMS service associated with this subscription is not available or * the IMS service is not available. + * @hide */ + @SystemApi @TestApi @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull @CallbackExecutor Executor executor, @NonNull @ImsFeature.ImsState Consumer<Integer> callback) throws ImsException { diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java index ca081ec1ea51..5c86ba732701 100644 --- a/telephony/java/android/telephony/ims/RegistrationManager.java +++ b/telephony/java/android/telephony/ims/RegistrationManager.java @@ -22,8 +22,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.annotation.TestApi; import android.net.Uri; import android.os.Binder; import android.telephony.AccessNetworkConstants; @@ -41,10 +39,7 @@ import java.util.function.Consumer; /** * Manages IMS Service registration state for associated {@link ImsFeature}s. - * @hide */ -@SystemApi -@TestApi public interface RegistrationManager { /** @@ -157,7 +152,6 @@ public interface RegistrationManager { } } - @Override public void onSubscriberAssociatedUriChanged(Uri[] uris) { if (mLocalCallback == null) return; @@ -246,7 +240,11 @@ public interface RegistrationManager { /** * Registers a {@link RegistrationCallback} with the system. Use - * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed + * @param executor The {@link Executor} that will be used to call the IMS registration state + * callback. + * @param c A callback called on the supplied {@link Executor} that will contain the + * registration state of the IMS service, which will be one of the + * {@see SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. * * When the callback is registered, it will initiate the callback c to be called with the @@ -296,10 +294,10 @@ public interface RegistrationManager { * Gets the Transport Type associated with the current IMS registration. * @param executor The {@link Executor} that will be used to call the transportTypeCallback. * @param transportTypeCallback The transport type associated with the current IMS registration, - * which will be one of following: - * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN}, - * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or - * {@link AccessNetworkConstants#TRANSPORT_TYPE_INVALID}. + * which will be one of following: + * {@see AccessNetworkConstants#TRANSPORT_TYPE_WWAN}, + * {@see AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or + * {@see AccessNetworkConstants#TRANSPORT_TYPE_INVALID}. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) void getRegistrationTransportType( diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index 1004e1b4acb7..e5779b315c93 100644 --- a/telephony/java/android/telephony/ims/feature/ImsFeature.java +++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java @@ -60,15 +60,21 @@ public abstract class ImsFeature { * This feature supports emergency calling over MMTEL. If defined, the framework will try to * place an emergency call over IMS first. If it is not defined, the framework will only use * CSFB for emergency calling. + * @hide */ + @SystemApi @TestApi public static final int FEATURE_EMERGENCY_MMTEL = 0; /** * This feature supports the MMTEL feature. + * @hide */ + @SystemApi @TestApi public static final int FEATURE_MMTEL = 1; /** * This feature supports the RCS feature. + * @hide */ + @SystemApi @TestApi public static final int FEATURE_RCS = 2; /** * Total number of features defined @@ -116,18 +122,24 @@ public abstract class ImsFeature { * This {@link ImsFeature}'s state is unavailable and should not be communicated with. This will * remove all bindings back to the framework. Any attempt to communicate with the framework * during this time will result in an {@link IllegalStateException}. + * @hide */ + @SystemApi @TestApi public static final int STATE_UNAVAILABLE = 0; /** * This {@link ImsFeature} state is initializing and should not be communicated with. This will * remove all bindings back to the framework. Any attempt to communicate with the framework * during this time will result in an {@link IllegalStateException}. + * @hide */ + @SystemApi @TestApi public static final int STATE_INITIALIZING = 1; /** * This {@link ImsFeature} is ready for communication. Do not attempt to call framework methods - * until {@link #onFeatureReady()} is called. + * until {@see #onFeatureReady()} is called. + * @hide */ + @SystemApi @TestApi public static final int STATE_READY = 2; /** @@ -155,11 +167,15 @@ public abstract class ImsFeature { /** * The capability was unable to be changed. + * @hide */ + @SystemApi @TestApi public static final int CAPABILITY_ERROR_GENERIC = -1; /** * The capability was able to be changed. + * @hide */ + @SystemApi @TestApi public static final int CAPABILITY_SUCCESS = 0; /** @@ -331,7 +347,9 @@ public abstract class ImsFeature { * * @see SubscriptionManager#getSubscriptionIds(int) for more information on getting the * subscription IDs associated with this slot. + * @hide */ + @SystemApi @TestApi public final int getSlotIndex() { return mSlotId; } @@ -339,7 +357,9 @@ public abstract class ImsFeature { /** * @return The current state of the ImsFeature, set previously by {@link #setFeatureState(int)} * or {@link #STATE_UNAVAILABLE} if it has not been updated yet. + * @hide */ + @SystemApi @TestApi public @ImsState int getFeatureState() { synchronized (mLock) { return mState; @@ -351,7 +371,9 @@ public abstract class ImsFeature { * stop communication, depending on the state sent. * @param state The ImsFeature's state, defined as {@link #STATE_UNAVAILABLE}, * {@link #STATE_INITIALIZING}, or {@link #STATE_READY}. + * @hide */ + @SystemApi @TestApi public final void setFeatureState(@ImsState int state) { synchronized (mLock) { if (mState != state) { diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index 56c87710244c..0d5a979e5894 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -52,14 +52,18 @@ import java.lang.annotation.RetentionPolicy; * * Any class wishing to use MmTelFeature should extend this class and implement all methods that the * service supports. - * @hide */ -@SystemApi -@TestApi public class MmTelFeature extends ImsFeature { private static final String LOG_TAG = "MmTelFeature"; + /** + * @hide + */ + @SystemApi @TestApi + public MmTelFeature() { + } + private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() { @Override @@ -215,11 +219,11 @@ public class MmTelFeature extends ImsFeature { * {@link MmTelCapabilities#CAPABILITY_TYPE_SMS}. * * The capabilities of this MmTelFeature will be set by the framework and can be queried with - * {@link #queryCapabilityStatus()}. + * {@see #queryCapabilityStatus()}. * * This MmTelFeature can then return the status of each of these capabilities (enabled or not) - * by sending a {@link #notifyCapabilitiesStatusChanged} callback to the framework. The current - * status can also be queried using {@link #queryCapabilityStatus()}. + * by sending a {@see #notifyCapabilitiesStatusChanged} callback to the framework. The current + * status can also be queried using {@see #queryCapabilityStatus()}. * @see #isCapable(int) */ public static class MmTelCapabilities extends Capabilities { @@ -228,13 +232,18 @@ public class MmTelFeature extends ImsFeature { * Create a new empty {@link MmTelCapabilities} instance. * @see #addCapabilities(int) * @see #removeCapabilities(int) + * @hide */ + @SystemApi @TestApi public MmTelCapabilities() { super(); } - /**@deprecated Use {@link MmTelCapabilities} to construct a new instance instead.*/ + /**@deprecated Use {@link MmTelCapabilities} to construct a new instance instead. + * @hide + */ @Deprecated + @SystemApi @TestApi public MmTelCapabilities(Capabilities c) { mCapabilities = c.mCapabilities; } @@ -243,11 +252,17 @@ public class MmTelFeature extends ImsFeature { * Create a new {link @MmTelCapabilities} instance with the provided capabilities. * @param capabilities The capabilities that are supported for MmTel in the form of a * bitfield. + * @hide */ + @SystemApi @TestApi public MmTelCapabilities(@MmTelCapability int capabilities) { super(capabilities); } + /** + * @hide + */ + @SystemApi @TestApi @IntDef(flag = true, value = { CAPABILITY_TYPE_VOICE, @@ -278,23 +293,39 @@ public class MmTelFeature extends ImsFeature { */ public static final int CAPABILITY_TYPE_SMS = 1 << 3; + /** + * @hide + */ @Override + @SystemApi @TestApi public final void addCapabilities(@MmTelCapability int capabilities) { super.addCapabilities(capabilities); } + /** + * @hide + */ @Override + @SystemApi @TestApi public final void removeCapabilities(@MmTelCapability int capability) { super.removeCapabilities(capability); } + /** + * @hide + */ @Override + @SystemApi @TestApi public final boolean isCapable(@MmTelCapability int capabilities) { return super.isCapable(capabilities); } + /** + * @hide + */ @NonNull @Override + @SystemApi @TestApi public String toString() { StringBuilder builder = new StringBuilder("MmTel Capabilities - ["); builder.append("Voice: "); @@ -319,8 +350,10 @@ public class MmTelFeature extends ImsFeature { /** * Called when the IMS provider receives an incoming call. * @param c The {@link ImsCallSession} associated with the new call. + * @hide */ @Override + @SystemApi @TestApi public void onIncomingCall(IImsCallSession c, Bundle extras) { } @@ -329,8 +362,10 @@ public class MmTelFeature extends ImsFeature { * Called when the IMS provider implicitly rejects an incoming call during setup. * @param callProfile An {@link ImsCallProfile} with the call details. * @param reason The {@link ImsReasonInfo} reason for call rejection. + * @hide */ @Override + @SystemApi @TestApi public void onRejectedCall(ImsCallProfile callProfile, ImsReasonInfo reason) { } @@ -338,8 +373,10 @@ public class MmTelFeature extends ImsFeature { /** * Updates the Listener when the voice message count for IMS has changed. * @param count an integer representing the new message count. + * @hide */ @Override + @SystemApi @TestApi public void onVoiceMessageCountUpdate(int count) { } @@ -348,14 +385,22 @@ public class MmTelFeature extends ImsFeature { /** * To be returned by {@link #shouldProcessCall(String[])} when the ImsService should process the * outgoing call as IMS. + * @hide */ + @SystemApi @TestApi public static final int PROCESS_CALL_IMS = 0; /** * To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should * not process the outgoing call as IMS and should instead use circuit switch. + * @hide */ + @SystemApi @TestApi public static final int PROCESS_CALL_CSFB = 1; + /** + * @hide + */ + @SystemApi @TestApi @IntDef(flag = true, value = { PROCESS_CALL_IMS, @@ -368,7 +413,9 @@ public class MmTelFeature extends ImsFeature { * If the flag is present and true, it indicates that the incoming call is for USSD. * <p> * This is an optional boolean flag. + * @hide */ + @SystemApi @TestApi public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; /** @@ -379,7 +426,9 @@ public class MmTelFeature extends ImsFeature { * certain situations. * <p> * This is an optional boolean flag. + * @hide */ + @SystemApi @TestApi public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; @@ -388,6 +437,7 @@ public class MmTelFeature extends ImsFeature { /** * @param listener A {@link Listener} used when the MmTelFeature receives an incoming call and * notifies the framework. + * @hide */ private void setListener(IImsMmTelListener listener) { synchronized (mLock) { @@ -406,9 +456,11 @@ public class MmTelFeature extends ImsFeature { * Should be a subset of the capabilities that are enabled by the framework in * {@link #changeEnabledCapabilities}. * @return A copy of the current MmTelFeature capability status. + * @hide */ @Override - public final MmTelCapabilities queryCapabilityStatus() { + @SystemApi @TestApi + public @NonNull final MmTelCapabilities queryCapabilityStatus() { return new MmTelCapabilities(super.queryCapabilityStatus()); } @@ -420,7 +472,9 @@ public class MmTelFeature extends ImsFeature { * the status of that capability is disabled. This can happen if the network does not currently * support the capability that is enabled. A capability that is disabled by the framework (via * {@link #changeEnabledCapabilities}) should also show the status as disabled. + * @hide */ + @SystemApi @TestApi public final void notifyCapabilitiesStatusChanged(@NonNull MmTelCapabilities c) { if (c == null) { throw new IllegalArgumentException("MmTelCapabilities must be non-null!"); @@ -433,7 +487,9 @@ public class MmTelFeature extends ImsFeature { * @param c The {@link ImsCallSessionImplBase} of the new incoming call. * @param extras A bundle containing extra parameters related to the call. See * {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above. + * @hide */ + @SystemApi @TestApi public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c, @NonNull Bundle extras) { if (c == null || extras == null) { @@ -458,7 +514,9 @@ public class MmTelFeature extends ImsFeature { * @param callProfile The {@link ImsCallProfile} IMS call profile with details. * This can be null if no call information is available for the rejected call. * @param reason The {@link ImsReasonInfo} call rejection reason. + * * @hide */ + @SystemApi @TestApi public final void notifyRejectedCall(@NonNull ImsCallProfile callProfile, @NonNull ImsReasonInfo reason) { if (callProfile == null || reason == null) { @@ -497,7 +555,9 @@ public class MmTelFeature extends ImsFeature { /** * Notify the framework of a change in the Voice Message count. * @link count the new Voice Message count. + * @hide */ + @SystemApi @TestApi public final void notifyVoiceMessageCountUpdate(int count) { synchronized (mLock) { if (mListener == null) { @@ -518,8 +578,10 @@ public class MmTelFeature extends ImsFeature { * status for capability A. * @param capability The capability that we are querying the configuration for. * @return true if the capability is enabled, false otherwise. + * @hide */ @Override + @SystemApi @TestApi public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { // Base implementation - Override to provide functionality @@ -537,8 +599,10 @@ public class MmTelFeature extends ImsFeature { * Enabling/Disabling a capability here indicates that the capability should be registered or * deregistered (depending on the capability change) and become available or unavailable to * the framework. + * * @hide */ @Override + @SystemApi @TestApi public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request, @NonNull CapabilityCallbackProxy c) { // Base implementation, no-op @@ -561,7 +625,9 @@ public class MmTelFeature extends ImsFeature { * {@link ImsCallProfile#CALL_TYPE_VS_TX} * {@link ImsCallProfile#CALL_TYPE_VS_RX} * @return a {@link ImsCallProfile} object + * @hide */ + @SystemApi @TestApi public @Nullable ImsCallProfile createCallProfile(int callSessionType, int callType) { // Base Implementation - Should be overridden return null; @@ -582,7 +648,9 @@ public class MmTelFeature extends ImsFeature { * {@link ImsCallSession} directly. * * @param profile a call profile to make the call + * @hide */ + @SystemApi @TestApi public @Nullable ImsCallSessionImplBase createCallSession(@NonNull ImsCallProfile profile) { // Base Implementation - Should be overridden return null; @@ -599,7 +667,9 @@ public class MmTelFeature extends ImsFeature { * call as a conference. * @return a {@link ProcessCallResult} to the framework, which will be used to determine if the * call will be placed over IMS or via CSFB. + * @hide */ + @SystemApi @TestApi public @ProcessCallResult int shouldProcessCall(@NonNull String[] numbers) { return PROCESS_CALL_IMS; } @@ -632,7 +702,9 @@ public class MmTelFeature extends ImsFeature { /** * @return The {@link ImsUtImplBase} Ut interface implementation for the supplementary service * configuration. + * @hide */ + @SystemApi @TestApi public @NonNull ImsUtImplBase getUt() { // Base Implementation - Should be overridden return new ImsUtImplBase(); @@ -641,7 +713,9 @@ public class MmTelFeature extends ImsFeature { /** * @return The {@link ImsEcbmImplBase} Emergency call-back mode interface for emergency VoLTE * calls that support it. + * @hide */ + @SystemApi @TestApi public @NonNull ImsEcbmImplBase getEcbm() { // Base Implementation - Should be overridden return new ImsEcbmImplBase(); @@ -650,7 +724,9 @@ public class MmTelFeature extends ImsFeature { /** * @return The {@link ImsMultiEndpointImplBase} implementation for implementing Dialog event * package processing for multi-endpoint. + * @hide */ + @SystemApi @TestApi public @NonNull ImsMultiEndpointImplBase getMultiEndpoint() { // Base Implementation - Should be overridden return new ImsMultiEndpointImplBase(); @@ -676,7 +752,9 @@ public class MmTelFeature extends ImsFeature { * // Remote side is dead * } * } + * @hide */ + @SystemApi @TestApi public void setUiTtyMode(int mode, @Nullable Message onCompleteMessage) { // Base Implementation - Should be overridden } @@ -710,7 +788,9 @@ public class MmTelFeature extends ImsFeature { * * @return an instance of {@link ImsSmsImplBase} which should be implemented by the IMS * Provider. + * @hide */ + @SystemApi @TestApi public @NonNull ImsSmsImplBase getSmsImplementation() { return new ImsSmsImplBase(); } @@ -719,14 +799,22 @@ public class MmTelFeature extends ImsFeature { return getSmsImplementation().getSmsFormat(); } - /**{@inheritDoc}*/ + /** + * {@inheritDoc} + * @hide + */ @Override + @SystemApi @TestApi public void onFeatureRemoved() { // Base Implementation - Should be overridden } - /**{@inheritDoc}*/ + /** + * {@inheritDoc} + * @hide + */ @Override + @SystemApi @TestApi public void onFeatureReady() { // Base Implementation - Should be overridden } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index a8e76b9d7902..7add741e84fa 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -922,6 +922,23 @@ interface ITelephony { int subId, in OperatorInfo operatorInfo, boolean persisSelection); /** + * Get the allowed network types that store in the telephony provider. + * + * @param subId the id of the subscription. + * @return allowedNetworkTypes the allowed network types. + */ + long getAllowedNetworkTypes(int subId); + + /** + * Set the allowed network types. + * + * @param subId the id of the subscription. + * @param allowedNetworkTypes the allowed network types. + * @return true on success; false on any failure. + */ + boolean setAllowedNetworkTypes(int subId, long allowedNetworkTypes); + + /** * Set the preferred network type. * Used for device configuration by some CDMA operators. * @@ -2147,4 +2164,10 @@ interface ITelephony { * Notify Rcs auto config received. */ void notifyRcsAutoConfigurationReceived(int subId, in byte[] config, boolean isCompressed); + + boolean isIccLockEnabled(int subId); + + int setIccLockEnabled(int subId, boolean enabled, String password); + + int changeIccLockPassword(int subId, String oldPassword, String newPassword); } diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java index db8c84560282..4d677545bc39 100644 --- a/telephony/java/com/android/internal/telephony/PhoneConstants.java +++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java @@ -16,6 +16,7 @@ package com.android.internal.telephony; import android.compat.annotation.UnsupportedAppUsage; +import android.telephony.data.ApnSetting; /** * @hide @@ -125,32 +126,32 @@ public class PhoneConstants { * APN_TYPE_ALL is a special type to indicate that this APN entry can * service all data connections. */ - public static final String APN_TYPE_ALL = "*"; + public static final String APN_TYPE_ALL = ApnSetting.TYPE_ALL_STRING; /** APN type for default data traffic */ - public static final String APN_TYPE_DEFAULT = "default"; + public static final String APN_TYPE_DEFAULT = ApnSetting.TYPE_DEFAULT_STRING; /** APN type for MMS traffic */ - public static final String APN_TYPE_MMS = "mms"; + public static final String APN_TYPE_MMS = ApnSetting.TYPE_MMS_STRING; /** APN type for SUPL assisted GPS */ - public static final String APN_TYPE_SUPL = "supl"; + public static final String APN_TYPE_SUPL = ApnSetting.TYPE_SUPL_STRING; /** APN type for DUN traffic */ - public static final String APN_TYPE_DUN = "dun"; + public static final String APN_TYPE_DUN = ApnSetting.TYPE_DUN_STRING; /** APN type for HiPri traffic */ - public static final String APN_TYPE_HIPRI = "hipri"; + public static final String APN_TYPE_HIPRI = ApnSetting.TYPE_HIPRI_STRING; /** APN type for FOTA */ - public static final String APN_TYPE_FOTA = "fota"; + public static final String APN_TYPE_FOTA = ApnSetting.TYPE_FOTA_STRING; /** APN type for IMS */ - public static final String APN_TYPE_IMS = "ims"; + public static final String APN_TYPE_IMS = ApnSetting.TYPE_IMS_STRING; /** APN type for CBS */ - public static final String APN_TYPE_CBS = "cbs"; + public static final String APN_TYPE_CBS = ApnSetting.TYPE_CBS_STRING; /** APN type for IA Initial Attach APN */ - public static final String APN_TYPE_IA = "ia"; + public static final String APN_TYPE_IA = ApnSetting.TYPE_IA_STRING; /** APN type for Emergency PDN. This is not an IA apn, but is used * for access to carrier services in an emergency call situation. */ - public static final String APN_TYPE_EMERGENCY = "emergency"; + public static final String APN_TYPE_EMERGENCY = ApnSetting.TYPE_EMERGENCY_STRING; /** APN type for Mission Critical Services */ - public static final String APN_TYPE_MCX = "mcx"; + public static final String APN_TYPE_MCX = ApnSetting.TYPE_MCX_STRING; /** APN type for XCAP */ - public static final String APN_TYPE_XCAP = "xcap"; + public static final String APN_TYPE_XCAP = ApnSetting.TYPE_XCAP_STRING; /** Array of all APN types */ public static final String[] APN_TYPES = {APN_TYPE_DEFAULT, APN_TYPE_MMS, diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index 1c6920986318..a35fb407bca9 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -222,7 +222,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { @Override public Network getNetwork() { - return mNetworkAgent.network; + return mNetworkAgent.getNetwork(); } public void expectPreventReconnectReceived(long timeoutMs) { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 1901a1db633b..4e2933472706 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -575,7 +575,7 @@ public class ConnectivityServiceTest { } }; - assertEquals(na.network.netId, nmNetworkCaptor.getValue().netId); + assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId); mNmCallbacks = nmCbCaptor.getValue(); mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor); diff --git a/wifi/java/android/net/wifi/ILocalOnlyHotspotCallback.aidl b/wifi/java/android/net/wifi/ILocalOnlyHotspotCallback.aidl index b83b594c8cb9..b567f29660a7 100644 --- a/wifi/java/android/net/wifi/ILocalOnlyHotspotCallback.aidl +++ b/wifi/java/android/net/wifi/ILocalOnlyHotspotCallback.aidl @@ -16,7 +16,7 @@ package android.net.wifi; -import android.net.wifi.WifiConfiguration; +import android.net.wifi.SoftApConfiguration; /** * Communicates LOHS status back to the application process. @@ -24,7 +24,7 @@ import android.net.wifi.WifiConfiguration; * @hide */ oneway interface ILocalOnlyHotspotCallback { - void onHotspotStarted(in WifiConfiguration config); + void onHotspotStarted(in SoftApConfiguration config); void onHotspotStopped(); void onHotspotFailed(int reason); } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 5a98ac86e783..dafb4de62f3c 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -117,6 +117,8 @@ interface IWifiManager boolean is6GHzBandSupported(); + boolean isWifiStandardSupported(int standard); + boolean needs5GHzToAnyApBandConversion(); DhcpInfo getDhcpInfo(); diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java index a77d30a18817..c02f8c3a8cd1 100644 --- a/wifi/java/android/net/wifi/SoftApConfiguration.java +++ b/wifi/java/android/net/wifi/SoftApConfiguration.java @@ -24,6 +24,7 @@ import android.net.MacAddress; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; @@ -36,7 +37,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Objects; -import java.util.concurrent.Executor; /** * Configuration for a soft access point (a.k.a. Soft AP, SAP, Hotspot). @@ -45,22 +45,23 @@ import java.util.concurrent.Executor; * framework how it should configure a hotspot. * * System apps can use this to configure a tethered hotspot using - * {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} and - * {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)} + * {@code WifiManager#startTetheredHotspot(SoftApConfiguration)} and + * {@code WifiManager#setSoftApConfiguration(SoftApConfiguration)} * or local-only hotspot using - * {@link WifiManager#startLocalOnlyHotspot(SoftApConfiguration, Executor, + * {@code WifiManager#startLocalOnlyHotspot(SoftApConfiguration, Executor, * WifiManager.LocalOnlyHotspotCallback)}. * * Instances of this class are immutable; use {@link SoftApConfiguration.Builder} and its methods to * create a new instance. * - * @hide */ -@SystemApi public final class SoftApConfiguration implements Parcelable { + private static final String TAG = "SoftApConfiguration"; + @VisibleForTesting static final int PSK_MIN_LEN = 8; + @VisibleForTesting static final int PSK_MAX_LEN = 63; @@ -207,22 +208,24 @@ public final class SoftApConfiguration implements Parcelable { private final int mShutdownTimeoutMillis; /** - * Security types we support. + * THe definition of security type OPEN. */ - /** @hide */ - @SystemApi public static final int SECURITY_TYPE_OPEN = 0; - /** @hide */ - @SystemApi + + /** + * The definition of security type WPA2-PSK. + */ public static final int SECURITY_TYPE_WPA2_PSK = 1; - /** @hide */ - @SystemApi + /** + * The definition of security type WPA3-SAE Transition mode. + */ public static final int SECURITY_TYPE_WPA3_SAE_TRANSITION = 2; - /** @hide */ - @SystemApi + /** + * The definition of security type WPA3-SAE. + */ public static final int SECURITY_TYPE_WPA3_SAE = 3; /** @hide */ @@ -346,7 +349,7 @@ public final class SoftApConfiguration implements Parcelable { /** * Return String set to be the SSID for the AP. - * {@link #setSsid(String)}. + * {@link Builder#setSsid(String)}. */ @Nullable public String getSsid() { @@ -364,7 +367,7 @@ public final class SoftApConfiguration implements Parcelable { /** * Returns String set to be passphrase for current AP. - * {@link #setPassphrase(String, @SecurityType int)}. + * {@link Builder#setPassphrase(String, int)}. */ @Nullable public String getPassphrase() { @@ -383,7 +386,10 @@ public final class SoftApConfiguration implements Parcelable { /** * Returns {@link BandType} set to be the band for the AP. * {@link Builder#setBand(@BandType int)}. + * + * @hide */ + @SystemApi public @BandType int getBand() { return mBand; } @@ -391,7 +397,10 @@ public final class SoftApConfiguration implements Parcelable { /** * Returns Integer set to be the channel for the AP. * {@link Builder#setChannel(int)}. + * + * @hide */ + @SystemApi public int getChannel() { return mChannel; } @@ -408,7 +417,10 @@ public final class SoftApConfiguration implements Parcelable { /** * Returns the maximum number of clients that can associate to the AP. * {@link Builder#setMaxNumberOfClients(int)}. + * + * @hide */ + @SystemApi public int getMaxNumberOfClients() { return mMaxNumberOfClients; } @@ -417,7 +429,10 @@ public final class SoftApConfiguration implements Parcelable { * Returns the shutdown timeout in milliseconds. * The Soft AP will shutdown when there are no devices associated to it for * the timeout duration. See {@link Builder#setShutdownTimeoutMillis(int)}. + * + * @hide */ + @SystemApi public int getShutdownTimeoutMillis() { return mShutdownTimeoutMillis; } @@ -426,7 +441,10 @@ public final class SoftApConfiguration implements Parcelable { * Returns a flag indicating whether clients need to be pre-approved by the user. * (true: authorization required) or not (false: not required). * {@link Builder#enableClientControlByUser(Boolean)}. + * + * @hide */ + @SystemApi public boolean isClientControlByUserEnabled() { return mClientControlByUser; } @@ -435,8 +453,11 @@ public final class SoftApConfiguration implements Parcelable { * Returns List of clients which aren't allowed to associate to the AP. * * Clients are configured using {@link Builder#setClientList(List, List)} + * + * @hide */ @NonNull + @SystemApi public List<MacAddress> getBlockedClientList() { return mBlockedClientList; } @@ -444,19 +465,77 @@ public final class SoftApConfiguration implements Parcelable { /** * List of clients which are allowed to associate to the AP. * Clients are configured using {@link Builder#setClientList(List, List)} + * + * @hide */ @NonNull + @SystemApi public List<MacAddress> getAllowedClientList() { return mAllowedClientList; } /** + * Returns a {@link WifiConfiguration} representation of this {@link SoftApConfiguration}. + * Note that SoftApConfiguration may contain configuration which is cannot be represented + * by the legacy WifiConfiguration, in such cases a null will be returned. + * + * <li> SoftAp band in {@link WifiConfiguration.apBand} only supports + * 2GHz, 5GHz, 2GHz+5GHz bands, so conversion is limited to these bands. </li> + * + * <li> SoftAp security type in {@link WifiConfiguration.KeyMgmt} only supports + * NONE, WPA2_PSK, so conversion is limited to these security type.</li> + * @hide + */ + @Nullable + @SystemApi + public WifiConfiguration toWifiConfiguration() { + WifiConfiguration wifiConfig = new WifiConfiguration(); + wifiConfig.SSID = mSsid; + if (mBssid != null) { + wifiConfig.BSSID = mBssid.toString(); + } + wifiConfig.preSharedKey = mPassphrase; + wifiConfig.hiddenSSID = mHiddenSsid; + wifiConfig.apChannel = mChannel; + switch (mSecurityType) { + case SECURITY_TYPE_OPEN: + wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + break; + case SECURITY_TYPE_WPA2_PSK: + wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK); + break; + default: + Log.e(TAG, "Convert fail, unsupported security type :" + mSecurityType); + return null; + } + + switch (mBand) { + case BAND_2GHZ: + wifiConfig.apBand = WifiConfiguration.AP_BAND_2GHZ; + break; + case BAND_5GHZ: + wifiConfig.apBand = WifiConfiguration.AP_BAND_5GHZ; + break; + case BAND_ANY: + wifiConfig.apBand = WifiConfiguration.AP_BAND_ANY; + break; + default: + Log.e(TAG, "Convert fail, unsupported band setting :" + mBand); + return null; + } + return wifiConfig; + } + + /** * Builds a {@link SoftApConfiguration}, which allows an app to configure various aspects of a * Soft AP. * * All fields are optional. By default, SSID and BSSID are automatically chosen by the * framework, and an open network is created. + * + * @hide */ + @SystemApi public static final class Builder { private String mSsid; private MacAddress mBssid; diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index b2fbb401dde5..e84369fb7ba1 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -938,8 +938,10 @@ public class WifiConfiguration implements Parcelable { } /** - * Indicate whther the network is trusted or not. Networks are considered trusted + * Indicate whether the network is trusted or not. Networks are considered trusted * if the user explicitly allowed this network connection. + * This bit can be used by suggestion network, see + * {@link WifiNetworkSuggestion.Builder#setUnTrusted(boolean)} * @hide */ public boolean trusted; diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 64d4eafe71bf..c35303da9056 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -193,6 +193,14 @@ public class WifiManager { */ public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5; + /** + * Reason code if one or more of the network suggestions added is not allowed. + * + * This error may be caused by suggestion is using SIM-based encryption method, but calling app + * is not carrier privileged. + */ + public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED = 6; + /** @hide */ @IntDef(prefix = { "STATUS_NETWORK_SUGGESTIONS_" }, value = { STATUS_NETWORK_SUGGESTIONS_SUCCESS, @@ -201,6 +209,7 @@ public class WifiManager { STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE, STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP, STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, + STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED, }) @Retention(RetentionPolicy.SOURCE) public @interface NetworkSuggestionsStatusCode {} @@ -1948,6 +1957,15 @@ public class WifiManager { * @param config The Passpoint configuration to be added * @throws IllegalArgumentException if configuration is invalid or Passpoint is not enabled on * the device. + * + * Deprecated for general app usage - except DO/PO apps. + * See {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} to + * create a passpoint suggestion. + * See {@link #addNetworkSuggestions(List)}, {@link #removeNetworkSuggestions(List)} for new + * API to add Wi-Fi networks for consideration when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#R} or above, except for system of DO/PO apps, this API + * will throw {@link IllegalArgumentException} */ public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) { try { @@ -2482,6 +2500,20 @@ public class WifiManager { } /** + * Check if the chipset supports a certain Wi-Fi standard. + * @param standard the IEEE 802.11 standard to check on. + * valid values from {@link ScanResult}'s {@code WIFI_STANDARD_} + * @return {@code true} if supported, {@code false} otherwise. + */ + public boolean isWifiStandardSupported(@ScanResult.WifiStandard int standard) { + try { + return mService.isWifiStandardSupported(standard); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Interface for Wi-Fi activity energy info listener. Should be implemented by applications and * set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}. * @@ -2971,7 +3003,7 @@ public class WifiManager { * Each application can make a single active call to this method. The {@link * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} callback supplies the * requestor with a {@link LocalOnlyHotspotReservation} that contains a - * {@link WifiConfiguration} with the SSID, security type and credentials needed to connect + * {@link SoftApConfiguration} with the SSID, security type and credentials needed to connect * to the hotspot. Communicating this information is up to the application. * <p> * If the LocalOnlyHotspot cannot be created, the {@link LocalOnlyHotspotCallback#onFailed(int)} @@ -3136,7 +3168,7 @@ public class WifiManager { * Allow callers (Settings UI) to watch LocalOnlyHotspot state changes. Callers will * receive a {@link LocalOnlyHotspotSubscription} object as a parameter of the * {@link LocalOnlyHotspotObserver#onRegistered(LocalOnlyHotspotSubscription)}. The registered - * callers will receive the {@link LocalOnlyHotspotObserver#onStarted(WifiConfiguration)} and + * callers will receive the {@link LocalOnlyHotspotObserver#onStarted(SoftApConfiguration)} and * {@link LocalOnlyHotspotObserver#onStopped()} callbacks. * <p> * Applications should have the @@ -3223,9 +3255,13 @@ public class WifiManager { * Gets the Wi-Fi AP Configuration. * @return AP details in WifiConfiguration * + * Note that AP detail may contain configuration which is cannot be represented + * by the legacy WifiConfiguration, in such cases a null will be returned. + * * @deprecated This API is deprecated. Use {@link #getSoftApConfiguration()} instead. * @hide */ + @Nullable @SystemApi @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) @Deprecated @@ -3711,13 +3747,13 @@ public class WifiManager { } /** - * LocalOnlyHotspotReservation that contains the {@link WifiConfiguration} for the active + * LocalOnlyHotspotReservation that contains the {@link SoftApConfiguration} for the active * LocalOnlyHotspot request. * <p> * Applications requesting LocalOnlyHotspot for sharing will receive an instance of the * LocalOnlyHotspotReservation in the * {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call. This - * reservation contains the relevant {@link WifiConfiguration}. + * reservation contains the relevant {@link SoftApConfiguration}. * When an application is done with the LocalOnlyHotspot, they should call {@link * LocalOnlyHotspotReservation#close()}. Once this happens, the application will not receive * any further callbacks. If the LocalOnlyHotspot is stopped due to a @@ -3727,18 +3763,38 @@ public class WifiManager { public class LocalOnlyHotspotReservation implements AutoCloseable { private final CloseGuard mCloseGuard = new CloseGuard(); - private final WifiConfiguration mConfig; + private final SoftApConfiguration mSoftApConfig; + private final WifiConfiguration mWifiConfig; private boolean mClosed = false; /** @hide */ @VisibleForTesting - public LocalOnlyHotspotReservation(WifiConfiguration config) { - mConfig = config; + public LocalOnlyHotspotReservation(SoftApConfiguration config) { + mSoftApConfig = config; + mWifiConfig = config.toWifiConfiguration(); mCloseGuard.open("close"); } + /** + * Returns the {@link WifiConfiguration} of the current Local Only Hotspot (LOHS). + * May be null if hotspot enabled and security type is not + * {@code WifiConfiguration.KeyMgmt.None} or {@code WifiConfiguration.KeyMgmt.WPA2_PSK}. + * + * @deprecated Use {@code WifiManager#getSoftApConfiguration()} to get the + * LOHS configuration. + */ + @Deprecated + @Nullable public WifiConfiguration getWifiConfiguration() { - return mConfig; + return mWifiConfig; + } + + /** + * Returns the {@link SoftApConfiguration} of the current Local Only Hotspot (LOHS). + */ + @NonNull + public SoftApConfiguration getSoftApConfiguration() { + return mSoftApConfig; } @Override @@ -3835,7 +3891,7 @@ public class WifiManager { } @Override - public void onHotspotStarted(WifiConfiguration config) { + public void onHotspotStarted(SoftApConfiguration config) { WifiManager manager = mWifiManager.get(); if (manager == null) return; @@ -3927,7 +3983,7 @@ public class WifiManager { /** * LocalOnlyHotspot started with the supplied config. */ - public void onStarted(WifiConfiguration config) {}; + public void onStarted(SoftApConfiguration config) {}; /** * LocalOnlyHotspot stopped. @@ -3967,7 +4023,7 @@ public class WifiManager { } @Override - public void onHotspotStarted(WifiConfiguration config) { + public void onHotspotStarted(SoftApConfiguration config) { WifiManager manager = mWifiManager.get(); if (manager == null) return; diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java index 2fba5a3f4624..0cf0c22d8dc2 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java +++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java @@ -139,6 +139,11 @@ public final class WifiNetworkSuggestion implements Parcelable { */ private @Nullable WifiEnterpriseConfig mWapiEnterpriseConfig; + /** + * Whether this network will be brought up as untrusted (TRUSTED capability bit removed). + */ + private boolean mIsNetworkUntrusted; + public Builder() { mSsid = null; mBssid = null; @@ -159,6 +164,7 @@ public final class WifiNetworkSuggestion implements Parcelable { mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; mWapiPskPassphrase = null; mWapiEnterpriseConfig = null; + mIsNetworkUntrusted = false; } /** @@ -468,6 +474,27 @@ public final class WifiNetworkSuggestion implements Parcelable { return this; } + /** + * Specifies whether the system will bring up the network (if selected) as untrusted. An + * untrusted network has its {@link android.net.NetworkCapabilities#NET_CAPABILITY_TRUSTED} + * capability removed. The Wi-Fi network selection process may use this information to + * influence priority of the suggested network for Wi-Fi network selection (most likely to + * reduce it). The connectivity service may use this information to influence the overall + * network configuration of the device. + * <p> + * <li> An untrusted network's credentials may not be shared with the user using + * {@link #setCredentialSharedWithUser(boolean)}.</li> + * <li> If not set, defaults to false (i.e. network is trusted).</li> + * + * @param isUntrusted Boolean indicating whether the network should be brought up untrusted + * (if true) or trusted (if false). + * @return Instance of {@link Builder} to enable chaining of the builder method. + */ + public @NonNull Builder setUntrusted(boolean isUntrusted) { + mIsNetworkUntrusted = isUntrusted; + return this; + } + private void setSecurityParamsInWifiConfiguration( @NonNull WifiConfiguration configuration) { if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network. @@ -546,6 +573,7 @@ public final class WifiNetworkSuggestion implements Parcelable { wifiConfiguration.meteredOverride = mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED : WifiConfiguration.METERED_OVERRIDE_NONE; + wifiConfiguration.trusted = !mIsNetworkUntrusted; mPasspointConfiguration.setCarrierId(mCarrierId); return wifiConfiguration; } @@ -635,21 +663,28 @@ public final class WifiNetworkSuggestion implements Parcelable { } mIsSharedWithUser = false; } - - if (!mIsSharedWithUser && !mIsInitialAutoJoinEnabled) { - throw new IllegalStateException("Should have not a network with both " - + "setIsUserAllowedToManuallyConnect and " - + "setIsAutoJoinEnabled set to false"); + } + if (!mIsSharedWithUser && !mIsInitialAutoJoinEnabled) { + throw new IllegalStateException("Should have not a network with both " + + "setCredentialSharedWithUser and " + + "setIsAutoJoinEnabled set to false"); + } + if (mIsNetworkUntrusted) { + if (mIsSharedWithUserSet && mIsSharedWithUser) { + throw new IllegalStateException("Should not be both" + + "setCredentialSharedWithUser and +" + + "setIsNetworkAsUntrusted to true"); } + mIsSharedWithUser = false; } - return new WifiNetworkSuggestion( wifiConfiguration, mPasspointConfiguration, mIsAppInteractionRequired, mIsUserInteractionRequired, mIsSharedWithUser, - mIsInitialAutoJoinEnabled); + mIsInitialAutoJoinEnabled, + mIsNetworkUntrusted); } } @@ -690,6 +725,13 @@ public final class WifiNetworkSuggestion implements Parcelable { */ public final boolean isInitialAutoJoinEnabled; + /** + * Whether this network will be brought up as untrusted (TRUSTED capability bit removed). + * @hide + */ + public final boolean isNetworkUntrusted; + + /** @hide */ public WifiNetworkSuggestion() { this.wifiConfiguration = null; @@ -698,6 +740,7 @@ public final class WifiNetworkSuggestion implements Parcelable { this.isUserInteractionRequired = false; this.isUserAllowedToManuallyConnect = true; this.isInitialAutoJoinEnabled = true; + this.isNetworkUntrusted = false; } /** @hide */ @@ -706,7 +749,8 @@ public final class WifiNetworkSuggestion implements Parcelable { boolean isAppInteractionRequired, boolean isUserInteractionRequired, boolean isUserAllowedToManuallyConnect, - boolean isInitialAutoJoinEnabled) { + boolean isInitialAutoJoinEnabled, + boolean isNetworkUntrusted) { checkNotNull(networkConfiguration); this.wifiConfiguration = networkConfiguration; this.passpointConfiguration = passpointConfiguration; @@ -715,6 +759,7 @@ public final class WifiNetworkSuggestion implements Parcelable { this.isUserInteractionRequired = isUserInteractionRequired; this.isUserAllowedToManuallyConnect = isUserAllowedToManuallyConnect; this.isInitialAutoJoinEnabled = isInitialAutoJoinEnabled; + this.isNetworkUntrusted = isNetworkUntrusted; } public static final @NonNull Creator<WifiNetworkSuggestion> CREATOR = @@ -727,7 +772,8 @@ public final class WifiNetworkSuggestion implements Parcelable { in.readBoolean(), // isAppInteractionRequired in.readBoolean(), // isUserInteractionRequired in.readBoolean(), // isSharedCredentialWithUser - in.readBoolean() // isAutoJoinEnabled + in.readBoolean(), // isAutoJoinEnabled + in.readBoolean() ); } @@ -750,6 +796,7 @@ public final class WifiNetworkSuggestion implements Parcelable { dest.writeBoolean(isUserInteractionRequired); dest.writeBoolean(isUserAllowedToManuallyConnect); dest.writeBoolean(isInitialAutoJoinEnabled); + dest.writeBoolean(isNetworkUntrusted); } @Override @@ -789,8 +836,9 @@ public final class WifiNetworkSuggestion implements Parcelable { .append(", FQDN=").append(wifiConfiguration.FQDN) .append(", isAppInteractionRequired=").append(isAppInteractionRequired) .append(", isUserInteractionRequired=").append(isUserInteractionRequired) - .append(", isUserAllowedToManuallyConnect=").append(isUserAllowedToManuallyConnect) + .append(", isCredentialSharedWithUser=").append(isUserAllowedToManuallyConnect) .append(", isInitialAutoJoinEnabled=").append(isInitialAutoJoinEnabled) + .append(", isUnTrusted=").append(isNetworkUntrusted) .append(" ]"); return sb.toString(); } diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java index 08822e2762f6..56fa6e23a852 100644 --- a/wifi/java/com/android/server/wifi/BaseWifiService.java +++ b/wifi/java/com/android/server/wifi/BaseWifiService.java @@ -254,6 +254,11 @@ public class BaseWifiService extends IWifiManager.Stub { } @Override + public boolean isWifiStandardSupported(int standard) { + throw new UnsupportedOperationException(); + } + + @Override public boolean needs5GHzToAnyApBandConversion() { throw new UnsupportedOperationException(); } diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java index 6884a4ede27a..2efdd97543a9 100644 --- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java @@ -18,6 +18,8 @@ package android.net.wifi; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertNull; + import android.net.MacAddress; import android.os.Parcel; @@ -251,7 +253,7 @@ public class SoftApConfigurationTest { } @Test(expected = IllegalArgumentException.class) - public void testsetClientListExceptionWhenExistMacAddressInBothList() { + public void testSetClientListExceptionWhenExistMacAddressInBothList() { final MacAddress testMacAddress_1 = MacAddress.fromString("22:33:44:55:66:77"); final MacAddress testMacAddress_2 = MacAddress.fromString("aa:bb:cc:dd:ee:ff"); ArrayList<MacAddress> testAllowedClientList = new ArrayList<>(); @@ -262,4 +264,40 @@ public class SoftApConfigurationTest { SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); configBuilder.setClientList(testBlockedClientList, testAllowedClientList); } + + @Test + public void testToWifiConfigurationWithUnsupportedParameter() { + SoftApConfiguration sae_config = new SoftApConfiguration.Builder() + .setPassphrase("secretsecret", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE) + .build(); + + assertNull(sae_config.toWifiConfiguration()); + SoftApConfiguration band_6g_config = new SoftApConfiguration.Builder() + .setBand(SoftApConfiguration.BAND_6GHZ) + .build(); + + assertNull(band_6g_config.toWifiConfiguration()); + SoftApConfiguration sae_transition_config = new SoftApConfiguration.Builder() + .setPassphrase("secretsecret", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) + .build(); + + assertNull(sae_transition_config.toWifiConfiguration()); + } + + @Test + public void testToWifiConfigurationWithSupportedParameter() { + SoftApConfiguration softApConfig = new SoftApConfiguration.Builder() + .setPassphrase("secretsecret", + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) + .setChannel(149, SoftApConfiguration.BAND_5GHZ) + .setHiddenSsid(true) + .build(); + WifiConfiguration wifiConfig = softApConfig.toWifiConfiguration(); + assertThat(wifiConfig.getAuthType()).isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK); + assertThat(wifiConfig.preSharedKey).isEqualTo("secretsecret"); + assertThat(wifiConfig.apBand).isEqualTo(WifiConfiguration.AP_BAND_5GHZ); + assertThat(wifiConfig.apChannel).isEqualTo(149); + assertThat(wifiConfig.hiddenSSID).isEqualTo(true); + } } diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index 1ee5374aaa69..f369203e05ab 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -106,6 +106,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.Executor; /** @@ -148,6 +149,50 @@ public class WifiManagerTest { private ScanResultsCallback mScanResultsCallback; private WifiActivityEnergyInfo mWifiActivityEnergyInfo; + /** + * Util function to check public field which used for softap in WifiConfiguration + * same as the value in SoftApConfiguration. + * + */ + private boolean compareWifiAndSoftApConfiguration( + SoftApConfiguration softApConfig, WifiConfiguration wifiConfig) { + if (!Objects.equals(wifiConfig.SSID, softApConfig.getSsid())) { + return false; + } + if (!Objects.equals(wifiConfig.BSSID, softApConfig.getBssid())) { + return false; + } + if (!Objects.equals(wifiConfig.preSharedKey, softApConfig.getPassphrase())) { + return false; + } + + if (wifiConfig.hiddenSSID != softApConfig.isHiddenSsid()) { + return false; + } + switch (softApConfig.getSecurityType()) { + case SoftApConfiguration.SECURITY_TYPE_OPEN: + if (wifiConfig.getAuthType() != WifiConfiguration.KeyMgmt.NONE) { + return false; + } + break; + case SoftApConfiguration.SECURITY_TYPE_WPA2_PSK: + if (wifiConfig.getAuthType() != WifiConfiguration.KeyMgmt.WPA2_PSK) { + return false; + } + break; + default: + return false; + } + return true; + } + + private SoftApConfiguration generatorTestSoftApConfig() { + return new SoftApConfiguration.Builder() + .setSsid("TestSSID") + .setPassphrase("TestPassphrase", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) + .build(); + } + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -212,12 +257,12 @@ public class WifiManagerTest { */ @Test public void testStartTetheredHotspotCallsServiceWithSoftApConfig() throws Exception { - SoftApConfiguration mSoftApConfig = new SoftApConfiguration.Builder().build(); - when(mWifiService.startTetheredHotspot(eq(mSoftApConfig))).thenReturn(true); - assertTrue(mWifiManager.startTetheredHotspot(mSoftApConfig)); + SoftApConfiguration softApConfig = generatorTestSoftApConfig(); + when(mWifiService.startTetheredHotspot(eq(softApConfig))).thenReturn(true); + assertTrue(mWifiManager.startTetheredHotspot(softApConfig)); - when(mWifiService.startTetheredHotspot(eq(mSoftApConfig))).thenReturn(false); - assertFalse(mWifiManager.startTetheredHotspot(mSoftApConfig)); + when(mWifiService.startTetheredHotspot(eq(softApConfig))).thenReturn(false); + assertFalse(mWifiManager.startTetheredHotspot(softApConfig)); } /** @@ -239,14 +284,18 @@ public class WifiManagerTest { */ @Test public void testCreationAndCloseOfLocalOnlyHotspotReservation() throws Exception { + SoftApConfiguration softApConfig = generatorTestSoftApConfig(); TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED); mWifiManager.startLocalOnlyHotspot(callback, mHandler); - callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig)); + callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(softApConfig)); + + assertEquals(softApConfig, callback.mRes.getSoftApConfiguration()); + WifiConfiguration wifiConfig = callback.mRes.getWifiConfiguration(); + assertTrue(compareWifiAndSoftApConfiguration(softApConfig, wifiConfig)); - assertEquals(mApConfig, callback.mRes.getWifiConfiguration()); callback.mRes.close(); verify(mWifiService).stopLocalOnlyHotspot(); } @@ -257,15 +306,18 @@ public class WifiManagerTest { @Test public void testLocalOnlyHotspotReservationCallsStopProperlyInTryWithResources() throws Exception { + SoftApConfiguration softApConfig = generatorTestSoftApConfig(); TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED); mWifiManager.startLocalOnlyHotspot(callback, mHandler); - callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig)); + callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(softApConfig)); try (WifiManager.LocalOnlyHotspotReservation res = callback.mRes) { - assertEquals(mApConfig, res.getWifiConfiguration()); + assertEquals(softApConfig, res.getSoftApConfiguration()); + WifiConfiguration wifiConfig = callback.mRes.getWifiConfiguration(); + assertTrue(compareWifiAndSoftApConfiguration(softApConfig, wifiConfig)); } verify(mWifiService).stopLocalOnlyHotspot(); @@ -315,6 +367,7 @@ public class WifiManagerTest { */ @Test public void testLocalOnlyHotspotCallback() { + SoftApConfiguration softApConfig = generatorTestSoftApConfig(); TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); assertFalse(callback.mOnStartedCalled); assertFalse(callback.mOnStoppedCalled); @@ -323,7 +376,7 @@ public class WifiManagerTest { // test onStarted WifiManager.LocalOnlyHotspotReservation res = - mWifiManager.new LocalOnlyHotspotReservation(mApConfig); + mWifiManager.new LocalOnlyHotspotReservation(softApConfig); callback.onStarted(res); assertEquals(res, callback.mRes); assertTrue(callback.mOnStartedCalled); @@ -349,7 +402,7 @@ public class WifiManagerTest { public boolean mOnRegistered = false; public boolean mOnStartedCalled = false; public boolean mOnStoppedCalled = false; - public WifiConfiguration mConfig = null; + public SoftApConfiguration mConfig = null; public LocalOnlyHotspotSubscription mSub = null; public long mCallingThreadId = -1; @@ -361,7 +414,7 @@ public class WifiManagerTest { } @Override - public void onStarted(WifiConfiguration config) { + public void onStarted(SoftApConfiguration config) { mOnStartedCalled = true; mConfig = config; mCallingThreadId = Thread.currentThread().getId(); @@ -380,6 +433,7 @@ public class WifiManagerTest { @Test public void testLocalOnlyHotspotObserver() { TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); + SoftApConfiguration softApConfig = generatorTestSoftApConfig(); assertFalse(observer.mOnRegistered); assertFalse(observer.mOnStartedCalled); assertFalse(observer.mOnStoppedCalled); @@ -395,18 +449,18 @@ public class WifiManagerTest { assertEquals(null, observer.mConfig); assertEquals(sub, observer.mSub); - observer.onStarted(mApConfig); + observer.onStarted(softApConfig); assertTrue(observer.mOnRegistered); assertTrue(observer.mOnStartedCalled); assertFalse(observer.mOnStoppedCalled); - assertEquals(mApConfig, observer.mConfig); + assertEquals(softApConfig, observer.mConfig); assertEquals(sub, observer.mSub); observer.onStopped(); assertTrue(observer.mOnRegistered); assertTrue(observer.mOnStartedCalled); assertTrue(observer.mOnStoppedCalled); - assertEquals(mApConfig, observer.mConfig); + assertEquals(softApConfig, observer.mConfig); assertEquals(sub, observer.mSub); } @@ -488,6 +542,39 @@ public class WifiManagerTest { */ @Test public void testOnStartedIsCalledWithReservation() throws Exception { + SoftApConfiguration softApConfig = generatorTestSoftApConfig(); + TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); + TestLooper callbackLooper = new TestLooper(); + Handler callbackHandler = new Handler(callbackLooper.getLooper()); + ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback = + ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class); + when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(), + nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED); + mWifiManager.startLocalOnlyHotspot(callback, callbackHandler); + callbackLooper.dispatchAll(); + mLooper.dispatchAll(); + assertFalse(callback.mOnStartedCalled); + assertEquals(null, callback.mRes); + // now trigger the callback + internalCallback.getValue().onHotspotStarted(softApConfig); + mLooper.dispatchAll(); + callbackLooper.dispatchAll(); + assertTrue(callback.mOnStartedCalled); + assertEquals(softApConfig, callback.mRes.getSoftApConfiguration()); + WifiConfiguration wifiConfig = callback.mRes.getWifiConfiguration(); + assertTrue(compareWifiAndSoftApConfiguration(softApConfig, wifiConfig)); + } + + /** + * Verify the LOHS onStarted callback is triggered when WifiManager receives a HOTSPOT_STARTED + * message from WifiServiceImpl when softap enabled with SAE security type. + */ + @Test + public void testOnStartedIsCalledWithReservationAndSaeSoftApConfig() throws Exception { + SoftApConfiguration softApConfig = new SoftApConfiguration.Builder() + .setSsid("TestSSID") + .setPassphrase("TestPassphrase", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE) + .build(); TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); TestLooper callbackLooper = new TestLooper(); Handler callbackHandler = new Handler(callbackLooper.getLooper()); @@ -501,11 +588,12 @@ public class WifiManagerTest { assertFalse(callback.mOnStartedCalled); assertEquals(null, callback.mRes); // now trigger the callback - internalCallback.getValue().onHotspotStarted(mApConfig); + internalCallback.getValue().onHotspotStarted(softApConfig); mLooper.dispatchAll(); callbackLooper.dispatchAll(); assertTrue(callback.mOnStartedCalled); - assertEquals(mApConfig, callback.mRes.getWifiConfiguration()); + assertEquals(softApConfig, callback.mRes.getSoftApConfiguration()); + assertEquals(null, callback.mRes.getWifiConfiguration()); } /** @@ -1037,6 +1125,7 @@ public class WifiManagerTest { */ @Test public void testObserverOnStartedIsCalledWithWifiConfig() throws Exception { + SoftApConfiguration softApConfig = generatorTestSoftApConfig(); TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); TestLooper observerLooper = new TestLooper(); Handler observerHandler = new Handler(observerLooper.getLooper()); @@ -1048,11 +1137,11 @@ public class WifiManagerTest { mLooper.dispatchAll(); assertFalse(observer.mOnStartedCalled); // now trigger the callback - internalCallback.getValue().onHotspotStarted(mApConfig); + internalCallback.getValue().onHotspotStarted(softApConfig); mLooper.dispatchAll(); observerLooper.dispatchAll(); assertTrue(observer.mOnStartedCalled); - assertEquals(mApConfig, observer.mConfig); + assertEquals(softApConfig, observer.mConfig); } /** @@ -1248,7 +1337,7 @@ public class WifiManagerTest { */ @Test public void testSetSoftApConfigurationSuccessReturnsTrue() throws Exception { - SoftApConfiguration apConfig = new SoftApConfiguration.Builder().build(); + SoftApConfiguration apConfig = generatorTestSoftApConfig(); when(mWifiService.setSoftApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME))) .thenReturn(true); @@ -1260,7 +1349,7 @@ public class WifiManagerTest { */ @Test public void testSetSoftApConfigurationFailureReturnsFalse() throws Exception { - SoftApConfiguration apConfig = new SoftApConfiguration.Builder().build(); + SoftApConfiguration apConfig = generatorTestSoftApConfig(); when(mWifiService.setSoftApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME))) .thenReturn(false); @@ -1275,7 +1364,7 @@ public class WifiManagerTest { doThrow(new SecurityException()).when(mWifiService).setSoftApConfiguration(any(), any()); try { - mWifiManager.setSoftApConfiguration(new SoftApConfiguration.Builder().build()); + mWifiManager.setSoftApConfiguration(generatorTestSoftApConfig()); fail("setWifiApConfiguration should rethrow Exceptions from WifiService"); } catch (SecurityException e) { } } @@ -1870,6 +1959,17 @@ public class WifiManagerTest { } /** + * Test behavior of {@link WifiManager#isWifiStandardSupported()} + */ + @Test + public void testIsWifiStandardSupported() throws Exception { + int standard = ScanResult.WIFI_STANDARD_11AX; + when(mWifiService.isWifiStandardSupported(standard)).thenReturn(true); + assertTrue(mWifiManager.isWifiStandardSupported(standard)); + verify(mWifiService).isWifiStandardSupported(standard); + } + + /** * Test behavior of {@link WifiManager#getDhcpInfo()} */ @Test diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java index cb1b7747798d..15accc337429 100644 --- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java +++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java @@ -532,7 +532,7 @@ public class WifiNetworkSuggestionTest { configuration.BSSID = TEST_BSSID; configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion( - configuration, null, false, true, true, false); + configuration, null, false, true, true, true, false); Parcel parcelW = Parcel.obtain(); suggestion.writeToParcel(parcelW, 0); @@ -603,14 +603,14 @@ public class WifiNetworkSuggestionTest { configuration.BSSID = TEST_BSSID; configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); WifiNetworkSuggestion suggestion = - new WifiNetworkSuggestion(configuration, null, true, false, true, true); + new WifiNetworkSuggestion(configuration, null, true, false, true, true, false); WifiConfiguration configuration1 = new WifiConfiguration(); configuration1.SSID = TEST_SSID; configuration1.BSSID = TEST_BSSID; configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); WifiNetworkSuggestion suggestion1 = - new WifiNetworkSuggestion(configuration1, null, false, true, true, false); + new WifiNetworkSuggestion(configuration1, null, false, true, true, true, false); assertEquals(suggestion, suggestion1); assertEquals(suggestion.hashCode(), suggestion1.hashCode()); @@ -626,13 +626,13 @@ public class WifiNetworkSuggestionTest { configuration.SSID = TEST_SSID; configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); WifiNetworkSuggestion suggestion = - new WifiNetworkSuggestion(configuration, null, false, false, true, false); + new WifiNetworkSuggestion(configuration, null, false, false, true, true, false); WifiConfiguration configuration1 = new WifiConfiguration(); configuration1.SSID = TEST_SSID_1; configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); WifiNetworkSuggestion suggestion1 = - new WifiNetworkSuggestion(configuration1, null, false, false, true, false); + new WifiNetworkSuggestion(configuration1, null, false, false, true, true, false); assertNotEquals(suggestion, suggestion1); } @@ -648,13 +648,13 @@ public class WifiNetworkSuggestionTest { configuration.BSSID = TEST_BSSID; configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); WifiNetworkSuggestion suggestion = - new WifiNetworkSuggestion(configuration, null, false, false, true, true); + new WifiNetworkSuggestion(configuration, null, false, false, true, true, false); WifiConfiguration configuration1 = new WifiConfiguration(); configuration1.SSID = TEST_SSID; configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); WifiNetworkSuggestion suggestion1 = - new WifiNetworkSuggestion(configuration1, null, false, false, true, true); + new WifiNetworkSuggestion(configuration1, null, false, false, true, true, false); assertNotEquals(suggestion, suggestion1); } @@ -669,13 +669,13 @@ public class WifiNetworkSuggestionTest { configuration.SSID = TEST_SSID; configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); WifiNetworkSuggestion suggestion = - new WifiNetworkSuggestion(configuration, null, false, false, true, true); + new WifiNetworkSuggestion(configuration, null, false, false, true, true, false); WifiConfiguration configuration1 = new WifiConfiguration(); configuration1.SSID = TEST_SSID; configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); WifiNetworkSuggestion suggestion1 = - new WifiNetworkSuggestion(configuration1, null, false, false, true, true); + new WifiNetworkSuggestion(configuration1, null, false, false, true, true, false); assertNotEquals(suggestion, suggestion1); } @@ -723,8 +723,8 @@ public class WifiNetworkSuggestionTest { * true on a open network suggestion. */ @Test(expected = IllegalStateException.class) - public void testSetIsUserAllowedToManuallyConnectToWithOpenNetwork() { - new WifiNetworkSuggestion.Builder() + public void testSetCredentialSharedWithUserWithOpenNetwork() { + WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() .setSsid(TEST_SSID) .setCredentialSharedWithUser(true) .build(); @@ -758,4 +758,67 @@ public class WifiNetworkSuggestionTest { .setIsInitialAutoJoinEnabled(false) .build(); } + + /** + * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the + * correct value to the WifiConfiguration. + */ + @Test + public void testSetIsNetworkAsUntrusted() { + WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() + .setSsid(TEST_SSID) + .setWpa2Passphrase(TEST_PRESHARED_KEY) + .setUntrusted(true) + .build(); + assertTrue(suggestion.isNetworkUntrusted); + assertFalse(suggestion.isUserAllowedToManuallyConnect); + } + + /** + * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the + * correct value to the WifiConfiguration. + * Also the {@link WifiNetworkSuggestion#isUserAllowedToManuallyConnect} should be false; + */ + @Test + public void testSetIsNetworkAsUntrustedOnPasspointNetwork() { + PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig(); + WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() + .setPasspointConfig(passpointConfiguration) + .setUntrusted(true) + .build(); + assertTrue(suggestion.isNetworkUntrusted); + assertFalse(suggestion.isUserAllowedToManuallyConnect); + } + + /** + * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception + * when set {@link WifiNetworkSuggestion.Builder#setUntrusted(boolean)} to true and + * set {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} to true + * together. + */ + @Test(expected = IllegalStateException.class) + public void testSetCredentialSharedWithUserWithSetIsNetworkAsUntrusted() { + new WifiNetworkSuggestion.Builder() + .setSsid(TEST_SSID) + .setWpa2Passphrase(TEST_PRESHARED_KEY) + .setCredentialSharedWithUser(true) + .setUntrusted(true) + .build(); + } + + /** + * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception + * when set both {@link WifiNetworkSuggestion.Builder#setIsInitialAutoJoinEnabled(boolean)} + * and {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} (boolean)} + * to false on a passpoint suggestion. + */ + @Test(expected = IllegalStateException.class) + public void testSetIsAutoJoinDisabledWithSecureNetworkNotSharedWithUserForPasspoint() { + PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig(); + new WifiNetworkSuggestion.Builder() + .setPasspointConfig(passpointConfiguration) + .setCredentialSharedWithUser(false) + .setIsInitialAutoJoinEnabled(false) + .build(); + } } |