Merge "Using BaseIconFactory to draw legacy icon." into sc-dev
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index cd9be9b..8964668 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -57,12 +57,8 @@
// This list must be kept in sync with jarjar.txt
"modules-utils-preconditions",
],
- libs: ["unsupportedappusage"], // TODO(b/181887768) should be removed
defaults: ["framework-module-defaults"],
permitted_packages: ["android.app.appsearch"],
- aidl: {
- include_dirs: ["frameworks/base/core/java"], // TODO(b/146218515) should be removed
- },
jarjar_rules: "jarjar-rules.txt",
apex_available: ["com.android.appsearch"],
impl_library_visibility: [
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index b5e3662..82b6d62 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -25,7 +25,6 @@
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.app.appsearch.exceptions.AppSearchException;
import android.app.appsearch.util.SchemaMigrationUtil;
-import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -309,19 +308,6 @@
}
/**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- public void getByUri(
- @NonNull GetByUriRequest request,
- @NonNull @CallbackExecutor Executor executor,
- @NonNull BatchResultCallback<String, GenericDocument> callback) {
- getByDocumentId(request.toGetByDocumentIdRequest(), executor, callback);
- }
-
- /**
* Gets {@link GenericDocument} objects by document IDs in a namespace from the {@link
* AppSearchSession} database.
*
@@ -521,19 +507,6 @@
}
/**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- public void remove(
- @NonNull RemoveByUriRequest request,
- @NonNull @CallbackExecutor Executor executor,
- @NonNull BatchResultCallback<String, Void> callback) {
- remove(request.toRemoveByDocumentIdRequest(), executor, callback);
- }
-
- /**
* Removes {@link GenericDocument} objects by document IDs in a namespace from the {@link
* AppSearchSession} database.
*
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
index 0ee5e65..2e04d71 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchSchema.java
@@ -22,7 +22,6 @@
import android.app.appsearch.exceptions.IllegalSchemaException;
import android.app.appsearch.util.BundleUtil;
import android.app.appsearch.util.IndentingStringBuilder;
-import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.util.ArraySet;
@@ -643,60 +642,8 @@
}
}
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- public static class Int64PropertyConfig extends PropertyConfig {
- @UnsupportedAppUsage
- Int64PropertyConfig(@NonNull Bundle bundle) {
- super(bundle);
- }
-
- /** Builder for {@link Int64PropertyConfig}. */
- public static final class Builder {
- private final String mPropertyName;
- private @Cardinality int mCardinality = CARDINALITY_OPTIONAL;
-
- /** Creates a new {@link Int64PropertyConfig.Builder}. */
- @UnsupportedAppUsage
- public Builder(@NonNull String propertyName) {
- mPropertyName = Objects.requireNonNull(propertyName);
- }
-
- /**
- * The cardinality of the property (whether it is optional, required or repeated).
- *
- * <p>If this method is not called, the default cardinality is {@link
- * PropertyConfig#CARDINALITY_OPTIONAL}.
- */
- @SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
- @NonNull
- @UnsupportedAppUsage
- public Int64PropertyConfig.Builder setCardinality(@Cardinality int cardinality) {
- Preconditions.checkArgumentInRange(
- cardinality, CARDINALITY_REPEATED, CARDINALITY_REQUIRED, "cardinality");
- mCardinality = cardinality;
- return this;
- }
-
- /** Constructs a new {@link Int64PropertyConfig} from the contents of this builder. */
- @NonNull
- @UnsupportedAppUsage
- public Int64PropertyConfig build() {
- Bundle bundle = new Bundle();
- bundle.putString(NAME_FIELD, mPropertyName);
- bundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_LONG);
- bundle.putInt(CARDINALITY_FIELD, mCardinality);
- return new Int64PropertyConfig(bundle);
- }
- }
- }
-
/** Configuration for a property containing a 64-bit integer. */
- // TODO(b/181887768): This should extend directly from PropertyConfig
- public static final class LongPropertyConfig extends Int64PropertyConfig {
+ public static final class LongPropertyConfig extends PropertyConfig {
LongPropertyConfig(@NonNull Bundle bundle) {
super(bundle);
}
@@ -896,8 +843,7 @@
/** Builder for {@link DocumentPropertyConfig}. */
public static final class Builder {
private final String mPropertyName;
- // TODO(b/181887768): This should be final
- private String mSchemaType;
+ private final String mSchemaType;
private @Cardinality int mCardinality = CARDINALITY_OPTIONAL;
private boolean mShouldIndexNestedProperties = false;
@@ -916,29 +862,6 @@
}
/**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- public Builder(@NonNull String propertyName) {
- mPropertyName = Objects.requireNonNull(propertyName);
- mSchemaType = null;
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public Builder setSchemaType(@NonNull String schemaType) {
- mSchemaType = Objects.requireNonNull(schemaType);
- return this;
- }
-
- /**
* The cardinality of the property (whether it is optional, required or repeated).
*
* <p>If this method is not called, the default cardinality is {@link
@@ -967,18 +890,6 @@
return this;
}
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public DocumentPropertyConfig.Builder setIndexNestedProperties(
- boolean indexNestedProperties) {
- return setShouldIndexNestedProperties(indexNestedProperties);
- }
-
/** Constructs a new {@link PropertyConfig} from the contents of this builder. */
@NonNull
public DocumentPropertyConfig build() {
@@ -987,9 +898,7 @@
bundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_DOCUMENT);
bundle.putInt(CARDINALITY_FIELD, mCardinality);
bundle.putBoolean(INDEX_NESTED_PROPERTIES_FIELD, mShouldIndexNestedProperties);
- // TODO(b/181887768): Remove checkNotNull after the deprecated constructor (which
- // is the only way to get null here) is removed
- bundle.putString(SCHEMA_TYPE_FIELD, Objects.requireNonNull(mSchemaType));
+ bundle.putString(SCHEMA_TYPE_FIELD, mSchemaType);
return new DocumentPropertyConfig(bundle);
}
}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
index c905f95..4d27519 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/GenericDocument.java
@@ -23,7 +23,6 @@
import android.annotation.SuppressLint;
import android.app.appsearch.util.BundleUtil;
import android.app.appsearch.util.IndentingStringBuilder;
-import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
@@ -51,9 +50,6 @@
public class GenericDocument {
private static final String TAG = "AppSearchGenericDocumen";
- /** The maximum {@link String#length} of a {@link String} field. */
- private static final int MAX_STRING_LENGTH = 20_000;
-
/** The maximum number of indexed properties a document can have. */
private static final int MAX_INDEXED_PROPERTIES = 16;
@@ -134,17 +130,6 @@
return mBundle;
}
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public String getUri() {
- return getId();
- }
-
/** Returns the unique identifier of the {@link GenericDocument}. */
@NonNull
public String getId() {
@@ -1286,15 +1271,6 @@
for (int i = 0; i < values.length; i++) {
if (values[i] == null) {
throw new IllegalArgumentException("The String at " + i + " is null.");
- } else if (values[i].length() > MAX_STRING_LENGTH) {
- throw new IllegalArgumentException(
- "The String at "
- + i
- + " length is: "
- + values[i].length()
- + ", which exceeds length limit: "
- + MAX_STRING_LENGTH
- + ".");
}
}
mProperties.putStringArray(name, values);
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java
deleted file mode 100644
index 7b05eac..0000000
--- a/apex/appsearch/framework/java/external/android/app/appsearch/GetByUriRequest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch;
-
-import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
-@Deprecated
-public final class GetByUriRequest {
- /**
- * Schema type to be used in {@link GetByUriRequest.Builder#addProjection} to apply property
- * paths to all results, excepting any types that have had their own, specific property paths
- * set.
- */
- public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*";
-
- private final String mNamespace;
- private final Set<String> mIds;
- private final Map<String, List<String>> mTypePropertyPathsMap;
-
- GetByUriRequest(
- @NonNull String namespace,
- @NonNull Set<String> ids,
- @NonNull Map<String, List<String>> typePropertyPathsMap) {
- mNamespace = Objects.requireNonNull(namespace);
- mIds = Objects.requireNonNull(ids);
- mTypePropertyPathsMap = Objects.requireNonNull(typePropertyPathsMap);
- }
-
- /** Returns the namespace attached to the request. */
- @NonNull
- public String getNamespace() {
- return mNamespace;
- }
-
- /** Returns the set of document IDs attached to the request. */
- @NonNull
- public Set<String> getUris() {
- return Collections.unmodifiableSet(mIds);
- }
-
- /**
- * Returns a map from schema type to property paths to be used for projection.
- *
- * <p>If the map is empty, then all properties will be retrieved for all results.
- *
- * <p>Calling this function repeatedly is inefficient. Prefer to retain the Map returned by this
- * function, rather than calling it multiple times.
- */
- @NonNull
- public Map<String, List<String>> getProjections() {
- Map<String, List<String>> copy = new ArrayMap<>();
- for (Map.Entry<String, List<String>> entry : mTypePropertyPathsMap.entrySet()) {
- copy.put(entry.getKey(), new ArrayList<>(entry.getValue()));
- }
- return copy;
- }
-
- /**
- * Returns a map from schema type to property paths to be used for projection.
- *
- * <p>If the map is empty, then all properties will be retrieved for all results.
- *
- * <p>A more efficient version of {@link #getProjections}, but it returns a modifiable map. This
- * is not meant to be unhidden and should only be used by internal classes.
- *
- * @hide
- */
- @NonNull
- public Map<String, List<String>> getProjectionsInternal() {
- return mTypePropertyPathsMap;
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @NonNull
- public GetByDocumentIdRequest toGetByDocumentIdRequest() {
- GetByDocumentIdRequest.Builder builder =
- new GetByDocumentIdRequest.Builder(mNamespace).addIds(mIds);
- for (Map.Entry<String, List<String>> projection : mTypePropertyPathsMap.entrySet()) {
- builder.addProjection(projection.getKey(), projection.getValue());
- }
- return builder.build();
- }
-
- /**
- * Builder for {@link GetByUriRequest} objects.
- *
- * <p>Once {@link #build} is called, the instance can no longer be used.
- */
- public static final class Builder {
- private final String mNamespace;
- private final Set<String> mIds = new ArraySet<>();
- private final Map<String, List<String>> mProjectionTypePropertyPaths = new ArrayMap<>();
- private boolean mBuilt = false;
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- public Builder(@NonNull String namespace) {
- mNamespace = Objects.requireNonNull(namespace);
- }
-
- /**
- * Adds one or more document IDs to the request.
- *
- * @throws IllegalStateException if the builder has already been used.
- */
- @NonNull
- public Builder addUris(@NonNull String... ids) {
- Objects.requireNonNull(ids);
- return addUris(Arrays.asList(ids));
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public Builder addUris(@NonNull Collection<String> ids) {
- Preconditions.checkState(!mBuilt, "Builder has already been used");
- Objects.requireNonNull(ids);
- mIds.addAll(ids);
- return this;
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public Builder addProjection(
- @NonNull String schemaType, @NonNull Collection<String> propertyPaths) {
- Preconditions.checkState(!mBuilt, "Builder has already been used");
- Objects.requireNonNull(schemaType);
- Objects.requireNonNull(propertyPaths);
- List<String> propertyPathsList = new ArrayList<>(propertyPaths.size());
- for (String propertyPath : propertyPaths) {
- Objects.requireNonNull(propertyPath);
- propertyPathsList.add(propertyPath);
- }
- mProjectionTypePropertyPaths.put(schemaType, propertyPathsList);
- return this;
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public GetByUriRequest build() {
- Preconditions.checkState(!mBuilt, "Builder has already been used");
- mBuilt = true;
- return new GetByUriRequest(mNamespace, mIds, mProjectionTypePropertyPaths);
- }
- }
-}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
deleted file mode 100644
index 9c74966..0000000
--- a/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch;
-
-import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.util.ArraySet;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
-@Deprecated
-public final class RemoveByUriRequest {
- private final String mNamespace;
- private final Set<String> mIds;
-
- RemoveByUriRequest(String namespace, Set<String> ids) {
- mNamespace = namespace;
- mIds = ids;
- }
-
- /** Returns the namespace to remove documents from. */
- @NonNull
- public String getNamespace() {
- return mNamespace;
- }
-
- /** Returns the set of document IDs attached to the request. */
- @NonNull
- public Set<String> getUris() {
- return Collections.unmodifiableSet(mIds);
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @NonNull
- public RemoveByDocumentIdRequest toRemoveByDocumentIdRequest() {
- return new RemoveByDocumentIdRequest.Builder(mNamespace).addIds(mIds).build();
- }
-
- /**
- * Builder for {@link RemoveByUriRequest} objects.
- *
- * <p>Once {@link #build} is called, the instance can no longer be used.
- */
- public static final class Builder {
- private final String mNamespace;
- private final Set<String> mIds = new ArraySet<>();
- private boolean mBuilt = false;
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- public Builder(@NonNull String namespace) {
- mNamespace = Objects.requireNonNull(namespace);
- }
-
- /**
- * Adds one or more document IDs to the request.
- *
- * @throws IllegalStateException if the builder has already been used.
- */
- @NonNull
- public Builder addUris(@NonNull String... ids) {
- Objects.requireNonNull(ids);
- return addUris(Arrays.asList(ids));
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public Builder addUris(@NonNull Collection<String> ids) {
- Preconditions.checkState(!mBuilt, "Builder has already been used");
- Objects.requireNonNull(ids);
- mIds.addAll(ids);
- return this;
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public RemoveByUriRequest build() {
- Preconditions.checkState(!mBuilt, "Builder has already been used");
- mBuilt = true;
- return new RemoveByUriRequest(mNamespace, mIds);
- }
- }
-}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java
index c388bde..e807803 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/ReportUsageRequest.java
@@ -18,7 +18,6 @@
import android.annotation.CurrentTimeMillisLong;
import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
import java.util.Objects;
@@ -67,8 +66,7 @@
/** Builder for {@link ReportUsageRequest} objects. */
public static final class Builder {
private final String mNamespace;
- // TODO(b/181887768): Make this final
- private String mDocumentId;
+ private final String mDocumentId;
private Long mUsageTimestampMillis;
/**
@@ -85,40 +83,6 @@
}
/**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- public Builder(@NonNull String namespace) {
- mNamespace = Objects.requireNonNull(namespace);
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public Builder setUri(@NonNull String uri) {
- mDocumentId = uri;
- return this;
- }
-
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public ReportUsageRequest.Builder setUsageTimeMillis(
- @CurrentTimeMillisLong long usageTimestampMillis) {
- return setUsageTimestampMillis(usageTimestampMillis);
- }
-
- /**
* Sets the timestamp in milliseconds of the usage report (the time at which the document
* was used).
*
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
index 4beb667..f6a597c 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import com.android.internal.util.Preconditions;
@@ -84,17 +83,6 @@
}
/**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public List<MatchInfo> getMatches() {
- return getMatchInfos();
- }
-
- /**
* Returns a list of {@link MatchInfo}s providing information about how the document in {@link
* #getGenericDocument} matched the query.
*
@@ -196,17 +184,6 @@
return this;
}
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public Builder addMatch(@NonNull MatchInfo matchInfo) {
- return addMatchInfo(matchInfo);
- }
-
/** Adds another match to this SearchResult. */
@NonNull
public Builder addMatchInfo(@NonNull MatchInfo matchInfo) {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
index 3e5a2ca..a3a4a23 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.util.ArraySet;
@@ -342,17 +341,6 @@
return mBundle.getString(NAMESPACE_FIELD, /*defaultValue=*/ "");
}
- /**
- * @deprecated TODO(b/181887768): Exists for dogfood transition; must be removed.
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- @NonNull
- public String getUri() {
- return getDocumentId();
- }
-
/** Returns the id of the {@link GenericDocument} that failed to be migrated. */
@NonNull
public String getDocumentId() {
diff --git a/apex/appsearch/service/Android.bp b/apex/appsearch/service/Android.bp
index b101895..b6521ff 100644
--- a/apex/appsearch/service/Android.bp
+++ b/apex/appsearch/service/Android.bp
@@ -52,7 +52,6 @@
libs: [
"framework-appsearch.impl",
"framework-statsd.stubs.module_lib",
- "unsupportedappusage", // TODO(b/181887768) should be removed
],
defaults: ["framework-system-server-module-defaults"],
permitted_packages: [
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 666d497..1d66beb 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -18,7 +18,6 @@
import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
import static android.os.Process.INVALID_UID;
-import android.Manifest;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.app.appsearch.AppSearchBatchResult;
@@ -1354,43 +1353,26 @@
/**
* Helper for dealing with incoming user arguments to system service calls.
*
- * <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
- *
* @param requestedUser The user which the caller is requesting to execute as.
* @param callingUid The actual uid of the caller as determined by Binder.
* @return the user handle that the call should run as. Will always be a concrete user.
*/
@NonNull
private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
- int callingPid = Binder.getCallingPid();
UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
if (callingUser.equals(requestedUser)) {
return requestedUser;
}
+
// Duplicates UserController#ensureNotSpecialUser
if (requestedUser.getIdentifier() < 0) {
throw new IllegalArgumentException(
"Call does not support special user " + requestedUser);
}
- boolean canInteractAcrossUsers = mContext.checkPermission(
- Manifest.permission.INTERACT_ACROSS_USERS,
- callingPid,
- callingUid) == PackageManager.PERMISSION_GRANTED;
- if (!canInteractAcrossUsers) {
- canInteractAcrossUsers = mContext.checkPermission(
- Manifest.permission.INTERACT_ACROSS_USERS_FULL,
- callingPid,
- callingUid) == PackageManager.PERMISSION_GRANTED;
- }
- if (canInteractAcrossUsers) {
- return requestedUser;
- }
+
throw new SecurityException(
- "Permission denied while calling from uid " + callingUid
- + " with " + requestedUser + "; Need to run as either the calling user ("
- + callingUser + "), or with one of the following permissions: "
- + Manifest.permission.INTERACT_ACROSS_USERS + " or "
- + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+ "Requested user, " + requestedUser + ", is not the same as the calling user, "
+ + callingUser + ".");
}
/**
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index ac20187..45588e8 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -3944,8 +3944,8 @@
} else {
if (mConstants.USE_WINDOW_ALARMS) {
mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- mConstants.FLEX_TIME_SHORT,
- mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
+ mNextAlarmTime, mConstants.FLEX_TIME_SHORT,
+ "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
} else {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 9f52954..98e963e 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -4635,7 +4635,6 @@
Slog.d(TAG, "Package " + packageName + " for user " + userId + " now in bucket " +
bucket);
}
- mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
mHandler.obtainMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED, userId, -1, packageName)
.sendToTarget();
}
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 363b5a7..4d6e4ae 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -21,6 +21,7 @@
import android.app.AppOpsManager.AttributionFlags;
import android.content.AttributionSource;
import android.os.IBinder;
+import android.os.UserHandle;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -215,4 +216,11 @@
* Sets a global restriction on an op code.
*/
public abstract void setGlobalRestriction(int code, boolean restricted, IBinder token);
+
+ /**
+ * Gets the number of tokens restricting the given appop for a user, package, and
+ * attributionTag.
+ */
+ public abstract int getOpRestrictionCount(int code, UserHandle user, String pkg,
+ String attributionTag);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6bc331d..549ab6e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10151,8 +10151,8 @@
* An example of a supported preferential network service is the Enterprise
* slice on 5G networks.
*
- * By default, preferential network service is enabled on the work profile on supported
- * carriers and devices. Admins can explicitly disable it with this API.
+ * By default, preferential network service is disabled on the work profile on supported
+ * carriers and devices. Admins can explicitly enable it with this API.
* On fully-managed devices this method is unsupported because all traffic is considered
* work traffic.
*
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 9501994..d9fa56e 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -991,13 +991,27 @@
* camera's crop region is set to maximum size, the FOV of the physical streams for the
* ultrawide lens will be the same as the logical stream, by making the crop region
* smaller than its active array size to compensate for the smaller focal length.</p>
- * <p>Even if the underlying physical cameras have different RAW characteristics (such as
- * size or CFA pattern), a logical camera can still advertise RAW capability. In this
- * case, when the application configures a RAW stream, the camera device will make sure
- * the active physical camera will remain active to ensure consistent RAW output
- * behavior, and not switch to other physical cameras.</p>
+ * <p>There are two ways for the application to capture RAW images from a logical camera
+ * with RAW capability:</p>
+ * <ul>
+ * <li>Because the underlying physical cameras may have different RAW capabilities (such
+ * as resolution or CFA pattern), to maintain backward compatibility, when a RAW stream
+ * is configured, the camera device makes sure the default active physical camera remains
+ * active and does not switch to other physical cameras. (One exception is that, if the
+ * logical camera consists of identical image sensors and advertises multiple focalLength
+ * due to different lenses, the camera device may generate RAW images from different
+ * physical cameras based on the focalLength being set by the application.) This
+ * backward-compatible approach usually results in loss of optical zoom, to telephoto
+ * lens or to ultrawide lens.</li>
+ * <li>Alternatively, to take advantage of the full zoomRatio range of the logical camera,
+ * the application should use {@link android.hardware.camera2.MultiResolutionImageReader }
+ * to capture RAW images from the currently active physical camera. Because different
+ * physical camera may have different RAW characteristics, the application needs to use
+ * the characteristics and result metadata of the active physical camera for the
+ * relevant RAW metadata.</li>
+ * </ul>
* <p>The capture request and result metadata tags required for backward compatible camera
- * functionalities will be solely based on the logical camera capabiltity. On the other
+ * functionalities will be solely based on the logical camera capability. On the other
* hand, the use of manual capture controls (sensor or post-processing) with a
* logical camera may result in unexpected behavior when the HAL decides to switch
* between physical cameras with different characteristics under the hood. For example,
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 12557f9..c2a2c4c 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -74,7 +74,7 @@
private final IFaceService mService;
private final Context mContext;
- private IBinder mToken = new Binder();
+ private final IBinder mToken = new Binder();
@Nullable private AuthenticationCallback mAuthenticationCallback;
@Nullable private FaceDetectionCallback mFaceDetectionCallback;
@Nullable private EnrollmentCallback mEnrollmentCallback;
@@ -86,7 +86,7 @@
private Face mRemovalFace;
private Handler mHandler;
- private IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {
+ private final IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {
@Override // binder call
public void onEnrollResult(Face face, int remaining) {
@@ -293,7 +293,7 @@
/**
* Defaults to {@link FaceManager#enroll(int, byte[], CancellationSignal, EnrollmentCallback,
- * int[], Surface)} with {@code surface} set to null.
+ * int[], Surface)} with {@code previewSurface} set to null.
*
* @see FaceManager#enroll(int, byte[], CancellationSignal, EnrollmentCallback, int[], Surface)
* @hide
@@ -301,8 +301,8 @@
@RequiresPermission(MANAGE_BIOMETRIC)
public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
EnrollmentCallback callback, int[] disabledFeatures) {
- enroll(userId, hardwareAuthToken, cancel, callback, disabledFeatures, null /* surface */,
- false /* debugConsent */);
+ enroll(userId, hardwareAuthToken, cancel, callback, disabledFeatures,
+ null /* previewSurface */, false /* debugConsent */);
}
/**
@@ -319,14 +319,14 @@
* @param cancel an object that can be used to cancel enrollment
* @param userId the user to whom this face will belong to
* @param callback an object to receive enrollment events
- * @param surface optional camera preview surface for a single-camera device.
+ * @param previewSurface optional camera preview surface for a single-camera device.
* Must be null if not used.
* @param debugConsent a feature flag that the user has consented to debug.
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
- EnrollmentCallback callback, int[] disabledFeatures, @Nullable Surface surface,
+ EnrollmentCallback callback, int[] disabledFeatures, @Nullable Surface previewSurface,
boolean debugConsent) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an enrollment callback");
@@ -346,7 +346,8 @@
mEnrollmentCallback = callback;
Trace.beginSection("FaceManager#enroll");
mService.enroll(userId, mToken, hardwareAuthToken, mServiceReceiver,
- mContext.getOpPackageName(), disabledFeatures, surface, debugConsent);
+ mContext.getOpPackageName(), disabledFeatures, previewSurface,
+ debugConsent);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception in enroll: ", e);
// Though this may not be a hardware issue, it will cause apps to give up or
@@ -853,10 +854,10 @@
* @hide
*/
public static class AuthenticationResult {
- private Face mFace;
- private CryptoObject mCryptoObject;
- private int mUserId;
- private boolean mIsStrongBiometric;
+ private final Face mFace;
+ private final CryptoObject mCryptoObject;
+ private final int mUserId;
+ private final boolean mIsStrongBiometric;
/**
* Authentication result
@@ -1127,7 +1128,7 @@
}
private class OnAuthenticationCancelListener implements OnCancelListener {
- private CryptoObject mCrypto;
+ private final CryptoObject mCrypto;
OnAuthenticationCancelListener(CryptoObject crypto) {
mCrypto = crypto;
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 270d662..b9a49c6 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -75,7 +75,7 @@
// Start face enrollment
void enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
- String opPackageName, in int [] disabledFeatures, in Surface surface, boolean debugConsent);
+ String opPackageName, in int [] disabledFeatures, in Surface previewSurface, boolean debugConsent);
// Start remote face enrollment
void enrollRemotely(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 5a25cfc..ae8d010 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -23,6 +23,9 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
@@ -126,6 +129,24 @@
private static final boolean DBG = false;
/**
+ * When enabled, apps targeting < Android 12 are considered legacy for
+ * the NSD native daemon.
+ * The platform will only keep the daemon running as long as there are
+ * any legacy apps connected.
+ *
+ * After Android 12, directly communicate with native daemon might not
+ * work since the native damon won't always stay alive.
+ * Use the NSD APIs from NsdManager as the replacement is recommended.
+ * An another alternative could be bundling your own mdns solutions instead of
+ * depending on the system mdns native daemon.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
+ public static final long RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS = 191844585L;
+
+ /**
* Broadcast intent action to indicate whether network service discovery is
* enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state
* information as int.
@@ -203,6 +224,9 @@
public static final int DAEMON_CLEANUP = BASE + 21;
/** @hide */
+ public static final int DAEMON_STARTUP = BASE + 22;
+
+ /** @hide */
public static final int ENABLE = BASE + 24;
/** @hide */
public static final int DISABLE = BASE + 25;
@@ -232,6 +256,8 @@
EVENT_NAMES.put(RESOLVE_SERVICE, "RESOLVE_SERVICE");
EVENT_NAMES.put(RESOLVE_SERVICE_FAILED, "RESOLVE_SERVICE_FAILED");
EVENT_NAMES.put(RESOLVE_SERVICE_SUCCEEDED, "RESOLVE_SERVICE_SUCCEEDED");
+ EVENT_NAMES.put(DAEMON_CLEANUP, "DAEMON_CLEANUP");
+ EVENT_NAMES.put(DAEMON_STARTUP, "DAEMON_STARTUP");
EVENT_NAMES.put(ENABLE, "ENABLE");
EVENT_NAMES.put(DISABLE, "DISABLE");
EVENT_NAMES.put(NATIVE_DAEMON_EVENT, "NATIVE_DAEMON_EVENT");
@@ -494,6 +520,12 @@
} catch (InterruptedException e) {
fatal("Interrupted wait at init");
}
+ if (CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) {
+ return;
+ }
+ // Only proactively start the daemon if the target SDK < S, otherwise the internal service
+ // would automatically start/stop the native daemon as needed.
+ mAsyncChannel.sendMessage(DAEMON_STARTUP);
}
private static void fatal(String msg) {
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index 575fc4c..f38271a 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -72,7 +72,7 @@
/** Flag value: Content is human-readable UTF-8 text (can be combined with IS_GZIPPED). */
public static final int IS_TEXT = 2;
- /** Flag value: Content can be decompressed with {@link java.util.zip.GZIPOutputStream}. */
+ /** Flag value: Content can be decompressed with java.util.zip.GZIPOutputStream. */
public static final int IS_GZIPPED = 4;
/** Flag value for serialization only: Value is a byte array, not a file descriptor */
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 4b18c5a..bedad73 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -111,7 +111,12 @@
IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
@Override
public void onSubscriptionsChanged () {
- executor.execute(() -> listener.onSubscriptionsChanged());
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> listener.onSubscriptionsChanged());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
};
mSubscriptionChangedListenerMap.put(listener, callback);
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index f28c42a..8e7fae7 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -251,7 +251,7 @@
// 2. The session never begun.
if (mBeginVsyncId == INVALID_ID) {
cancel(REASON_CANCEL_NOT_BEGUN);
- } else if (mEndVsyncId == mBeginVsyncId) {
+ } else if (mEndVsyncId <= mBeginVsyncId) {
cancel(REASON_CANCEL_SAME_VSYNC);
} else {
if (DEBUG) {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index d49d215..bed0aae 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -887,7 +887,7 @@
for (int fd : fds_to_close) {
ALOGV("Switching descriptor %d to /dev/null", fd);
- if (dup3(devnull_fd, fd, O_CLOEXEC) == -1) {
+ if (TEMP_FAILURE_RETRY(dup3(devnull_fd, fd, O_CLOEXEC)) == -1) {
fail_fn(StringPrintf("Failed dup3() on descriptor %d: %s", fd, strerror(errno)));
}
}
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index 5fe96ed..248db76 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -426,7 +426,7 @@
tmp_pid >>= 8;
}
pid_buf[4] = 0; // Process is not wrapped.
- int res = write(session_socket, pid_buf, 5);
+ int res = TEMP_FAILURE_RETRY(write(session_socket, pid_buf, 5));
if (res != 5) {
if (res == -1) {
(first_time ? fail_fn_1 : fail_fn_n)
@@ -451,18 +451,18 @@
}
// We've now seen either a disconnect or connect request.
close(session_socket);
- int new_fd = accept(zygote_socket_fd, nullptr, nullptr);
+ int new_fd = TEMP_FAILURE_RETRY(accept(zygote_socket_fd, nullptr, nullptr));
if (new_fd == -1) {
fail_fn_z(CREATE_ERROR("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno)));
}
if (new_fd != session_socket) {
// Move new_fd back to the old value, so that we don't have to change Java-level data
// structures to reflect a change. This implicitly closes the old one.
- if (dup2(new_fd, session_socket) != session_socket) {
+ if (TEMP_FAILURE_RETRY(dup2(new_fd, session_socket)) != session_socket) {
fail_fn_z(CREATE_ERROR("Failed to move fd %d to %d: %s",
new_fd, session_socket, strerror(errno)));
}
- close(new_fd);
+ close(new_fd); // On Linux, fd is closed even if EINTR is returned.
}
// If we ever return, we effectively reuse the old Java ZygoteConnection.
// None of its state needs to change.
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index f51a9a5..5add36b 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -815,7 +815,7 @@
<string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="7522314392003565121">"કાર્યાલય મોબાઇલ"</string>
<string name="phoneTypeWorkPager" msgid="3748332310638505234">"કાર્ય પેજર"</string>
- <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string>
+ <string name="phoneTypeAssistant" msgid="757550783842231039">"આસિસ્ટંટ"</string>
<string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string>
<string name="eventTypeCustom" msgid="3257367158986466481">"કસ્ટમ"</string>
<string name="eventTypeBirthday" msgid="7770026752793912283">"જન્મદિવસ"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 1b224c3..44172ea 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -815,7 +815,7 @@
<string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="7522314392003565121">"ഓഫീസ് മൊബൈല്"</string>
<string name="phoneTypeWorkPager" msgid="3748332310638505234">"ഔദ്യോഗിക പേജര്"</string>
- <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string>
+ <string name="phoneTypeAssistant" msgid="757550783842231039">"അസിസ്റ്റന്റ്"</string>
<string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string>
<string name="eventTypeCustom" msgid="3257367158986466481">"ഇഷ്ടാനുസൃതം"</string>
<string name="eventTypeBirthday" msgid="7770026752793912283">"ജന്മദിനം"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 86a9c3f..2648296 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -306,7 +306,7 @@
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"ਆਪਣੇ ਸੰਪਰਕਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"ਟਿਕਾਣਾ"</string>
<string name="permgroupdesc_location" msgid="1995955142118450685">"ਇਸ ਡੀਵਾਈਸ ਦੇ ਨਿਰਧਾਰਤ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚੋ"</string>
- <string name="permgrouplab_calendar" msgid="6426860926123033230">"ਕੈਲੰਡਰ"</string>
+ <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS ਸੁਨੇਹੇ ਭੇਜੋ ਅਤੇ ਦੇਖੋ"</string>
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 6f17ea9..fb820cb 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -286,6 +286,7 @@
}
@Test
+ @FlakyTest(bugId = 194242735)
public void testHandleActivityConfigurationChanged_EnsureUpdatesProcessedInOrder()
throws Exception {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
index 6884f13d..3d820ac 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
@@ -62,4 +62,18 @@
assertThat(outDoc.getPropertyDocument("propDocument").getPropertyBytesArray("propBytes"))
.isEqualTo(new byte[][] {{3, 4}});
}
+
+ @Test
+ public void testPutLargeDocument_exceedLimit() throws Exception {
+ // Create a String property that has a very large property.
+ char[] chars = new char[10_000_000];
+ String property = new StringBuilder().append(chars).append("the end.").toString();
+
+ GenericDocument doc =
+ new GenericDocument.Builder<>("namespace", "id1", "schema1")
+ .setPropertyString("propString", property)
+ .build();
+
+ assertThat(doc.getPropertyString("propString")).isEqualTo(property);
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index c8f8ca9..96b4316 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -257,21 +257,14 @@
}
@Test
- public void testRemoveObserversWhenCancelledInEnd() {
+ public void testCancelIfEndVsyncIdEqualsToBeginVsyncId() {
when(mChoreographer.getVsyncId()).thenReturn(100L);
mTracker.begin();
verify(mRenderer, only()).addObserver(any());
- // send first frame - not janky
- sendFrame(4, JANK_NONE, 100L);
-
- // send another frame - should be considered janky
- sendFrame(40, JANK_APP_DEADLINE_MISSED, 101L);
-
// end the trace session
when(mChoreographer.getVsyncId()).thenReturn(101L);
mTracker.end(FrameTracker.REASON_END_NORMAL);
- sendFrame(4, JANK_NONE, 102L);
// Since the begin vsync id (101) equals to the end vsync id (101), will be treat as cancel.
verify(mTracker).cancel(FrameTracker.REASON_CANCEL_SAME_VSYNC);
@@ -284,6 +277,26 @@
}
@Test
+ public void testCancelIfEndVsyncIdLessThanBeginVsyncId() {
+ when(mChoreographer.getVsyncId()).thenReturn(100L);
+ mTracker.begin();
+ verify(mRenderer, only()).addObserver(any());
+
+ // end the trace session at the same vsync id, end vsync id will less than the begin one.
+ // Because the begin vsync id is supposed to the next frame,
+ mTracker.end(FrameTracker.REASON_END_NORMAL);
+
+ // The begin vsync id (101) is larger than the end one (100), will be treat as cancel.
+ verify(mTracker).cancel(FrameTracker.REASON_CANCEL_SAME_VSYNC);
+
+ // Observers should be removed in this case, or FrameTracker object will be leaked.
+ verify(mTracker).removeObservers();
+
+ // Should never trigger Perfetto since it is a cancel.
+ verify(mTracker, never()).triggerPerfetto();
+ }
+
+ @Test
public void testCancelWhenSessionNeverBegun() {
mTracker.cancel(FrameTracker.REASON_CANCEL_NORMAL);
verify(mTracker).removeObservers();
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
index 8ec1559..c153b38 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -99,6 +99,8 @@
new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
/*traceThresholdFrameTimeMillis=*/ -1, null));
doReturn(tracker).when(monitor).createFrameTracker(any(), any());
+ doNothing().when(tracker).triggerPerfetto();
+ doNothing().when(tracker).postTraceStartMarker();
// Simulate a trace session and see if begin / end are invoked.
assertThat(monitor.begin(mView, session.getCuj())).isTrue();
@@ -146,6 +148,8 @@
new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
/*traceThresholdFrameTimeMillis=*/ -1, null));
doReturn(tracker).when(monitor).createFrameTracker(any(), any());
+ doNothing().when(tracker).triggerPerfetto();
+ doNothing().when(tracker).postTraceStartMarker();
assertThat(monitor.begin(mView, session.getCuj())).isTrue();
verify(tracker).begin();
diff --git a/keystore/java/android/security/GenerateRkpKey.java b/keystore/java/android/security/GenerateRkpKey.java
index a1a7aa8..053bec74 100644
--- a/keystore/java/android/security/GenerateRkpKey.java
+++ b/keystore/java/android/security/GenerateRkpKey.java
@@ -22,6 +22,10 @@
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* GenerateKey is a helper class to handle interactions between Keystore and the RemoteProvisioner
@@ -41,14 +45,25 @@
* @hide
*/
public class GenerateRkpKey {
+ private static final String TAG = "GenerateRkpKey";
+
+ private static final int NOTIFY_EMPTY = 0;
+ private static final int NOTIFY_KEY_GENERATED = 1;
+ private static final int TIMEOUT_MS = 1000;
private IGenerateRkpKeyService mBinder;
private Context mContext;
+ private CountDownLatch mCountDownLatch;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
mBinder = IGenerateRkpKeyService.Stub.asInterface(service);
+ mCountDownLatch.countDown();
+ }
+
+ @Override public void onBindingDied(ComponentName className) {
+ mCountDownLatch.countDown();
}
@Override
@@ -64,36 +79,52 @@
mContext = context;
}
- /**
- * Fulfills the use case of (2) described in the class documentation. Blocks until the
- * RemoteProvisioner application can get new attestation keys signed by the server.
- */
- public void notifyEmpty(int securityLevel) throws RemoteException {
+ private void bindAndSendCommand(int command, int securityLevel) throws RemoteException {
Intent intent = new Intent(IGenerateRkpKeyService.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ if (comp == null) {
+ // On a system that does not use RKP, the RemoteProvisioner app won't be installed.
+ return;
+ }
intent.setComponent(comp);
- if (comp == null || !mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
- throw new RemoteException("Failed to bind to GenerateKeyService");
+ mCountDownLatch = new CountDownLatch(1);
+ if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
+ throw new RemoteException("Failed to bind to GenerateRkpKeyService");
+ }
+ try {
+ mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Interrupted: ", e);
}
if (mBinder != null) {
- mBinder.generateKey(securityLevel);
+ switch (command) {
+ case NOTIFY_EMPTY:
+ mBinder.generateKey(securityLevel);
+ break;
+ case NOTIFY_KEY_GENERATED:
+ mBinder.notifyKeyGenerated(securityLevel);
+ break;
+ default:
+ Log.e(TAG, "Invalid case for command");
+ }
+ } else {
+ Log.e(TAG, "Binder object is null; failed to bind to GenerateRkpKeyService.");
}
mContext.unbindService(mConnection);
}
/**
- * FUlfills the use case of (1) described in the class documentation. Non blocking call.
+ * Fulfills the use case of (2) described in the class documentation. Blocks until the
+ * RemoteProvisioner application can get new attestation keys signed by the server.
+ */
+ public void notifyEmpty(int securityLevel) throws RemoteException {
+ bindAndSendCommand(NOTIFY_EMPTY, securityLevel);
+ }
+
+ /**
+ * Fulfills the use case of (1) described in the class documentation. Non blocking call.
*/
public void notifyKeyGenerated(int securityLevel) throws RemoteException {
- Intent intent = new Intent(IGenerateRkpKeyService.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
- throw new RemoteException("Failed to bind to GenerateKeyService");
- }
- if (mBinder != null) {
- mBinder.notifyKeyGenerated(securityLevel);
- }
- mContext.unbindService(mConnection);
+ bindAndSendCommand(NOTIFY_KEY_GENERATED, securityLevel);
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 7258a3a..2e85b30 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -599,7 +599,7 @@
} catch (RemoteException e) {
// This is not really an error state, and necessarily does not apply to non RKP
// systems or hybrid systems where RKP is not currently turned on.
- Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.");
+ Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.", e);
}
success = true;
return new KeyPair(publicKey, publicKey.getPrivateKey());
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 8cea869..d0e4f7a 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -36,6 +36,9 @@
<!-- Allow PIP to resize via dragging the corner of PiP. -->
<bool name="config_pipEnableDragCornerResize">false</bool>
+ <!-- PiP minimum size, which is a % based off the shorter side of display width and height -->
+ <fraction name="config_pipShortestEdgePercent">40%</fraction>
+
<!-- Animation duration when using long press on recents to dock -->
<integer name="long_press_dock_anim_duration">250</integer>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index c46b559..200af74 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -26,10 +26,14 @@
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.app.TaskInfo;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
import android.graphics.Rect;
import android.view.Choreographer;
import android.view.Surface;
import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
@@ -253,6 +257,7 @@
mSurfaceControlTransactionFactory;
private PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private @TransitionDirection int mTransitionDirection;
+ protected SurfaceControl mContentOverlay;
private PipTransitionAnimator(TaskInfo taskInfo, SurfaceControl leash,
@AnimationType int animationType, Rect destinationBounds, T baseValue, T startValue,
@@ -331,6 +336,53 @@
return false;
}
+ SurfaceControl getContentOverlay() {
+ return mContentOverlay;
+ }
+
+ PipTransitionAnimator<T> setUseContentOverlay(Context context) {
+ final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
+ if (mContentOverlay != null) {
+ // remove existing content overlay if there is any.
+ tx.remove(mContentOverlay);
+ tx.apply();
+ }
+ mContentOverlay = new SurfaceControl.Builder(new SurfaceSession())
+ .setCallsite("PipAnimation")
+ .setName("PipContentOverlay")
+ .setColorLayer()
+ .build();
+ tx.show(mContentOverlay);
+ tx.setLayer(mContentOverlay, Integer.MAX_VALUE);
+ tx.setColor(mContentOverlay, getContentOverlayColor(context));
+ tx.setAlpha(mContentOverlay, 0f);
+ tx.reparent(mContentOverlay, mLeash);
+ tx.apply();
+ return this;
+ }
+
+ private float[] getContentOverlayColor(Context context) {
+ final TypedArray ta = context.obtainStyledAttributes(new int[] {
+ android.R.attr.colorBackground });
+ try {
+ int colorAccent = ta.getColor(0, 0);
+ return new float[] {
+ Color.red(colorAccent) / 255f,
+ Color.green(colorAccent) / 255f,
+ Color.blue(colorAccent) / 255f };
+ } finally {
+ ta.recycle();
+ }
+ }
+
+ /**
+ * Clears the {@link #mContentOverlay}, this should be done after the content overlay is
+ * faded out, such as in {@link PipTaskOrganizer#fadeOutAndRemoveOverlay}
+ */
+ void clearContentOverlay() {
+ mContentOverlay = null;
+ }
+
@VisibleForTesting
@TransitionDirection public int getTransitionDirection() {
return mTransitionDirection;
@@ -517,6 +569,9 @@
final Rect base = getBaseValue();
final Rect start = getStartValue();
final Rect end = getEndValue();
+ if (mContentOverlay != null) {
+ tx.setAlpha(mContentOverlay, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2);
+ }
if (rotatedEndRect != null) {
// Animate the bounds in a different orientation. It only happens when
// switching between PiP and fullscreen.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index f367cd6..5a50619 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -107,6 +107,13 @@
*/
private static final int ONE_SHOT_ALPHA_ANIMATION_TIMEOUT_MS = 1000;
+ /**
+ * The fixed start delay in ms when fading out the content overlay from bounds animation.
+ * This is to overcome the flicker caused by configuration change when rotating from landscape
+ * to portrait PiP in button navigation mode.
+ */
+ private static final int CONTENT_OVERLAY_FADE_OUT_DELAY_MS = 500;
+
// Not a complete set of states but serves what we want right now.
private enum State {
UNDEFINED(0),
@@ -176,6 +183,10 @@
final int direction = animator.getTransitionDirection();
final int animationType = animator.getAnimationType();
final Rect destinationBounds = animator.getDestinationBounds();
+ if (isInPipDirection(direction) && animator.getContentOverlay() != null) {
+ fadeOutAndRemoveOverlay(animator.getContentOverlay(),
+ animator::clearContentOverlay, true /* withStartDelay*/);
+ }
if (mWaitForFixedRotation && animationType == ANIM_TYPE_BOUNDS
&& direction == TRANSITION_DIRECTION_TO_PIP) {
// Notify the display to continue the deferred orientation change.
@@ -199,17 +210,17 @@
finishResize(tx, destinationBounds, direction, animationType);
sendOnPipTransitionFinished(direction);
}
- if (direction == TRANSITION_DIRECTION_TO_PIP) {
- // TODO (b//169221267): Add jank listener for transactions without buffer updates.
- //InteractionJankMonitor.getInstance().end(
- // InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_PIP);
- }
}
@Override
public void onPipAnimationCancel(TaskInfo taskInfo,
PipAnimationController.PipTransitionAnimator animator) {
- sendOnPipTransitionCancelled(animator.getTransitionDirection());
+ final int direction = animator.getTransitionDirection();
+ if (isInPipDirection(direction) && animator.getContentOverlay() != null) {
+ fadeOutAndRemoveOverlay(animator.getContentOverlay(),
+ animator::clearContentOverlay, true /* withStartDelay */);
+ }
+ sendOnPipTransitionCancelled(direction);
}
};
@@ -640,7 +651,8 @@
// Remove the swipe to home overlay
if (swipeToHomeOverlay != null) {
- fadeOutAndRemoveOverlay(swipeToHomeOverlay);
+ fadeOutAndRemoveOverlay(swipeToHomeOverlay,
+ null /* callback */, false /* withStartDelay */);
}
}, tx);
mInSwipePipToHomeTransition = false;
@@ -723,9 +735,12 @@
mOnDisplayIdChangeCallback.accept(Display.DEFAULT_DISPLAY);
}
- final PipAnimationController.PipTransitionAnimator animator =
+ final PipAnimationController.PipTransitionAnimator<?> animator =
mPipAnimationController.getCurrentAnimator();
if (animator != null) {
+ if (animator.getContentOverlay() != null) {
+ removeContentOverlay(animator.getContentOverlay(), animator::clearContentOverlay);
+ }
animator.removeAllUpdateListeners();
animator.removeAllListeners();
animator.cancel();
@@ -1196,7 +1211,8 @@
snapshotDest);
// Start animation to fade out the snapshot.
- fadeOutAndRemoveOverlay(snapshotSurface);
+ fadeOutAndRemoveOverlay(snapshotSurface,
+ null /* callback */, false /* withStartDelay */);
});
} else {
applyFinishBoundsResize(wct, direction);
@@ -1287,15 +1303,20 @@
animator.setTransitionDirection(direction)
.setPipAnimationCallback(mPipAnimationCallback)
.setPipTransactionHandler(mPipTransactionHandler)
- .setDuration(durationMs)
- .start();
- if (rotationDelta != Surface.ROTATION_0 && direction == TRANSITION_DIRECTION_TO_PIP) {
+ .setDuration(durationMs);
+ if (isInPipDirection(direction)) {
+ // Similar to auto-enter-pip transition, we use content overlay when there is no
+ // source rect hint to enter PiP use bounds animation.
+ if (sourceHintRect == null) animator.setUseContentOverlay(mContext);
// The destination bounds are used for the end rect of animation and the final bounds
// after animation finishes. So after the animation is started, the destination bounds
// can be updated to new rotation (computeRotatedBounds has changed the DisplayLayout
// without affecting the animation.
- animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds());
+ if (rotationDelta != Surface.ROTATION_0) {
+ animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds());
+ }
}
+ animator.start();
return animator;
}
@@ -1308,6 +1329,14 @@
outDestinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds());
// Transform the destination bounds to current display coordinates.
rotateBounds(outDestinationBounds, displayBounds, mNextRotation, mCurrentRotation);
+ // When entering PiP (from button navigation mode), adjust the source rect hint by
+ // display cutout if applicable.
+ if (sourceHintRect != null && mTaskInfo.displayCutoutInsets != null) {
+ if (rotationDelta == Surface.ROTATION_270) {
+ sourceHintRect.offset(mTaskInfo.displayCutoutInsets.left,
+ mTaskInfo.displayCutoutInsets.top);
+ }
+ }
} else if (direction == TRANSITION_DIRECTION_LEAVE_PIP) {
final Rect rotatedDestinationBounds = new Rect(outDestinationBounds);
rotateBounds(rotatedDestinationBounds, mPipBoundsState.getDisplayBounds(),
@@ -1346,7 +1375,8 @@
/**
* Fades out and removes an overlay surface.
*/
- private void fadeOutAndRemoveOverlay(SurfaceControl surface) {
+ private void fadeOutAndRemoveOverlay(SurfaceControl surface, Runnable callback,
+ boolean withStartDelay) {
if (surface == null) {
return;
}
@@ -1363,15 +1393,21 @@
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- final SurfaceControl.Transaction tx =
- mSurfaceControlTransactionFactory.getTransaction();
- tx.remove(surface);
- tx.apply();
+ removeContentOverlay(surface, callback);
}
});
+ animator.setStartDelay(withStartDelay ? CONTENT_OVERLAY_FADE_OUT_DELAY_MS : 0);
animator.start();
}
+ private void removeContentOverlay(SurfaceControl surface, Runnable callback) {
+ final SurfaceControl.Transaction tx =
+ mSurfaceControlTransactionFactory.getTransaction();
+ tx.remove(surface);
+ tx.apply();
+ if (callback != null) callback.run();
+ }
+
/**
* Dumps internal states.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 0bcd1a3..7867f93 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -63,7 +63,6 @@
* the PIP.
*/
public class PipTouchHandler {
- @VisibleForTesting static final float MINIMUM_SIZE_PERCENT = 0.4f;
private static final String TAG = "PipTouchHandler";
private static final float DEFAULT_STASH_VELOCITY_THRESHOLD = 18000.f;
@@ -115,6 +114,7 @@
private float mSavedSnapFraction = -1f;
private boolean mSendingHoverAccessibilityEvents;
private boolean mMovementWithinDismiss;
+ private float mMinimumSizePercent;
// Touch state
private final PipTouchState mTouchState;
@@ -252,6 +252,7 @@
mExpandedShortestEdgeSize = res.getDimensionPixelSize(
R.dimen.pip_expanded_shortest_edge_size);
mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
+ mMinimumSizePercent = res.getFraction(R.fraction.config_pipShortestEdgePercent, 1, 1);
mPipDismissTargetHandler.updateMagneticTargetSize();
}
@@ -481,12 +482,12 @@
+ (mPipBoundsState.getDisplayBounds().height() - insetBounds.bottom);
final int minWidth, minHeight, maxWidth, maxHeight;
if (aspectRatio > 1f) {
- minWidth = (int) Math.min(normalBounds.width(), shorterLength * MINIMUM_SIZE_PERCENT);
+ minWidth = (int) Math.min(normalBounds.width(), shorterLength * mMinimumSizePercent);
minHeight = (int) (minWidth / aspectRatio);
maxWidth = (int) Math.max(normalBounds.width(), shorterLength - totalHorizontalPadding);
maxHeight = (int) (maxWidth / aspectRatio);
} else {
- minHeight = (int) Math.min(normalBounds.height(), shorterLength * MINIMUM_SIZE_PERCENT);
+ minHeight = (int) Math.min(normalBounds.height(), shorterLength * mMinimumSizePercent);
minWidth = (int) (minHeight * aspectRatio);
maxHeight = (int) Math.max(normalBounds.height(), shorterLength - totalVerticalPadding);
maxWidth = (int) (maxHeight * aspectRatio);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index cc05ecd..8b91536 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -72,6 +72,37 @@
Finally, you request (or receive) a filled output buffer, consume its contents and release it
back to the codec.
+ <h3 id=qualityFloor><a name="qualityFloor">Minimum Quality Floor for Video Encoding</h3>
+ <p>
+ Beginning with {@link android.os.Build.VERSION_CODES#S}, Android's Video MediaCodecs enforce a
+ minimum quality floor. The intent is to eliminate poor quality video encodings. This quality
+ floor is applied when the codec is in Variable Bitrate (VBR) mode; it is not applied when
+ the codec is in Constant Bitrate (CBR) mode. The quality floor enforcement is also restricted
+ to a particular size range; this size range is currently for video resolutions
+ larger than 320x240 up through 1920x1080.
+
+ <p>
+ When this quality floor is in effect, the codec and supporting framework code will work to
+ ensure that the generated video is of at least a "fair" or "good" quality. The metric
+ used to choose these targets is the VMAF (Video Multi-method Assessment Function) with a
+ target score of 70 for selected test sequences.
+
+ <p>
+ The typical effect is that
+ some videos will generate a higher bitrate than originally configured. This will be most
+ notable for videos which were configured with very low bitrates; the codec will use a bitrate
+ that is determined to be more likely to generate an "fair" or "good" quality video. Another
+ situation is where a video includes very complicated content (lots of motion and detail);
+ in such configurations, the codec will use extra bitrate as needed to avoid losing all of
+ the content's finer detail.
+
+ <p>
+ This quality floor will not impact content captured at high bitrates (a high bitrate should
+ already provide the codec with sufficient capacity to encode all of the detail).
+ The quality floor does not operate on CBR encodings.
+ The quality floor currently does not operate on resolutions of 320x240 or lower, nor on
+ videos with resolution above 1920x1080.
+
<h3>Data Types</h3>
<p>
Codecs operate on three kinds of data: compressed data, raw audio data and raw video data.
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 341bb8d..7d80e93 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -1096,6 +1096,13 @@
* clipped internally to ensure the video recording can proceed smoothly based on
* the capabilities of the platform.
*
+ * <p>
+ * NB: the actual bitrate and other encoding characteristics may be affected by
+ * the minimum quality floor behavior introduced in
+ * {@link android.os.Build.VERSION_CODES#S}. More detail on how and where this
+ * impacts video encoding can be found in the
+ * {@link MediaCodec} page and looking for "quality floor" (near the top of the page).
+ *
* @param bitRate the video encoding bit rate in bits per second.
*/
public void setVideoEncodingBitRate(int bitRate) {
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 9598e87..3506057 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou kamera te gebruik."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou kamera of mikrofoon te gebruik."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Toestel"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swiep op om programme te wissel"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Sleep regs om programme vinnig te wissel"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Wissel oorsig"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Gelaai"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laai tans"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d60d082..74009bf 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ይህ ካሜራዎን እንዲጠቀሙ ለተፈቀደላቸው ሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻን እገዳ ያነሳል።"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ይህ የእርስዎን ካሜራ ወይም ማይክሮፎን እንዲጠቀሙ የተፈቀደላቸው የሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻ እገዳን ያነሳል።"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"መሣሪያ"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"መተግበሪያዎችን ለመቀየር ወደ ላይ ያንሸራትቱ"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"መተግበሪያዎችን በፍጥነት ለመቀየር ወደ ቀኝ ይጎትቱ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"አጠቃላይ እይታን ቀያይር"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ባትሪ ሞልቷል"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ኃይል በመሙላት ላይ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 6195e5f..993ee39 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -441,8 +441,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الكاميرا."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الكاميرا أو الميكروفون."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"الجهاز"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"مرّر سريعًا لأعلى لتبديل التطبيقات"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"اسحب لليسار للتبديل السريع بين التطبيقات"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تبديل \"النظرة العامة\""</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"تم الشحن"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"جارٍ الشحن"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index bc5a91a..20023c0 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"এইটোৱে আপোনাৰ কেমেৰা ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"এইটোৱে আপোনাৰ কেমেৰা অথবা মাইক্ৰ\'ফ\'ন ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইচ"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"খৰতকীয়াকৈ আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ সোঁফালে টানক"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"অৱলোকন ট’গল কৰক"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"চ্চার্জ হ’ল"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"চ্চার্জ হৈ আছে"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 5479089..71f90fd5 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Tətbiqi dəyişmək üçün yuxarı sürüşdürün"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tətbiqləri cəld dəyişmək üçün sağa çəkin"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"İcmala Keçin"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Enerji yığılıb"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Enerji doldurulur"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index d48eebc..7402594 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -435,8 +435,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje kamere."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje kamere ili mikrofona."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prevucite nagore da biste menjali aplikacije"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Prevucite udesno da biste brzo promenili aplikacije"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključi/isključi pregled"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjena je"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Puni se"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 491cdcd..7688e06 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -437,8 +437,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць камеру."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць камеру ці мікрафон."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Прылада"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Правядзіце ўверх, каб пераключыць праграмы"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Каб хутка пераключыцца паміж праграмамі, перацягніце ўправа"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Уключыць/выключыць агляд"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Зараджаны"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарадка"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index da45743..386fbd6 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват камерата ви."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват камерата или микрофона ви."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Прекарайте пръст нагоре, за да превключите между приложенията"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Плъзнете надясно за бързо превключване между приложенията"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Превключване на общия преглед"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Заредена"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарежда се"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 46aea06..d269126 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"এটার জন্য ক্যামেরার অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার ক্যামেরা ব্যবহারের অনুমতি দেওয়া হয়েছে।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"এটার জন্য ক্যামেরা অথবা মাইক্রোফোনের অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার ক্যামেরা অথবা মাইক্রোফোন ব্যবহারের অনুমতি দেওয়া হয়েছে।"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইস"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"অন্য অ্যাপে যেতে উপরের দিকে সোয়াইপ করুন"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"একটি অ্যাপ ছেড়ে দ্রুত অন্য অ্যাপে যেতে ডান দিকে টেনে আনুন"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"\'এক নজরে\' বৈশিষ্ট্যটি চালু বা বন্ধ করুন"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"চার্জ হয়েছে"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"চার্জ হচ্ছে"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 2dc7301..2857ecc 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -435,8 +435,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vašu kameru."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vašu kameru ili mikrofon."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prevucite prema gore za promjenu aplikacije"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Prevucite udesno za brzu promjenu aplikacija"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pregled uključivanja/isključivanja"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjeno"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Punjenje"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 37fdbc1..c25dca5 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar la càmera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar la càmera o el micròfon."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositiu"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Llisca cap amunt per canviar d\'aplicació"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrossega el dit cap a la dreta per canviar ràpidament d\'aplicació"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activa o desactiva Aplicacions recents"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"S\'està carregant"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 25f796c..5fed1b3 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -437,8 +437,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš fotoaparát."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš fotoaparát či mikrofon."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Zařízení"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Přejetím nahoru přepnete aplikace"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Přetažením doprava rychle přepnete aplikace"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Přepnout přehled"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Nabito"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nabíjení"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index feb0dae..facedf0f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge dit kamera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge dit kamera eller din mikrofon."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Enhed"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Stryg opad for at skifte apps"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Træk til højre for hurtigt at skifte app"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå Oversigt til/fra"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Opladet"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Oplader"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a92dd6f..5d10eb4 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die deine Kamera verwenden dürfen."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die deine Kamera oder dein Mikrofon verwenden dürfen."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Gerät"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Nach oben wischen, um Apps zu wechseln"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Zum schnellen Wechseln der Apps nach rechts ziehen"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Übersicht ein-/ausblenden"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Aufgeladen"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Wird aufgeladen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 99a90cc..cfda46f 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν την κάμερά σας."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν την κάμερα ή το μικρόφωνό σας."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Συσκευή"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Σύρετε προς τα επάνω για εναλλαγή των εφαρμογών"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Σύρετε προς τα δεξιά για γρήγορη εναλλαγή εφαρμογών"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Εναλλαγή επισκόπησης"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Φορτίστηκε"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Φόρτιση"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index fd54063..9af2d89 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe up to switch apps"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Drag right to quickly switch apps"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index dff3c30..398420a 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe up to switch apps"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Drag right to quickly switch apps"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index fd54063..9af2d89 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe up to switch apps"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Drag right to quickly switch apps"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index fd54063..9af2d89 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe up to switch apps"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Drag right to quickly switch apps"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 97976db..b211026 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe up to switch apps"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Drag right to quickly switch apps"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index a431258..55b0f98 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Esta acción desbloquea el acceso para todos los servicios y las apps que tengan permitido usar la cámara."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Esta acción permite que todas las aplicaciones y servicios que tengan permiso puedan usar la cámara o el micrófono."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Desliza el dedo hacia arriba para cambiar de app"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra a la derecha para cambiar aplicaciones rápidamente"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ocultar o mostrar Recientes"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargada"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 0fa33e7..c5096e9 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara o tu micrófono."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Desliza el dedo hacia arriba para cambiar de aplicación"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra hacia la derecha para cambiar rápidamente de aplicación"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Mostrar u ocultar aplicaciones recientes"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargada"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 5e52394..ee7c760 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud kaamerat kasutada."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud kaamerat või mikrofoni kasutada."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Seade"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Rakenduste vahetamiseks pühkige üles"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Lohistage paremale, et rakendusi kiiresti vahetada"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Lehe Ülevaade sisse- ja väljalülitamine"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Laetud"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laadimine"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 3e687d7..0972c26b 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamera atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dute."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera edo mikrofonoa atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dituzte."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Gailua"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Egin gora aplikazioa aldatzeko"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastatu eskuinera aplikazioa azkar aldatzeko"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aldatu ikuspegi orokorra"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Kargatuta"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Kargatzen"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index b37a7be..2899e17 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"با این کار دسترسی برای همه برنامهها و سرویسهایی که مجاز هستند از دوربینتان استفاده کنند لغو انسداد میشود."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"با این کار دسترسی برای همه برنامهها و دستگاههایی که مجاز هستند از دوربین یا میکروفونتان استفاده کنند لغو انسداد میشود."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"دستگاه"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"برای تغییر برنامهها، تند بهبالا بکشید"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"برای جابهجایی سریع میان برنامهها، به چپ بکشید"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تغییر وضعیت نمای کلی"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"شارژ کامل شد"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"در حال شارژ شدن"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index e963853..dc49957 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tämä kumoaa kaikkien sellaisten sovellusten ja palveluiden eston, joilla on lupa käyttää kameraasi."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tämä kumoaa eston kaikkien sellaisten sovellusten ja palveluiden osalta, joilla on lupa käyttää kameraasi tai mikrofoniasi."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Laite"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Vaihda sovellusta pyyhkäisemällä ylös"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Vaihda sovellusta nopeasti vetämällä oikealle"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Näytä/piilota viimeisimmät"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Ladattu"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Ladataan"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 457ab8a..83c0ef4 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Cette action débloque l\'accès pour toutes les applications et pour tous les services autorisés à utiliser l\'appareil photo."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès pour toutes les applications et tous les services autorisés à utiliser l\'appareil photo ou le microphone."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Balayez vers le haut pour changer d\'application"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Balayez l\'écran vers la droite pour changer rapidement d\'application"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Basculer l\'aperçu"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Chargée"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charge en cours..."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1c09d87..bb3183e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Cette action débloque l\'accès à tous les services et applis autorisés à utiliser votre appareil photo."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès pour tous les services et applis autorisés à utiliser votre appareil photo ou votre micro."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Balayer l\'écran vers le haut pour changer d\'application"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Déplacer vers la droite pour changer rapidement d\'application"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activer/Désactiver l\'aperçu"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Chargé"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"En charge"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index b5018d1..d8fe4b8 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Con esta acción desbloquearase o acceso á cámara para todas as aplicacións e servizos que teñan permiso para utilizala."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Con esta acción desbloquearase o acceso á cámara ou ao micrófono para todas as aplicacións e servizos que teñan permiso para utilizalos."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Pasar o dedo cara arriba para cambiar de aplicación"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra cara á dereita para cambiar de aplicacións rapidamente"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activar/desactivar Visión xeral"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargado"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index b29a528..408e798 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"આ તમારા કૅમેરાનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"આ તમારા કૅમેરા અથવા માઇક્રોફોનનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ડિવાઇસ"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ઍપ સ્વિચ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ઍપને ઝડપથી સ્વિચ કરવા માટે જમણે ખેંચો"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ઝલકને ટૉગલ કરો"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ચાર્જ થઈ ગયું"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ચાર્જ થઈ રહ્યું છે"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1d56cd6..ac4a903 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ऐसा करने से, कैमरे का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें कैमरे का इस्तेमाल करने की अनुमति दी गई है."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ऐसा करने से, कैमरा या माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें ये इस्तेमाल करने की अनुमति है."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"डिवाइस"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ऐप्लिकेशन बदलने के लिए ऊपर स्वाइप करें"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ऐप्लिकेशन को झटपट स्विच करने के लिए उसे दाईं ओर खींचें और छोड़ें"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"खास जानकारी टॉगल करें"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज हो गई है"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज हो रही है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 689a435..571ca24 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -435,8 +435,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg fotoaparata."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg fotoaparata ili mikrofona."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prijeđite prstom prema gore da biste promijenili aplikaciju"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Povucite udesno da biste brzo promijenili aplikaciju"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključivanje/isključivanje pregleda"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjeno"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Punjenje"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index f7728d2..9a7ca9d6 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a kamera használatát."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a kamera vagy a mikrofon használatát."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Eszköz"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Váltás az alkalmazások között felfelé csúsztatással"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Húzza jobbra az ujját az alkalmazások közötti gyors váltáshoz"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Áttekintés be- és kikapcsolása"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Feltöltve"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Töltés"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4605a98..74ab34d 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր տեսախցիկն օգտագործելու թույլտվություն։"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր տեսախցիկը կամ խոսափողն օգտագործելու թույլտվություն։"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Սարք"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Սահեցրեք վերև՝ մյուս հավելվածին անցնելու համար"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Քաշեք աջ՝ հավելվածների միջև անցնելու համար"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Միացնել/անջատել համատեսքը"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Լիցքավորված է"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Լիցքավորվում է"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index ef20347..204484c 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Langkah ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera atau mikrofon."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Perangkat"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Geser ke atas untuk beralih aplikasi"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tarik ke kanan untuk beralih aplikasi dengan cepat"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktifkan Ringkasan"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Terisi penuh"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Mengisi daya"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index b2e2198..5afc8bc 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Þetta veitir öllum forritum og þjónustum aðgang að myndavélinni þinni."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Þetta veitir öllum forritum og þjónustum aðgang að myndavélinni og hljóðnemanum þínum."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Tæki"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Strjúktu upp til að skipta á milli forrita"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Dragðu til hægri til að skipta hratt á milli forrita"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kveikja/slökkva á yfirliti"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Fullhlaðin"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Í hleðslu"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 42e5dea..9c28363 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare la fotocamera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare la fotocamera o il microfono."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Scorri verso l\'alto per passare ad altre app"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Trascina verso destra per cambiare velocemente app"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Attiva/disattiva la panoramica"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carica"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"In carica"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 731d36c..b7153b1 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -437,8 +437,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במצלמה."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במצלמה או במיקרופון."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"מכשיר"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"יש להחליק מעלה כדי להחליף אפליקציות"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"יש לגרור ימינה כדי לעבור במהירות בין אפליקציות"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"החלפת מצב של מסכים אחרונים"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"הסוללה טעונה"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"בטעינה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index d638ace..a8fb87d 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"カメラの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"カメラやマイクの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"デバイス"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"アプリを切り替えるには上にスワイプ"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"右にドラッグするとアプリを素早く切り替えることができます"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"概要を切り替え"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"充電が完了しました"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電しています"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index aff2521..da4f5bc 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი კამერის გამოყენების უფლება."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი კამერის ან მიკროფონის გამოყენების უფლება."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"მოწყობილობა"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"გადაფურცლეთ ზემოთ აპების გადასართავად"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"აპების სწრაფად გადასართავად ჩავლებით გადაიტანეთ მარჯვნივ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"მიმოხილვის გადართვა"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"დატენილია"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"მიმდინარეობს დატენვა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 674f6a0..c15c6be 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Камераңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Камераңызды немесе микрофоныңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Құрылғы"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Қолданбалар арасында ауысу үшін жоғары сырғытыңыз"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Қолданбаларды жылдам ауыстырып қосу үшін оңға қарай сүйреңіз"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Шолуды қосу/өшіру"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Зарядталды"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарядталуда"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 1d4b515..31de2be 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ការធ្វើបែបនេះនឹងឈប់ទប់ស្កាត់ការចូលប្រើសម្រាប់កម្មវិធី និងសេវាកម្មទាំងអស់ ដែលត្រូវបានអនុញ្ញាតឱ្យប្រើកាមេរ៉ារបស់អ្នក។"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ការធ្វើបែបនេះនឹងឈប់ទប់ស្កាត់ការចូលប្រើសម្រាប់កម្មវិធី និងសេវាកម្មទាំងអស់ ដែលត្រូវបានអនុញ្ញាតឱ្យប្រើកាមេរ៉ា ឬមីក្រូហ្វូនរបស់អ្នក។"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ឧបករណ៍"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"អូសឡើងលើដើម្បីប្តូរកម្មវិធី"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"អូសទៅស្ដាំដើម្បីប្ដូរកម្មវិធីបានរហ័ស"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"បិទ/បើកទិដ្ឋភាពរួម"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"បានសាកថ្មពេញ"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"កំពុងសាកថ្ម"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 264f248..9b9138c 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾ ಅಥವಾ ಮೈಕ್ರೋಫೋನ್ ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ಸಾಧನ"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಬದಲಿಸಲು ತ್ವರಿತವಾಗಿ ಬಲಕ್ಕೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ಟಾಗಲ್ ನ ಅವಲೋಕನ"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index db96984..044086e 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"카메라를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"카메라 또는 마이크를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"기기"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"위로 스와이프하여 앱 전환"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"앱을 빠르게 전환하려면 오른쪽으로 드래그"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"최근 사용 버튼 전환"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"충전됨"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"충전 중"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 42d684e..9c2929d 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Камераны колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Камераңызды же микрофонуңузду колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Түзмөк"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Башка колдонмого которулуу үчүн өйдө сүрүңүз"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Колдонмолорду тез которуштуруу үчүн, оңго сүйрөңүз"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Назар режимин өчүрүү/күйгүзүү"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Кубатталды"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Кубатталууда"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index d6b8fa2..53a0ace 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ນີ້ຈະຍົກເລີກການບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບຂອງທ່ານ."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ນີ້ຈະປົດບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນຂອງທ່ານ."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ອຸປະກອນ"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ປັດຂື້ນເພື່ອສະຫຼັບແອັບ"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ລາກໄປຂວາເພື່ອສະຫຼັບແອັບດ່ວນ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ສະຫຼັບພາບຮວມ"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ສາກເຕັມແລ້ວ."</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ກຳລັງສາກໄຟ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 19e8fbf..56f187e 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -437,8 +437,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti fotoaparatą."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti fotoaparatą ar mikrofoną."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Įrenginys"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Perbraukite aukštyn, kad perjungtumėte programas"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Vilkite į dešinę, kad greitai perjungtumėte programas"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Perjungti apžvalgą"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Įkrautas"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Kraunamas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index f0d26c8..4522b98 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -435,8 +435,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru, varēs tai piekļūt."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru vai mikrofonu, varēs tiem piekļūt."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Ierīce"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Velciet augšup, lai pārslēgtu lietotnes"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Lai ātri pārslēgtu lietotnes, velciet pa labi"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pārskata pārslēgšana"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Akumulators uzlādēts"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Notiek uzlāde"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 719f519..5317bca 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на камерата."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на камерата или микрофонот."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Уред"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Повлечете нагоре за да се префрлите од една на друга апликација"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Повлечете надесно за брзо префрлање меѓу апликациите"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Вклучи/исклучи преглед"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Наполнета"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Се полни"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index cdb3a69..e798c7d 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"നിങ്ങളുടെ ക്യാമറ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"നിങ്ങളുടെ ക്യാമറയോ മൈക്രോഫോണോ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ഉപകരണം"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ആപ്പുകൾ മാറാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ആപ്പുകൾ പെട്ടെന്ന് മാറാൻ വലത്തോട്ട് വലിച്ചിടുക"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"അവലോകനം മാറ്റുക"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ചാർജായി"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ചാർജ് ചെയ്യുന്നു"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index d16e479..0e4cac02 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Энэ нь таны камерыг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Энэ нь таны камер эсвэл микрофоныг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Төхөөрөмж"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Апп сэлгэхийн тулд дээш шударна уу"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Аппуудыг хурдан сэлгэхийн тулд баруун тийш чирнэ үү"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Тоймыг асаах/унтраах"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Цэнэглэгдсэн"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Цэнэглэж байна"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 9578370..45a9a1b 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"हे तुमचा कॅमेरा वापरण्याची परवानगी असलेल्या सर्व ॲप्स आणि सेवांसाठी अॅक्सेस अनब्लॉक करते."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"हे तुमचा कॅमेरा आणि मायक्रोफोन वापरण्याची परवानगी असलेल्या सर्व ॲप्स व सेवांसाठी अॅक्सेस अनब्लॉक करते."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"डिव्हाइस"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"अॅप्स स्विच करण्यासाठी वर स्वाइप करा"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"अॅप्स वर झटपट स्विच करण्यासाठी उजवीकडे ड्रॅग करा"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"अवलोकन टॉगल करा."</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज झाली"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज होत आहे"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 684d718..2349e28 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan kamera anda."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan kamera atau mikrofon anda."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Peranti"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Leret ke atas untuk menukar apl"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Seret ke kanan untuk beralih apl dengan pantas"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Togol Ikhtisar"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Sudah dicas"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Mengecas"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 4dddc71..23de47f 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"၎င်းက သင့်ကင်မရာသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"၎င်းက သင့်ကင်မရာ (သို့) မိုက်ခရိုဖုန်းသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"စက်"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"အက်ပ်များကို ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"အက်ပ်များကို ပြောင်းရန် ညာဘက်သို့ ဖိဆွဲပါ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ဖွင့်၊ ပိတ် အနှစ်ချုပ်"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"အားသွင်းပြီး"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"အားသွင်းနေ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a0db779..9c18b95 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke kameraet."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke kameraet eller mikrofonen."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Sveip opp for å bytte apper"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Dra til høyre for å bytte apper raskt"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå oversikten av eller på"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Oppladet"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Lader"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d719123..9ae2d43e2 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"यसो गर्नुभयो भने क्यामेरा प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"यसो गर्नुभयो भने क्यामेरा वा माइक्रोफोन प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"यन्त्र"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"एपहरू बदल्न माथितिर स्वाइप गर्नुहोस्"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"एपहरू बदल्न द्रुत गतिमा दायाँतिर ड्र्याग गर्नुहोस्"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"परिदृश्य टगल गर्नुहोस्"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज भयो"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज हुँदै छ"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index b74892a..155d1ad 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je camera te gebruiken."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je camera of microfoon te gebruiken."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Apparaat"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe omhoog om te schakelen tussen apps"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Sleep naar rechts om snel tussen apps te schakelen"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Overzicht aan- of uitzetten"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Opgeladen"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Opladen"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index b8a104f..4d44690b 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ଆପଣଙ୍କ କ୍ୟାମେରାକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ଆପଣଙ୍କ କ୍ୟାମେରା କିମ୍ବା ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ଡିଭାଇସ୍"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ଆପ୍କୁ ବଦଳ କରିବା ପାଇଁ ସ୍ଵାଇପ୍ କରନ୍ତୁ"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ଆପ୍ଗୁଡ଼ିକ ମଧ୍ୟରେ ଶୀଘ୍ର ବଦଳ କରିବା ପାଇଁ ଡାହାଣକୁ ଡ୍ରାଗ୍ କରନ୍ତୁ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀକୁ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ଚାର୍ଜ ହୋଇଗଲା"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ଚାର୍ଜ କରାଯାଉଛି"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 45c4f0f..7bb60a0 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਜਾਂ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"ਡੀਵਾਈਸ"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ਐਪਾਂ ਵਿਚਾਲੇ ਤੇਜ਼ੀ ਨਾਲ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ਰੂਪ-ਰੇਖਾ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ਚਾਰਜ ਹੋਇਆ"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ਚਾਰਜ ਕਰ ਰਿਹਾ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b8da6bb..ea6f225 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -437,8 +437,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z aparatu."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z aparatu lub mikrofonu."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Urządzenie"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Przesuń w górę, by przełączyć aplikacje"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Szybko przeciągnij w prawo, by przełączyć aplikacje"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Przełącz Przegląd"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Naładowana"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Ładowanie"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 2755508..2f1501b 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera ou seu microfone."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Deslize para cima para mudar de app"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arraste para a direita para mudar rapidamente de app"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregado"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Carregando"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 15c2874..563e99d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar a sua câmara."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar a sua câmara ou microfone."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Deslizar rapidamente para cima para mudar de app"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arraste para a direita para mudar rapidamente de app."</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ativar/desativar Vista geral"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"A carregar"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 2755508..2f1501b 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera ou seu microfone."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Deslize para cima para mudar de app"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arraste para a direita para mudar rapidamente de app"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregado"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Carregando"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index cf957a4..2102600 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -435,8 +435,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi camera sau microfonul."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Dispozitiv"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Glisați în sus pentru a comuta între aplicații"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Glisați la dreapta pentru a comuta rapid între aplicații"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Comutați secțiunea Recente"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Încărcată"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Se încarcă"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9fd91f1..eeb1f3e 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -437,8 +437,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование камеры."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование камеры или микрофона."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Чтобы переключиться между приложениями, проведите по экрану вверх."</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Перетащите вправо, чтобы быстро переключиться между приложениями"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Переключить режим обзора"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Батарея заряжена"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарядка батареи"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 4235d81..247b7a5 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"මෙය ඔබගේ කැමරාව භාවිතා කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්රවේශය අවහිර කිරීම ඉවත් කරයි."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"මෙය ඔබගේ කැමරාව හෝ මයික්රෆෝනය භාවිත කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්රවේශය අවහිර කිරීම ඉවත් කරයි."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"උපාංගය"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"යෙදුම් මාරු කිරීමට ස්වයිප් කරන්න"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ඉක්මනින් යෙදුම් මාරු කිරීමට දකුණට අදින්න"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"දළ විශ්ලේෂණය ටොගල කරන්න"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"අරෝපිතයි"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ආරෝපණය වෙමින්"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 14aa0a7..74b24bd 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -437,8 +437,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát alebo mikrofón."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Zariadenie"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Potiahnutím nahor prepnete aplikácie"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Presunutím doprava rýchlo prepnete aplikácie"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Prepnúť prehľad"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Nabitá"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nabíja sa"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index a553ff22..cfb89d4 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -437,8 +437,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo fotoaparata."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo fotoaparata ali mikrofona."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Naprava"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Za preklop aplikacij povlecite navzgor"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Povlecite v desno za hiter preklop med aplikacijami"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Vklop/izklop pregleda"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Baterija napolnjena"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Polnjenje"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 5ce3cd4..f7753c7 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin kamerën tënde."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin kamerën ose mikrofonin tënd."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Pajisja"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Rrëshqit shpejt lart për të ndërruar aplikacionet"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Zvarrit djathtas për të ndërruar aplikacionet me shpejtësi"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kalo te përmbledhja"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"I karikuar"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Po karikohet"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 282d18b..73ecc4c 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -435,8 +435,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење камере."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење камере или микрофона."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Уређај"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Превуците нагоре да бисте мењали апликације"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Превуците удесно да бисте брзо променили апликације"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Укључи/искључи преглед"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Напуњена је"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Пуни се"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 7e0dbd7..1f60b3a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda kameran."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda kameran eller mikrofonen."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Byt appar genom att svepa uppåt"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tryck och dra åt höger för att snabbt byta mellan appar"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktivera och inaktivera översikten"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Laddat"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laddar"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index e603fc9..7ac26be4 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie kamera yako."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie kamera au maikrofoni yako."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Kifaa"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Telezesha kidole juu ili ubadilishe programu"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Buruta kulia ili ubadilishe programu haraka"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Washa Muhtasari"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Betri imejaa"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Inachaji"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index d1d6d0d..426ddd4 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"உங்கள் கேமராவைப் பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"உங்கள் கேமராவையோ மைக்ரோஃபோனையோ பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"சாதனம்"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ஆப்ஸிற்கு இடையே மாற்றுவதற்கு, மேல்நோக்கி ஸ்வைப் செய்க"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ஆப்ஸை வேகமாக மாற்ற, வலப்புறம் இழுக்கவும்"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"மேலோட்டப் பார்வையை நிலைமாற்று"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"சார்ஜ் செய்யப்பட்டது"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"சார்ஜ் ஆகிறது"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 2bc2923..020d9b4 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"మీ కెమెరాను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లు, సర్వీస్లకు యాక్సెస్ను ఇది అన్బ్లాక్ చేస్తుంది."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"మీ కెమెరాను లేదా మైక్రోఫోన్ను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లు, సర్వీస్లకు యాక్సెస్ను ఇది అన్బ్లాక్ చేస్తుంది."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"పరికరం"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"యాప్లను మార్చడం కోసం ఎగువకు స్వైప్ చేయండి"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"యాప్లను శీఘ్రంగా స్విచ్ చేయడానికి కుడి వైపుకు లాగండి"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"స్థూలదృష్టిని టోగుల్ చేయి"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ఛార్జ్ చేయబడింది"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ఛార్జ్ అవుతోంది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 69b4999..ce469f7 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้กล้องของคุณ"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้กล้องหรือไมโครโฟนของคุณ"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"อุปกรณ์"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"เลื่อนขึ้นเพื่อสลับแอป"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ลากไปทางขวาเพื่อสลับแอปอย่างรวดเร็ว"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"สลับภาพรวม"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ชาร์จแล้ว"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"กำลังชาร์จ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d65f16d..8d0a847 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong camera o mikropono."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Mag-swipe pataas upang lumipat ng app"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"I-drag pakanan para mabilisang magpalipat-lipat ng app"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"I-toggle ang Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Tapos nang mag-charge"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nagcha-charge"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index bbae9c9..6b55d1c 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Bu işlem, kameranızı kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Bu işlem, kamera veya mikrofonunuzu kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Uygulamalar arasında geçiş yapmak için yukarı kaydırın"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Uygulamaları hızlıca değiştirmek için sağa kaydırın"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Genel bakışı aç/kapat"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Şarj oldu"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Şarj oluyor"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d4d1816..0a5992b 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -437,8 +437,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою, отримають доступ."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою чи мікрофоном, отримають доступ."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Пристрій"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Проводьте пальцем угору, щоб переходити між додатками"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Перетягуйте праворуч, щоб швидко переходити між додатками"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Увімкнути або вимкнути огляд"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Заряджено"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Заряджається"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index e8cb657..5a96fa8 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"اس سے آپ کا کیمرا استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"اس سے آپ کا کیمرا یا مائیکروفون استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"آلہ"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ایپس سوئچ کرنے کیلئے اوپر سوائپ کریں"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"تیزی سے ایپس کو سوئچ کرنے کے لیے دائیں طرف گھسیٹیں"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"مجموعی جائزہ ٹوگل کریں"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"چارج ہوگئی"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"چارج ہو رہی ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index b722acc..d96ea064 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamerangizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera va mikrofoningizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Qurilma"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Ilovalarni almashtirish uchun ekranni tepaga suring"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Ilovalarni tezkor almashtirish uchun o‘ngga torting"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Umumiy nazar rejimini almashtirish"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Quvvat oldi"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Quvvat olmoqda"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index de7fbcbe..54b4967 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng máy ảnh của bạn."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng máy ảnh hoặc micrô của bạn."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Thiết bị"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Vuốt lên để chuyển đổi ứng dụng"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Kéo sang phải để chuyển đổi nhanh giữa các ứng dụng"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Bật/tắt chế độ xem Tổng quan"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Đã sạc đầy"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Đang sạc"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index e432c62..3cbcf31 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"这将会为所有获准使用您摄像头的应用和服务启用这项权限。"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"这将会为所有获准使用您的摄像头或麦克风的应用和服务启用这项权限。"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"设备"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑动可切换应用"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖动可快速切换应用"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切换概览"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"已充满"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"正在充电"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index ea9f1fc..726947f 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的相機。"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的相機或麥克風。"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑動即可切換應用程式"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖曳即可快速切換應用程式"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換概覽"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"已完成充電"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電中"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 7e9d2fe..437bece 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"這麼做可允許所有應用程式和服務使用相機。"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"這麼做可允許所有應用程式和服務使用相機或麥克風。"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑動即可切換應用程式"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖曳即可快速切換應用程式"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換總覽"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"已充飽"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電中"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index eac6f74..6b7d577 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -433,8 +433,6 @@
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa ikhamera yakho."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa ikhamera yakho noma imakrofoni."</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Idivayisi"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swayiphela phezulu ukuze ushintshe izinhlelo zokusebenza"</string>
- <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Hudula ngqo ukuze ushintshe ngokushesha izinhlelo zokusebenza"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Guqula ukubuka konke"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Kushajiwe"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Iyashaja"</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginEnabler.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginEnabler.java
index 01b012d..1c5da82 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginEnabler.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginEnabler.java
@@ -24,9 +24,9 @@
int ENABLED = 0;
int DISABLED_MANUALLY = 1;
- int DISABLED_INVALID_VERSION = 1;
- int DISABLED_FROM_EXPLICIT_CRASH = 2;
- int DISABLED_FROM_SYSTEM_CRASH = 3;
+ int DISABLED_INVALID_VERSION = 2;
+ int DISABLED_FROM_EXPLICIT_CRASH = 3;
+ int DISABLED_FROM_SYSTEM_CRASH = 4;
@IntDef({ENABLED, DISABLED_MANUALLY, DISABLED_INVALID_VERSION, DISABLED_FROM_EXPLICIT_CRASH,
DISABLED_FROM_SYSTEM_CRASH})
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
index f5ed9da..2b4cdd6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
@@ -197,10 +197,12 @@
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ mContext.registerReceiver(this, filter);
filter.addAction(PLUGIN_CHANGED);
filter.addAction(DISABLE_PLUGIN);
filter.addDataScheme("package");
- mContext.registerReceiver(this, filter);
+ mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null);
filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiver(this, filter);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index c89cda9..92f89d6 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -134,11 +134,15 @@
};
@Override
+ protected void onInit() {
+ mIsDozing = mStatusBarStateController.isDozing();
+ }
+
+ @Override
protected void onViewAttached() {
updateLocale();
mBroadcastDispatcher.registerReceiver(mLocaleBroadcastReceiver,
new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
- mIsDozing = mStatusBarStateController.isDozing();
mDozeAmount = mStatusBarStateController.getDozeAmount();
mBatteryController.addCallback(mBatteryCallback);
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 8032839..310a0d3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -123,10 +123,13 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -469,16 +472,39 @@
List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */);
// Hack level over 9000: Because the subscription id is not yet valid when we see the
- // first update in handleSimStateChange, we need to force refresh all all SIM states
+ // first update in handleSimStateChange, we need to force refresh all SIM states
// so the subscription id for them is consistent.
ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>();
+ Set<Integer> activeSubIds = new HashSet<>();
for (int i = 0; i < subscriptionInfos.size(); i++) {
SubscriptionInfo info = subscriptionInfos.get(i);
+ activeSubIds.add(info.getSubscriptionId());
boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex());
if (changed) {
changedSubscriptions.add(info);
}
}
+
+ // It is possible for active subscriptions to become invalid (-1), and these will not be
+ // present in the subscriptionInfo list
+ Iterator<Map.Entry<Integer, SimData>> iter = mSimDatas.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry<Integer, SimData> simData = iter.next();
+ if (!activeSubIds.contains(simData.getKey())) {
+ Log.i(TAG, "Previously active sub id " + simData.getKey() + " is now invalid, "
+ + "will remove");
+ iter.remove();
+
+ SimData data = simData.getValue();
+ for (int j = 0; j < mCallbacks.size(); j++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
+ if (cb != null) {
+ cb.onSimStateChanged(data.subId, data.slotId, data.simState);
+ }
+ }
+ }
+ }
+
for (int i = 0; i < changedSubscriptions.size(); i++) {
SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
for (int j = 0; j < mCallbacks.size(); j++) {
@@ -3339,6 +3365,7 @@
pw.println(" trustManaged=" + getUserTrustIsManaged(userId));
pw.println(" udfpsEnrolled=" + isUdfpsEnrolled());
pw.println(" mFingerprintLockedOut=" + mFingerprintLockedOut);
+ pw.println(" mFingerprintLockedOutPermanent=" + mFingerprintLockedOutPermanent);
pw.println(" enabledByUser=" + mBiometricEnabledForUser.get(userId));
if (isUdfpsEnrolled()) {
pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true));
@@ -3360,8 +3387,11 @@
+ getStrongAuthTracker().hasUserAuthenticatedSinceBoot());
pw.println(" disabled(DPM)=" + isFaceDisabled(userId));
pw.println(" possible=" + isUnlockWithFacePossible(userId));
+ pw.println(" listening: actual=" + mFaceRunningState
+ + " expected=(" + (shouldListenForFace() ? 1 : 0));
pw.println(" strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
pw.println(" trustManaged=" + getUserTrustIsManaged(userId));
+ pw.println(" mFaceLockedOutPermanent=" + mFaceLockedOutPermanent);
pw.println(" enabledByUser=" + mBiometricEnabledForUser.get(userId));
pw.println(" mSecureCameraLaunched=" + mSecureCameraLaunched);
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index c70281d..9c87fc4 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -140,7 +140,6 @@
import javax.inject.Inject;
import javax.inject.Named;
-import javax.inject.Provider;
import dagger.Lazy;
@@ -200,12 +199,6 @@
public static final String ALLOW_NOTIFICATION_LONG_PRESS_NAME = "allow_notif_longpress";
/**
- * A provider of {@link EdgeBackGestureHandler}.
- */
- public static final String EDGE_BACK_GESTURE_HANDLER_PROVIDER_NAME =
- "edge_back_gesture_handler_provider";
-
- /**
* Key for getting a background Looper for background work.
*/
public static final DependencyKey<Looper> BG_LOOPER = new DependencyKey<>(BG_LOOPER_NAME);
@@ -240,12 +233,6 @@
*/
public static final DependencyKey<String> LEAK_REPORT_EMAIL =
new DependencyKey<>(LEAK_REPORT_EMAIL_NAME);
- /**
- * Key for retrieving an Provider<EdgeBackGestureHandler>.
- */
- public static final DependencyKey<Provider<EdgeBackGestureHandler>>
- EDGE_BACK_GESTURE_HANDLER_PROVIDER =
- new DependencyKey<>(EDGE_BACK_GESTURE_HANDLER_PROVIDER_NAME);
private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>();
private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>();
@@ -372,7 +359,7 @@
@Inject Lazy<TelephonyListenerManager> mTelephonyListenerManager;
@Inject Lazy<SystemStatusAnimationScheduler> mSystemStatusAnimationSchedulerLazy;
@Inject Lazy<PrivacyDotViewController> mPrivacyDotViewControllerLazy;
- @Inject Provider<EdgeBackGestureHandler> mEdgeBackGestureHandlerProvider;
+ @Inject Lazy<EdgeBackGestureHandler.Factory> mEdgeBackGestureHandlerFactoryLazy;
@Inject Lazy<UiEventLogger> mUiEventLogger;
@Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
@@ -587,7 +574,8 @@
mProviders.put(SystemStatusAnimationScheduler.class,
mSystemStatusAnimationSchedulerLazy::get);
mProviders.put(PrivacyDotViewController.class, mPrivacyDotViewControllerLazy::get);
- mProviders.put(EDGE_BACK_GESTURE_HANDLER_PROVIDER, () -> mEdgeBackGestureHandlerProvider);
+ mProviders.put(EdgeBackGestureHandler.Factory.class,
+ mEdgeBackGestureHandlerFactoryLazy::get);
mProviders.put(UiEventLogger.class, mUiEventLogger::get);
mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 71e2bb6..0ce1846 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -37,6 +37,7 @@
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
+import android.hardware.display.DisplayManager;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintManager;
@@ -57,6 +58,7 @@
import com.android.systemui.SystemUI;
import com.android.systemui.assist.ui.DisplayUtils;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.statusbar.CommandQueue;
@@ -423,7 +425,9 @@
@Nullable FingerprintManager fingerprintManager,
@Nullable FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory,
- Provider<SidefpsController> sidefpsControllerFactory) {
+ Provider<SidefpsController> sidefpsControllerFactory,
+ @NonNull DisplayManager displayManager,
+ @Main Handler handler) {
super(context);
mCommandQueue = commandQueue;
mActivityTaskManager = activityTaskManager;
@@ -432,10 +436,13 @@
mUdfpsControllerFactory = udfpsControllerFactory;
mSidefpsControllerFactory = sidefpsControllerFactory;
mWindowManager = windowManager;
- mOrientationListener = new BiometricOrientationEventListener(context, () -> {
- onOrientationChanged();
- return Unit.INSTANCE;
- });
+ mOrientationListener = new BiometricOrientationEventListener(context,
+ () -> {
+ onOrientationChanged();
+ return Unit.INSTANCE;
+ },
+ displayManager,
+ handler);
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
index 08ea857..98a03a1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricOrientationEventListener.kt
@@ -17,7 +17,10 @@
package com.android.systemui.biometrics
import android.content.Context
+import android.hardware.display.DisplayManager
+import android.os.Handler
import android.view.OrientationEventListener
+import android.view.Surface
/**
* An [OrientationEventListener] that invokes the [onOrientationChanged] callback whenever
@@ -26,20 +29,16 @@
*/
class BiometricOrientationEventListener(
private val context: Context,
- private val onOrientationChanged: () -> Unit
-) : OrientationEventListener(context) {
+ private val onOrientationChanged: () -> Unit,
+ private val displayManager: DisplayManager,
+ private val handler: Handler
+) : DisplayManager.DisplayListener {
- /** If actively listening (not available in base class). */
- var enabled: Boolean = false
- private set
+ private var lastRotation = context.display?.rotation ?: Surface.ROTATION_0
- private var lastRotation = context.display?.rotation ?: ORIENTATION_UNKNOWN
-
- override fun onOrientationChanged(orientation: Int) {
- if (orientation == ORIENTATION_UNKNOWN) {
- return
- }
-
+ override fun onDisplayAdded(displayId: Int) {}
+ override fun onDisplayRemoved(displayId: Int) {}
+ override fun onDisplayChanged(displayId: Int) {
val rotation = context.display?.rotation ?: return
if (lastRotation != rotation) {
lastRotation = rotation
@@ -48,13 +47,11 @@
}
}
- override fun enable() {
- enabled = true
- super.enable()
+ fun enable() {
+ displayManager.registerDisplayListener(this, handler)
}
- override fun disable() {
- enabled = false
- super.disable()
+ fun disable() {
+ displayManager.unregisterDisplayListener(this)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
index a51c2b8..8f6e249 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.java
@@ -23,9 +23,11 @@
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.PixelFormat;
+import android.hardware.display.DisplayManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.ISidefpsController;
+import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
@@ -93,16 +95,22 @@
@NonNull LayoutInflater inflater,
@Nullable FingerprintManager fingerprintManager,
@NonNull WindowManager windowManager,
- @Main DelayableExecutor fgExecutor) {
+ @Main DelayableExecutor fgExecutor,
+ @NonNull DisplayManager displayManager,
+ @Main Handler handler) {
mContext = context;
mInflater = inflater;
mFingerprintManager = checkNotNull(fingerprintManager);
mWindowManager = windowManager;
mFgExecutor = fgExecutor;
- mOrientationListener = new BiometricOrientationEventListener(context, () -> {
- onOrientationChanged();
- return Unit.INSTANCE;
- });
+ mOrientationListener = new BiometricOrientationEventListener(
+ context,
+ () -> {
+ onOrientationChanged();
+ return Unit.INSTANCE;
+ },
+ displayManager,
+ handler);
mSensorProps = findFirstSidefps();
checkArgument(mSensorProps != null);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 3c3dfec..950bd83 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -32,6 +32,7 @@
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.RectF;
+import android.hardware.display.DisplayManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -519,7 +520,9 @@
@NonNull UdfpsHapticsSimulator udfpsHapticsSimulator,
@NonNull Optional<UdfpsHbmProvider> hbmProvider,
@NonNull KeyguardStateController keyguardStateController,
- @NonNull KeyguardBypassController keyguardBypassController) {
+ @NonNull KeyguardBypassController keyguardBypassController,
+ @NonNull DisplayManager displayManager,
+ @Main Handler mainHandler) {
mContext = context;
mExecution = execution;
// TODO (b/185124905): inject main handler and vibrator once done prototyping
@@ -545,10 +548,14 @@
mHbmProvider = hbmProvider.orElse(null);
screenLifecycle.addObserver(mScreenObserver);
mScreenOn = screenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_ON;
- mOrientationListener = new BiometricOrientationEventListener(context, () -> {
- onOrientationChanged();
- return Unit.INSTANCE;
- });
+ mOrientationListener = new BiometricOrientationEventListener(
+ context,
+ () -> {
+ onOrientationChanged();
+ return Unit.INSTANCE;
+ },
+ displayManager,
+ mainHandler);
mKeyguardBypassController = keyguardBypassController;
mSensorProps = findFirstUdfps();
@@ -662,7 +669,8 @@
// Transform dimensions if the device is in landscape mode
switch (mContext.getDisplay().getRotation()) {
case Surface.ROTATION_90:
- if (animation instanceof UdfpsKeyguardViewController) {
+ if (animation instanceof UdfpsKeyguardViewController
+ && mKeyguardUpdateMonitor.isGoingToSleep()) {
break;
}
mCoreLayoutParams.x = mSensorProps.sensorLocationY - mSensorProps.sensorRadius
@@ -672,7 +680,8 @@
break;
case Surface.ROTATION_270:
- if (animation instanceof UdfpsKeyguardViewController) {
+ if (animation instanceof UdfpsKeyguardViewController
+ && mKeyguardUpdateMonitor.isGoingToSleep()) {
break;
}
mCoreLayoutParams.x = p.x - mSensorProps.sensorLocationY - mSensorProps.sensorRadius
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 51124fb..6435bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -377,6 +377,9 @@
@Override
public boolean onTouch(MotionEvent event) {
+ if (mTransitionToFullShadeProgress != 0) {
+ return false;
+ }
return mUdfpsController.onTouch(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index c840c7a..61e8033 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -18,7 +18,6 @@
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -340,7 +339,8 @@
mNavColorSampleMargin = getResources()
.getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
- mEdgeBackGestureHandler = Dependency.get(EDGE_BACK_GESTURE_HANDLER_PROVIDER).get();
+ mEdgeBackGestureHandler = Dependency.get(EdgeBackGestureHandler.Factory.class)
+ .create(mContext);
mEdgeBackGestureHandler.setStateChangeCallback(this::updateStates);
mRegionSamplingHelper = new RegionSamplingHelper(this,
new RegionSamplingHelper.SamplingCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 3fc6a3a..aaa3bf0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -292,8 +292,8 @@
}
};
- @Inject
- public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
+
+ EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor,
BroadcastDispatcher broadcastDispatcher, ProtoTracer protoTracer,
NavigationModeController navigationModeController, ViewConfiguration viewConfiguration,
@@ -942,6 +942,53 @@
proto.edgeBackGestureHandler.allowGesture = mAllowGesture;
}
+ /**
+ * Injectable instance to create a new EdgeBackGestureHandler.
+ *
+ * Necessary because we don't have good handling of per-display contexts at the moment. With
+ * this, you can pass in a specific context that knows what display it is in.
+ */
+ public static class Factory {
+ private final OverviewProxyService mOverviewProxyService;
+ private final SysUiState mSysUiState;
+ private final PluginManager mPluginManager;
+ private final Executor mExecutor;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+ private final ProtoTracer mProtoTracer;
+ private final NavigationModeController mNavigationModeController;
+ private final ViewConfiguration mViewConfiguration;
+ private final WindowManager mWindowManager;
+ private final IWindowManager mWindowManagerService;
+ private final FalsingManager mFalsingManager;
+
+ @Inject
+ public Factory(OverviewProxyService overviewProxyService,
+ SysUiState sysUiState, PluginManager pluginManager, @Main Executor executor,
+ BroadcastDispatcher broadcastDispatcher, ProtoTracer protoTracer,
+ NavigationModeController navigationModeController,
+ ViewConfiguration viewConfiguration, WindowManager windowManager,
+ IWindowManager windowManagerService, FalsingManager falsingManager) {
+ mOverviewProxyService = overviewProxyService;
+ mSysUiState = sysUiState;
+ mPluginManager = pluginManager;
+ mExecutor = executor;
+ mBroadcastDispatcher = broadcastDispatcher;
+ mProtoTracer = protoTracer;
+ mNavigationModeController = navigationModeController;
+ mViewConfiguration = viewConfiguration;
+ mWindowManager = windowManager;
+ mWindowManagerService = windowManagerService;
+ mFalsingManager = falsingManager;
+ }
+
+ /** Construct a {@link EdgeBackGestureHandler}. */
+ public EdgeBackGestureHandler create(Context context) {
+ return new EdgeBackGestureHandler(context, mOverviewProxyService, mSysUiState,
+ mPluginManager, mExecutor, mBroadcastDispatcher, mProtoTracer,
+ mNavigationModeController, mViewConfiguration, mWindowManager,
+ mWindowManagerService, mFalsingManager);
+ }
+ }
private static class LogArray extends ArrayDeque<String> {
private final int mLength;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index ab81ac1..82b6c0c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -153,25 +153,9 @@
});
}
- @Nullable
- private CharSequence getServiceLabelSafe() {
- try {
- return mController.getWalletClient().getServiceLabel();
- } catch (RuntimeException e) {
- Log.e(TAG, "Failed to get the service label safely, recreating wallet client", e);
- mController.reCreateWalletClient();
- try {
- return mController.getWalletClient().getServiceLabel();
- } catch (RuntimeException e2) {
- Log.e(TAG, "The QAW service label is broken.", e2);
- return null;
- }
- }
- }
-
@Override
protected void handleUpdateState(State state, Object arg) {
- CharSequence label = getServiceLabelSafe();
+ CharSequence label = mController.getWalletClient().getServiceLabel();
state.label = label == null ? mLabel : label;
state.contentDescription = state.label;
Drawable tileIcon = mController.getWalletClient().getTileIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 44399a1..4d15a0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -94,7 +94,7 @@
* Controls the indications and error messages shown on the Keyguard
*/
@SysUISingleton
-public class KeyguardIndicationController implements KeyguardStateController.Callback {
+public class KeyguardIndicationController {
private static final String TAG = "KeyguardIndication";
private static final boolean DEBUG_CHARGING_SPEED = false;
@@ -206,7 +206,7 @@
mKeyguardUpdateMonitor.registerCallback(getKeyguardCallback());
mKeyguardUpdateMonitor.registerCallback(mTickReceiver);
mStatusBarStateController.addCallback(mStatusBarStateListener);
- mKeyguardStateController.addCallback(this);
+ mKeyguardStateController.addCallback(mKeyguardStateCallback);
mStatusBarStateListener.onDozingChanged(mStatusBarStateController.isDozing());
}
@@ -827,11 +827,6 @@
mRotateTextViewController.dump(fd, pw, args);
}
- @Override
- public void onUnlockedChanged() {
- updateIndication(false);
- }
-
protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
public static final int HIDE_DELAY_MS = 5000;
@@ -890,10 +885,7 @@
mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
- if (biometricSourceType == BiometricSourceType.FACE
- && shouldSuppressFaceMsgAndShowTryFingerprintMsg()) {
- // suggest trying fingerprint
- showTransientIndication(R.string.keyguard_try_fingerprint);
+ if (biometricSourceType == BiometricSourceType.FACE && shouldSuppressFaceMsg()) {
return;
}
showTransientIndication(helpString, false /* isError */, showSwipeToUnlock);
@@ -911,11 +903,9 @@
return;
}
if (biometricSourceType == BiometricSourceType.FACE
- && shouldSuppressFaceMsgAndShowTryFingerprintMsg()
+ && shouldSuppressFaceMsg()
&& !mStatusBarKeyguardViewManager.isBouncerShowing()
&& mKeyguardUpdateMonitor.isScreenOn()) {
- // suggest trying fingerprint
- showTransientIndication(R.string.keyguard_try_fingerprint);
return;
}
if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
@@ -966,11 +956,9 @@
|| msgId == FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED);
}
- private boolean shouldSuppressFaceMsgAndShowTryFingerprintMsg() {
- // For dual biometric, don't show face auth messages unless face auth was explicitly
- // requested by the user.
+ private boolean shouldSuppressFaceMsg() {
+ // For dual biometric, don't show face auth messages
return mKeyguardUpdateMonitor.isFingerprintDetectionRunning()
- && !mKeyguardUpdateMonitor.isFaceAuthUserRequested()
&& mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
true /* isStrongBiometric */);
}
@@ -1068,4 +1056,20 @@
updateIndication(false);
}
};
+
+ private KeyguardStateController.Callback mKeyguardStateCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onUnlockedChanged() {
+ updateIndication(false);
+ }
+
+ @Override
+ public void onKeyguardShowingChanged() {
+ if (!mKeyguardStateController.isShowing()) {
+ mTopIndicationView.clearMessages();
+ mLockScreenIndicationView.clearMessages();
+ }
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 28bdd5f..db553e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -89,6 +89,9 @@
private var prevShadeDirection = 0
private var prevShadeVelocity = 0f
+ // Only for dumpsys
+ private var lastAppliedBlur = 0
+
@VisibleForTesting
var shadeSpring = DepthAnimation()
var shadeAnimation = DepthAnimation()
@@ -201,6 +204,7 @@
val opaque = scrimsVisible && !blursDisabledForAppLaunch
Trace.traceCounter(Trace.TRACE_TAG_APP, "shade_blur_radius", blur)
blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur, opaque)
+ lastAppliedBlur = blur
try {
if (root.isAttachedToWindow && root.windowToken != null) {
wallpaperManager.setWallpaperZoomOut(root.windowToken, zoomOut)
@@ -271,6 +275,11 @@
brightnessMirrorSpring.finishIfRunning()
}
}
+
+ override fun onDozeAmountChanged(linear: Float, eased: Float) {
+ wakeAndUnlockBlurRadius = blurUtils.blurRadiusOfRatio(eased)
+ scheduleUpdate()
+ }
}
init {
@@ -428,6 +437,9 @@
it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
it.println("blursDisabledForAppLaunch: $blursDisabledForAppLaunch")
+ it.println("qsPanelExpansion: $qsPanelExpansion")
+ it.println("transitionToFullShadeProgress: $transitionToFullShadeProgress")
+ it.println("lastAppliedBlur: $lastAppliedBlur")
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index 1789743..f1cde8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -62,6 +62,14 @@
}
/**
+ * Clears message queue.
+ */
+ public void clearMessages() {
+ mMessages.clear();
+ mKeyguardIndicationInfo.clear();
+ }
+
+ /**
* Changes the text with an animation and makes sure a single indication is shown long enough.
*/
public void switchIndication(int textResId) {
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 db7ead7..63390f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4178,7 +4178,7 @@
private void vibrateForCameraGesture() {
// Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
- mVibrator.vibrate(mCameraLaunchGestureVibrationEffect);
+ mVibrator.vibrate(mCameraLaunchGestureVibrationEffect, VIBRATION_ATTRIBUTES);
}
private static VibrationEffect getCameraGestureVibrationEffect(Vibrator vibrator,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 4167287..a5b868b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -199,10 +199,9 @@
// We currently draw both the light reveal scrim, and the AOD UI, in the shade. If it's
// already expanded and showing notifications/QS, the animation looks really messy. For now,
- // disable it if the notification panel is expanded.
+ // disable it if the notification panel is not fully collapsed.
if (!this::statusBar.isInitialized ||
- statusBar.notificationPanelViewController.isFullyExpanded ||
- statusBar.notificationPanelViewController.isExpanding) {
+ !statusBar.notificationPanelViewController.isFullyCollapsed) {
return false
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 4e921a0..c94eaed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -539,6 +539,13 @@
mSecondaryUser = userInfo.id;
}
unpauseRefreshUsers = true;
+ if (mGuestUserAutoCreated) {
+ // Guest user must be scheduled for creation AFTER switching to the target user.
+ // This avoids lock contention which will produce UX bugs on the keyguard
+ // (b/193933686).
+ // TODO(b/191067027): Move guest user recreation to system_server
+ guaranteeGuestPresent();
+ }
} else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_NULL);
@@ -670,10 +677,6 @@
switchToUserId(newGuestId);
mUserManager.removeUser(currentUser.id);
} else {
- if (mGuestUserAutoCreated) {
- // TODO(b/191067027): Move guest recreation to system_server
- scheduleGuestCreation();
- }
switchToUserId(targetUserId);
mUserManager.removeUser(currentUser.id);
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
index 843630b..c3b4fbe 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
@@ -197,8 +197,10 @@
.collect(Collectors.toList());
OverlayManagerTransaction.Builder transaction = getTransactionBuilder();
+ HashSet<OverlayIdentifier> identifiersPending = new HashSet<>();
if (pendingCreation != null) {
for (FabricatedOverlay overlay : pendingCreation) {
+ identifiersPending.add(overlay.getIdentifier());
transaction.registerFabricatedOverlay(overlay);
}
}
@@ -206,14 +208,14 @@
for (Pair<String, String> packageToDisable : overlaysToDisable) {
OverlayIdentifier overlayInfo = new OverlayIdentifier(packageToDisable.second);
setEnabled(transaction, overlayInfo, packageToDisable.first, currentUser,
- managedProfiles, false);
+ managedProfiles, false, identifiersPending.contains(overlayInfo));
}
for (String category : THEME_CATEGORIES) {
if (categoryToPackage.containsKey(category)) {
OverlayIdentifier overlayInfo = categoryToPackage.get(category);
setEnabled(transaction, overlayInfo, category, currentUser, managedProfiles,
- true);
+ true, identifiersPending.contains(overlayInfo));
}
}
@@ -233,7 +235,7 @@
@AnyThread
private void setEnabled(OverlayManagerTransaction.Builder transaction,
OverlayIdentifier identifier, String category, int currentUser,
- Set<UserHandle> managedProfiles, boolean enabled) {
+ Set<UserHandle> managedProfiles, boolean enabled, boolean pendingCreation) {
if (DEBUG) {
Log.d(TAG, "setEnabled: " + identifier.getPackageName() + " category: "
+ category + ": " + enabled);
@@ -241,7 +243,7 @@
OverlayInfo overlayInfo = mOverlayManager.getOverlayInfo(identifier,
UserHandle.of(currentUser));
- if (overlayInfo == null) {
+ if (overlayInfo == null && !pendingCreation) {
Log.i(TAG, "Won't enable " + identifier + ", it doesn't exist for user"
+ currentUser);
return;
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
index 0ecc4e2..4a4f2e9 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
@@ -31,8 +31,10 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.time.SystemClock;
import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
@@ -52,9 +54,11 @@
}
private static final String TAG = "QAWController";
+ private static final long RECREATION_TIME_WINDOW = TimeUnit.MINUTES.toMillis(10L);
private final Context mContext;
private final Executor mExecutor;
private final SecureSettings mSecureSettings;
+ private final SystemClock mClock;
private QuickAccessWalletClient mQuickAccessWalletClient;
private ContentObserver mWalletPreferenceObserver;
@@ -62,17 +66,21 @@
private int mWalletPreferenceChangeEvents = 0;
private int mDefaultPaymentAppChangeEvents = 0;
private boolean mWalletEnabled = false;
+ private long mQawClientCreatedTimeMillis;
@Inject
public QuickAccessWalletController(
Context context,
@Main Executor executor,
SecureSettings secureSettings,
- QuickAccessWalletClient quickAccessWalletClient) {
+ QuickAccessWalletClient quickAccessWalletClient,
+ SystemClock clock) {
mContext = context;
mExecutor = executor;
mSecureSettings = secureSettings;
mQuickAccessWalletClient = quickAccessWalletClient;
+ mClock = clock;
+ mQawClientCreatedTimeMillis = mClock.elapsedRealtime();
}
/**
@@ -143,6 +151,11 @@
*/
public void queryWalletCards(
QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) {
+ if (mClock.elapsedRealtime() - mQawClientCreatedTimeMillis
+ > RECREATION_TIME_WINDOW) {
+ Log.i(TAG, "Re-creating the QAW client to avoid stale.");
+ reCreateWalletClient();
+ }
if (!mQuickAccessWalletClient.isWalletFeatureAvailable()) {
Log.d(TAG, "QuickAccessWallet feature is not available.");
return;
@@ -162,6 +175,7 @@
*/
public void reCreateWalletClient() {
mQuickAccessWalletClient = QuickAccessWalletClient.create(mContext);
+ mQawClientCreatedTimeMillis = mClock.elapsedRealtime();
}
private void setupDefaultPaymentAppObserver(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index fc0214a..e9061af 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -754,6 +754,28 @@
}
@Test
+ public void testActiveSubscriptionBecomesInactive() {
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(list);
+ mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged(
+ TEST_SUBSCRIPTION.getSubscriptionId());
+ mTestableLooper.processAllMessages();
+ assertThat(mKeyguardUpdateMonitor.mSimDatas.get(TEST_SUBSCRIPTION.getSubscriptionId()))
+ .isNotNull();
+
+ when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(null);
+ mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ mTestableLooper.processAllMessages();
+
+ assertThat(mKeyguardUpdateMonitor.mSimDatas.get(TEST_SUBSCRIPTION.getSubscriptionId()))
+ .isNull();
+ assertThat(mKeyguardUpdateMonitor.mSimDatas.get(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isNull();
+ }
+
+ @Test
public void testIsUserUnlocked() {
// mUserManager will report the user as unlocked on @Before
assertThat(mKeyguardUpdateMonitor.isUserUnlocked(KeyguardUpdateMonitor.getCurrentUser()))
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 e94f836..39d5314 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -20,9 +20,7 @@
import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT;
import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -50,12 +48,14 @@
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.SensorProperties;
+import android.hardware.display.DisplayManager;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.os.Bundle;
+import android.os.Handler;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
@@ -110,6 +110,10 @@
private UdfpsController mUdfpsController;
@Mock
private SidefpsController mSidefpsController;
+ @Mock
+ private DisplayManager mDisplayManager;
+ @Mock
+ private Handler mHandler;
@Captor
ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
@@ -544,13 +548,12 @@
@Test
public void testSubscribesToOrientationChangesWhenShowingDialog() {
- assertFalse(mAuthController.mOrientationListener.getEnabled());
-
showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
- assertTrue(mAuthController.mOrientationListener.getEnabled());
+
+ verify(mDisplayManager).registerDisplayListener(any(), eq(mHandler));
mAuthController.hideAuthenticationDialog();
- assertFalse(mAuthController.mOrientationListener.getEnabled());
+ verify(mDisplayManager).unregisterDisplayListener(any());
}
// Helpers
@@ -603,7 +606,7 @@
Provider<SidefpsController> sidefpsControllerFactory) {
super(context, commandQueue, activityTaskManager, windowManager,
fingerprintManager, faceManager, udfpsControllerFactory,
- sidefpsControllerFactory);
+ sidefpsControllerFactory, mDisplayManager, mHandler);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
index 7019a4b..977b05c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
@@ -17,11 +17,13 @@
package com.android.systemui.biometrics
import android.hardware.biometrics.SensorProperties
+import android.hardware.display.DisplayManager
import android.hardware.display.DisplayManagerGlobal
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.hardware.fingerprint.ISidefpsController
+import android.os.Handler
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.Display
@@ -34,14 +36,15 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
@@ -64,6 +67,10 @@
lateinit var windowManager: WindowManager
@Mock
lateinit var sidefpsView: SidefpsView
+ @Mock
+ lateinit var displayManager: DisplayManager
+ @Mock
+ lateinit var handler: Handler
private val executor = FakeExecutor(FakeSystemClock())
private lateinit var overlayController: ISidefpsController
@@ -94,7 +101,8 @@
)
sideFpsController = SidefpsController(
- mContext, layoutInflater, fingerprintManager, windowManager, executor
+ mContext, layoutInflater, fingerprintManager, windowManager, executor,
+ displayManager, handler
)
overlayController = ArgumentCaptor.forClass(ISidefpsController::class.java).apply {
@@ -104,14 +112,13 @@
@Test
fun testSubscribesToOrientationChangesWhenShowingOverlay() {
- assertThat(sideFpsController.mOrientationListener.enabled).isFalse()
-
overlayController.show()
executor.runAllReady()
- assertThat(sideFpsController.mOrientationListener.enabled).isTrue()
+
+ verify(displayManager).registerDisplayListener(any(), eq(handler))
overlayController.hide()
executor.runAllReady()
- assertThat(sideFpsController.mOrientationListener.enabled).isFalse()
+ verify(displayManager).unregisterDisplayListener(any())
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 36ca664..ca11451 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -17,8 +17,6 @@
package com.android.systemui.biometrics;
import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -33,11 +31,13 @@
import android.content.res.TypedArray;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.SensorProperties;
+import android.hardware.display.DisplayManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
+import android.os.Handler;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.Vibrator;
@@ -139,6 +139,10 @@
private KeyguardStateController mKeyguardStateController;
@Mock
private KeyguardBypassController mKeyguardBypassController;
+ @Mock
+ private DisplayManager mDisplayManager;
+ @Mock
+ private Handler mHandler;
private FakeExecutor mFgExecutor;
@@ -208,7 +212,9 @@
mUdfpsHapticsSimulator,
Optional.of(mHbmProvider),
mKeyguardStateController,
- mKeyguardBypassController);
+ mKeyguardBypassController,
+ mDisplayManager,
+ mHandler);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
@@ -324,18 +330,16 @@
@Test
public void testSubscribesToOrientationChangesWhenShowingOverlay() throws Exception {
- assertFalse(mUdfpsController.mOrientationListener.getEnabled());
-
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
- assertTrue(mUdfpsController.mOrientationListener.getEnabled());
+ verify(mDisplayManager).registerDisplayListener(any(), eq(mHandler));
mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
mFgExecutor.runAllReady();
- assertFalse(mUdfpsController.mOrientationListener.getEnabled());
+ verify(mDisplayManager).unregisterDisplayListener(any());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java
index d25b3e3..92652a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarButtonTest.java
@@ -16,12 +16,12 @@
package com.android.systemui.navigationbar;
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
-
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
@@ -38,7 +38,6 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.SysuiTestableContext;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -47,6 +46,8 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.function.Predicate;
@@ -56,6 +57,10 @@
@SmallTest
public class NavigationBarButtonTest extends SysuiTestCase {
+ @Mock
+ EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+ @Mock
+ EdgeBackGestureHandler mEdgeBackGestureHandler;
private static final String TAG = "NavigationBarButtonTest";
private ImageReader mReader;
private NavigationBarView mNavBar;
@@ -63,16 +68,20 @@
@Before
public void setup() {
+ MockitoAnnotations.initMocks(this);
final Display display = createVirtualDisplay();
final SysuiTestableContext context =
(SysuiTestableContext) mContext.createDisplayContext(display);
+ when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+ .thenReturn(mEdgeBackGestureHandler);
+
mDependency.injectMockDependency(AssistManager.class);
mDependency.injectMockDependency(OverviewProxyService.class);
mDependency.injectMockDependency(KeyguardStateController.class);
mDependency.injectMockDependency(NavigationBarController.class);
- mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
- () -> mock(EdgeBackGestureHandler.class));
+ mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+ mEdgeBackGestureHandlerFactory);
mNavBar = new NavigationBarView(context, null);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index a76afd4..1968f7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -24,7 +24,6 @@
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS;
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
import static com.android.systemui.navigationbar.NavigationBar.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS;
import static org.junit.Assert.assertEquals;
@@ -119,6 +118,10 @@
private BroadcastDispatcher mBroadcastDispatcher;
@Mock
private UiEventLogger mUiEventLogger;
+ @Mock
+ EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+ @Mock
+ EdgeBackGestureHandler mEdgeBackGestureHandler;
@Rule
public final LeakCheckedTest.SysuiLeakCheck mLeakCheck = new LeakCheckedTest.SysuiLeakCheck();
@@ -129,6 +132,8 @@
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
+ when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+ .thenReturn(mEdgeBackGestureHandler);
mCommandQueue = new CommandQueue(mContext);
setupSysuiDependency();
mDependency.injectMockDependency(AssistManager.class);
@@ -136,8 +141,8 @@
mDependency.injectMockDependency(StatusBarStateController.class);
mDependency.injectMockDependency(NavigationBarController.class);
mOverviewProxyService = mDependency.injectMockDependency(OverviewProxyService.class);
- mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
- () -> mock(EdgeBackGestureHandler.class));
+ mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+ mEdgeBackGestureHandlerFactory);
TestableLooper.get(this).runWithLooper(() -> {
mNavigationBar = createNavBar(mContext);
mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
index 62871dc..6a2a78b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
@@ -16,16 +16,16 @@
package com.android.systemui.navigationbar;
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
-
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.IWindowManager;
@@ -44,24 +44,34 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
public class NavigationBarTransitionsTest extends SysuiTestCase {
+ @Mock
+ EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+ @Mock
+ EdgeBackGestureHandler mEdgeBackGestureHandler;
private NavigationBarTransitions mTransitions;
@Before
public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+ .thenReturn(mEdgeBackGestureHandler);
mDependency.injectMockDependency(IWindowManager.class);
mDependency.injectMockDependency(AssistManager.class);
mDependency.injectMockDependency(OverviewProxyService.class);
mDependency.injectMockDependency(StatusBarStateController.class);
mDependency.injectMockDependency(KeyguardStateController.class);
mDependency.injectMockDependency(NavigationBarController.class);
- mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
- () -> mock(EdgeBackGestureHandler.class));
+ mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+ mEdgeBackGestureHandlerFactory);
doReturn(mContext)
.when(mDependency.injectMockDependency(NavigationModeController.class))
.getCurrentUserContext();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java
index 671b1be..7eb7c8e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NavigationBarContextTest.java
@@ -16,19 +16,20 @@
package com.android.systemui.navigationbar.buttons;
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
@@ -37,15 +38,14 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.navigationbar.buttons.ContextualButton;
-import com.android.systemui.navigationbar.buttons.ContextualButtonGroup;
-import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
/** atest NavigationBarContextTest */
@SmallTest
@@ -60,6 +60,11 @@
private static final float DARK_INTENSITY_ERR = 0.0002f;
private static final int ICON_RES_ID = 1;
+ @Mock
+ EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+ @Mock
+ EdgeBackGestureHandler mEdgeBackGestureHandler;
+
private ContextualButtonGroup mGroup;
private ContextualButton mBtn0;
private ContextualButton mBtn1;
@@ -67,9 +72,14 @@
@Before
public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+ .thenReturn(mEdgeBackGestureHandler);
+
mDependency.injectMockDependency(AssistManager.class);
- mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
- () -> mock(EdgeBackGestureHandler.class));
+ mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+ mEdgeBackGestureHandlerFactory);
mGroup = new ContextualButtonGroup(GROUP_ID);
mBtn0 = new ContextualButton(BUTTON_0_ID, mContext, ICON_RES_ID);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
index 2ab2c94..038b42b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/buttons/NearestTouchFrameTest.java
@@ -16,18 +16,16 @@
package com.android.systemui.navigationbar.buttons;
-import static com.android.systemui.Dependency.EDGE_BACK_GESTURE_HANDLER_PROVIDER;
-
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
@@ -38,12 +36,13 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.Map;
@@ -52,12 +51,21 @@
@SmallTest
public class NearestTouchFrameTest extends SysuiTestCase {
+ @Mock
+ EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+ @Mock
+ EdgeBackGestureHandler mEdgeBackGestureHandler;
private NearestTouchFrame mNearestTouchFrame;
@Before
public void setup() {
- mDependency.injectTestDependency(EDGE_BACK_GESTURE_HANDLER_PROVIDER,
- () -> mock(EdgeBackGestureHandler.class));
+ MockitoAnnotations.initMocks(this);
+
+ when(mEdgeBackGestureHandlerFactory.create(any(Context.class)))
+ .thenReturn(mEdgeBackGestureHandler);
+
+ mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class,
+ mEdgeBackGestureHandlerFactory);
Configuration c = new Configuration(mContext.getResources().getConfiguration());
c.smallestScreenWidthDp = 500;
mNearestTouchFrame = new NearestTouchFrame(mContext, null, c);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 17797b7..a70c2be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -30,7 +30,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -257,19 +256,6 @@
}
@Test
- public void testGetServiceLabelUnsafe_recreateWalletClient() {
- doAnswer(invocation -> {
- throw new Exception("Bad service label.");
- }).when(mQuickAccessWalletClient).getServiceLabel();
-
- QSTile.State state = new QSTile.State();
-
- mTile.handleUpdateState(state, null);
-
- verify(mController).reCreateWalletClient();
- }
-
- @Test
public void testHandleUpdateState_updateLabelAndIcon() {
QSTile.State state = new QSTile.State();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 1ba3831..298bd9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -154,6 +154,9 @@
private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
@Captor
private ArgumentCaptor<KeyguardIndication> mKeyguardIndicationCaptor;
+ @Captor
+ private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallbackCaptor;
+ private KeyguardStateController.Callback mKeyguardStateControllerCallback;
private StatusBarStateController.StateListener mStatusBarStateListener;
private BroadcastReceiver mBroadcastReceiver;
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@@ -223,6 +226,10 @@
mController.mRotateTextViewController = mRotateTextViewController;
mController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
clearInvocations(mIBatteryStats);
+
+ verify(mKeyguardStateController).addCallback(
+ mKeyguardStateControllerCallbackCaptor.capture());
+ mKeyguardStateControllerCallback = mKeyguardStateControllerCallbackCaptor.getValue();
}
@Test
@@ -529,7 +536,7 @@
reset(mKeyguardUpdateMonitor);
when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true);
when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
- mController.onUnlockedChanged();
+ mKeyguardStateControllerCallback.onUnlockedChanged();
verifyIndicationMessage(INDICATION_TYPE_RESTING, restingIndication);
}
@@ -572,7 +579,7 @@
@Test
public void updateMonitor_listener() {
createController();
- verify(mKeyguardStateController).addCallback(eq(mController));
+ verify(mKeyguardStateController).addCallback(any());
verify(mKeyguardUpdateMonitor, times(2)).registerCallback(any());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index d6c2797..d23a9ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -196,6 +196,13 @@
}
@Test
+ fun onDozeAmountChanged_appliesBlur() {
+ statusBarStateListener.onDozeAmountChanged(1f, 1f)
+ notificationShadeDepthController.updateBlurCallback.doFrame(0)
+ verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false))
+ }
+
+ @Test
fun setFullShadeTransition_appliesBlur_onlyIfSupported() {
reset(blurUtils)
`when`(blurUtils.blurRadiusOfRatio(anyFloat())).then { answer ->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
index ce0098e..72a329a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
@@ -37,6 +37,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.time.FakeSystemClock;
import com.google.common.util.concurrent.MoreExecutors;
@@ -62,6 +63,7 @@
@Captor
private ArgumentCaptor<GetWalletCardsRequest> mRequestCaptor;
+ private FakeSystemClock mClock = new FakeSystemClock();
private QuickAccessWalletController mController;
@Before
@@ -70,12 +72,14 @@
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked()).thenReturn(true);
+ mClock.setElapsedRealtime(100L);
mController = new QuickAccessWalletController(
mContext,
MoreExecutors.directExecutor(),
mSecureSettings,
- mQuickAccessWalletClient);
+ mQuickAccessWalletClient,
+ mClock);
}
@Test
@@ -125,6 +129,23 @@
}
@Test
+ public void queryWalletCards_avoidStale_recreateClient() {
+ // advance current time by 100 seconds, should not recreate the client.
+ mClock.setElapsedRealtime(100100L);
+
+ mController.queryWalletCards(mCardsRetriever);
+
+ assertSame(mQuickAccessWalletClient, mController.getWalletClient());
+
+ // advance current time by another 501 seconds, should recreate the client.
+ mClock.setElapsedRealtime(601100L);
+
+ mController.queryWalletCards(mCardsRetriever);
+
+ assertNotSame(mQuickAccessWalletClient, mController.getWalletClient());
+ }
+
+ @Test
public void queryWalletCards_walletEnabled_queryCards() {
mController.queryWalletCards(mCardsRetriever);
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index f440ee8..c9608a5 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -82,6 +82,8 @@
private static final int INVALID_ID = 0;
private int mUniqueId = 1;
+ // The count of the connected legacy clients.
+ private int mLegacyClientCount = 0;
private class NsdStateMachine extends StateMachine {
@@ -107,7 +109,9 @@
sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs);
}
private void maybeScheduleStop() {
- if (!isAnyRequestActive()) {
+ // The native daemon should stay alive and can't be cleanup
+ // if any legacy client connected.
+ if (!isAnyRequestActive() && mLegacyClientCount == 0) {
scheduleStop();
}
}
@@ -175,11 +179,11 @@
if (cInfo != null) {
cInfo.expungeAllRequests();
mClients.remove(msg.replyTo);
+ if (cInfo.isLegacy()) {
+ mLegacyClientCount -= 1;
+ }
}
- //Last client
- if (mClients.size() == 0) {
- scheduleStop();
- }
+ maybeScheduleStop();
break;
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
AsyncChannel ac = new AsyncChannel();
@@ -208,6 +212,17 @@
case NsdManager.DAEMON_CLEANUP:
mDaemon.maybeStop();
break;
+ // This event should be only sent by the legacy (target SDK < S) clients.
+ // Mark the sending client as legacy.
+ case NsdManager.DAEMON_STARTUP:
+ cInfo = mClients.get(msg.replyTo);
+ if (cInfo != null) {
+ cancelStop();
+ cInfo.setLegacy();
+ mLegacyClientCount += 1;
+ maybeStartDaemon();
+ }
+ break;
case NsdManager.NATIVE_DAEMON_EVENT:
default:
Slog.e(TAG, "Unhandled " + msg);
@@ -863,6 +878,9 @@
/* A map from client id to the type of the request we had received */
private final SparseIntArray mClientRequests = new SparseIntArray();
+ // The target SDK of this client < Build.VERSION_CODES.S
+ private boolean mIsLegacy = false;
+
private ClientInfo(AsyncChannel c, Messenger m) {
mChannel = c;
mMessenger = m;
@@ -875,6 +893,7 @@
sb.append("mChannel ").append(mChannel).append("\n");
sb.append("mMessenger ").append(mMessenger).append("\n");
sb.append("mResolvedService ").append(mResolvedService).append("\n");
+ sb.append("mIsLegacy ").append(mIsLegacy).append("\n");
for(int i = 0; i< mClientIds.size(); i++) {
int clientID = mClientIds.keyAt(i);
sb.append("clientId ").append(clientID).
@@ -884,6 +903,14 @@
return sb.toString();
}
+ private boolean isLegacy() {
+ return mIsLegacy;
+ }
+
+ private void setLegacy() {
+ mIsLegacy = true;
+ }
+
// Remove any pending requests from the global map when we get rid of a client,
// and send cancellations to the daemon.
private void expungeAllRequests() {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 795d3d6..07847f1 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1934,6 +1934,28 @@
if (smap != null) {
decActiveForegroundAppLocked(smap, r);
}
+
+ // Adjust notification handling before setting isForeground to false, because
+ // that state is relevant to the notification policy side.
+ // Leave the time-to-display as already set: re-entering foreground mode will
+ // only resume the previous quiet timeout, or will display immediately if the
+ // deferral period had already passed.
+ if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
+ cancelForegroundNotificationLocked(r);
+ r.foregroundId = 0;
+ r.foregroundNoti = null;
+ } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
+ // if it's been deferred, force to visibility
+ if (!r.mFgsNotificationShown) {
+ r.postNotification();
+ }
+ dropFgsNotificationStateLocked(r);
+ if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) {
+ r.foregroundId = 0;
+ r.foregroundNoti = null;
+ }
+ }
+
r.isForeground = false;
r.mFgsExitTime = SystemClock.uptimeMillis();
ServiceState stracker = r.getTracker();
@@ -1957,20 +1979,6 @@
updateServiceForegroundLocked(r.app.mServices, true);
}
}
- // Leave the time-to-display as already set: re-entering foreground mode will
- // only resume the previous quiet timeout, or will display immediately if the
- // deferral period had already passed.
- if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
- cancelForegroundNotificationLocked(r);
- r.foregroundId = 0;
- r.foregroundNoti = null;
- } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
- dropFgsNotificationStateLocked(r);
- if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) {
- r.foregroundId = 0;
- r.foregroundNoti = null;
- }
- }
}
}
diff --git a/services/core/java/com/android/server/am/LmkdStatsReporter.java b/services/core/java/com/android/server/am/LmkdStatsReporter.java
index c702d78..a8d0582 100644
--- a/services/core/java/com/android/server/am/LmkdStatsReporter.java
+++ b/services/core/java/com/android/server/am/LmkdStatsReporter.java
@@ -43,6 +43,7 @@
private static final int LOW_MEM_AND_THRASHING = 4;
private static final int DIRECT_RECL_AND_THRASHING = 5;
private static final int LOW_MEM_AND_SWAP_UTIL = 6;
+ private static final int LOW_FILECACHE_AFTER_THRASHING = 7;
/**
* Processes the LMK_KILL_OCCURRED packet data
@@ -100,6 +101,8 @@
return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__DIRECT_RECL_AND_THRASHING;
case LOW_MEM_AND_SWAP_UTIL:
return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_SWAP_UTIL;
+ case LOW_FILECACHE_AFTER_THRASHING:
+ return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_FILECACHE_AFTER_THRASHING;
default:
return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__UNKNOWN;
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index f7c777e..dc924c1 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -24,6 +24,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -408,6 +409,18 @@
}
controller.mAmInternal.tempAllowlistForPendingIntent(callingPid, callingUid,
uid, duration.duration, duration.type, duration.reasonCode, tag.toString());
+ } else if (key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE
+ && options != null) {
+ // If this is a getForegroundService() type pending intent, use its BroadcastOptions
+ // temp allowlist duration as its pending intent temp allowlist duration.
+ BroadcastOptions brOptions = new BroadcastOptions(options);
+ if (brOptions.getTemporaryAppAllowlistDuration() > 0) {
+ controller.mAmInternal.tempAllowlistForPendingIntent(callingPid, callingUid,
+ uid, brOptions.getTemporaryAppAllowlistDuration(),
+ brOptions.getTemporaryAppAllowlistType(),
+ brOptions.getTemporaryAppAllowlistReasonCode(),
+ brOptions.getTemporaryAppAllowlistReason());
+ }
}
boolean sendFinish = finishedReceiver != null;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 24edc01..a9905dc 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -7297,6 +7297,30 @@
}
}
}
+
+ @Override
+ public int getOpRestrictionCount(int code, UserHandle user, String pkg,
+ String attributionTag) {
+ int number = 0;
+ synchronized (AppOpsService.this) {
+ int numRestrictions = mOpUserRestrictions.size();
+ for (int i = 0; i < numRestrictions; i++) {
+ if (mOpUserRestrictions.valueAt(i)
+ .hasRestriction(code, pkg, attributionTag, user.getIdentifier())) {
+ number++;
+ }
+ }
+
+ numRestrictions = mOpGlobalRestrictions.size();
+ for (int i = 0; i < numRestrictions; i++) {
+ if (mOpGlobalRestrictions.valueAt(i).hasRestriction(code)) {
+ number++;
+ }
+ }
+ }
+
+ return number;
+ }
}
/**
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index fed320d..6b7787a 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -73,6 +73,7 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemService;
+import com.android.server.biometrics.sensors.CoexCoordinator;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -1100,6 +1101,12 @@
}
return new ArrayList<>();
}
+
+ public boolean isAdvancedCoexLogicEnabled(Context context) {
+ return (Build.IS_USERDEBUG || Build.IS_ENG)
+ && Settings.Secure.getInt(context.getContentResolver(),
+ CoexCoordinator.SETTING_ENABLE_NAME, 0) != 0;
+ }
}
/**
@@ -1126,6 +1133,12 @@
mSettingObserver = mInjector.getSettingObserver(context, mHandler,
mEnabledOnKeyguardCallbacks);
+ // TODO(b/193089985) This logic lives here (outside of CoexCoordinator) so that it doesn't
+ // need to depend on context. We can remove this code once the advanced logic is enabled
+ // by default.
+ CoexCoordinator coexCoordinator = CoexCoordinator.getInstance();
+ coexCoordinator.setAdvancedLogicEnabled(injector.isAdvancedCoexLogicEnabled(context));
+
try {
injector.getActivityManagerService().registerUserSwitchObserver(
new UserSwitchObserver() {
@@ -1437,5 +1450,7 @@
pw.println();
pw.println("CurrentSession: " + mCurrentAuthSession);
pw.println();
+ pw.println("CoexCoordinator: " + CoexCoordinator.getInstance().toString());
+ pw.println();
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 28c949d..6463e04 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -16,6 +16,7 @@
package com.android.server.biometrics.sensors;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -30,6 +31,7 @@
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.security.KeyStore;
import android.util.EventLog;
import android.util.Slog;
@@ -48,6 +50,18 @@
private static final String TAG = "Biometrics/AuthenticationClient";
+ // New, has not started yet
+ public static final int STATE_NEW = 0;
+ // Framework/HAL have started this operation
+ public static final int STATE_STARTED = 1;
+ // Operation is started, but requires some user action (such as finger lift & re-touch)
+ public static final int STATE_STARTED_PAUSED = 2;
+ // Done, errored, canceled, etc. HAL/framework are not running this sensor anymore.
+ public static final int STATE_STOPPED = 3;
+
+ @IntDef({STATE_NEW, STATE_STARTED, STATE_STARTED_PAUSED, STATE_STOPPED})
+ @interface State {}
+
private final boolean mIsStrongBiometric;
private final boolean mRequireConfirmation;
private final ActivityTaskManager mActivityTaskManager;
@@ -63,6 +77,20 @@
protected boolean mAuthAttempted;
+ // TODO: This is currently hard to maintain, as each AuthenticationClient subclass must update
+ // the state. We should think of a way to improve this in the future.
+ protected @State int mState = STATE_NEW;
+
+ /**
+ * Handles lifecycle, e.g. {@link BiometricScheduler},
+ * {@link com.android.server.biometrics.sensors.BaseClientMonitor.Callback} after authentication
+ * results are known. Note that this happens asynchronously from (but shortly after)
+ * {@link #onAuthenticated(BiometricAuthenticator.Identifier, boolean, ArrayList)} and allows
+ * {@link CoexCoordinator} a chance to invoke/delay this event.
+ * @param authenticated
+ */
+ protected abstract void handleLifecycleAfterAuth(boolean authenticated);
+
public AuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
int targetUserId, long operationId, boolean restricted, @NonNull String owner,
@@ -221,7 +249,8 @@
}
final CoexCoordinator coordinator = CoexCoordinator.getInstance();
- coordinator.onAuthenticationSucceeded(this, new CoexCoordinator.Callback() {
+ coordinator.onAuthenticationSucceeded(SystemClock.uptimeMillis(), this,
+ new CoexCoordinator.Callback() {
@Override
public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
if (addAuthTokenIfStrong && mIsStrongBiometric) {
@@ -262,6 +291,11 @@
vibrateSuccess();
}
}
+
+ @Override
+ public void handleLifecycleAfterAuth() {
+ AuthenticationClient.this.handleLifecycleAfterAuth(true /* authenticated */);
+ }
});
} else {
// Allow system-defined limit of number of attempts before giving up
@@ -272,7 +306,7 @@
}
final CoexCoordinator coordinator = CoexCoordinator.getInstance();
- coordinator.onAuthenticationRejected(this, lockoutMode,
+ coordinator.onAuthenticationRejected(SystemClock.uptimeMillis(), this, lockoutMode,
new CoexCoordinator.Callback() {
@Override
public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
@@ -291,6 +325,11 @@
vibrateError();
}
}
+
+ @Override
+ public void handleLifecycleAfterAuth() {
+ AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */);
+ }
});
}
}
@@ -307,6 +346,12 @@
}
}
+ @Override
+ public void onError(int errorCode, int vendorCode) {
+ super.onError(errorCode, vendorCode);
+ mState = STATE_STOPPED;
+ }
+
/**
* Start authentication
*/
@@ -345,6 +390,10 @@
}
}
+ public @State int getState() {
+ return mState;
+ }
+
@Override
public int getProtoEnum() {
return BiometricsProto.CM_AUTHENTICATE;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index 6126607..b20316e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -356,10 +356,12 @@
/**
* Creates a new scheduler.
* @param tag for the specific instance of the scheduler. Should be unique.
+ * @param sensorType the sensorType that this scheduler is handling.
* @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures
* (such as fingerprint swipe).
*/
- public BiometricScheduler(@NonNull String tag, @SensorType int sensorType,
+ public BiometricScheduler(@NonNull String tag,
+ @SensorType int sensorType,
@Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
this(tag, sensorType, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface(
ServiceManager.getService(Context.BIOMETRIC_SERVICE)), LOG_NUM_RECENT_OPERATIONS,
diff --git a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
index 08bf2e0..f97cb8a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
@@ -16,12 +16,23 @@
package com.android.server.biometrics.sensors;
+import static com.android.server.biometrics.sensors.BiometricScheduler.SENSOR_TYPE_FACE;
+import static com.android.server.biometrics.sensors.BiometricScheduler.SENSOR_TYPE_UDFPS;
import static com.android.server.biometrics.sensors.BiometricScheduler.sensorTypeToString;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.biometrics.sensors.BiometricScheduler.SensorType;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
+
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.Map;
/**
@@ -33,8 +44,13 @@
public class CoexCoordinator {
private static final String TAG = "BiometricCoexCoordinator";
+ public static final String SETTING_ENABLE_NAME =
+ "com.android.server.biometrics.sensors.CoexCoordinator.enable";
private static final boolean DEBUG = true;
+ // Successful authentications should be used within this amount of time.
+ static final long SUCCESSFUL_AUTH_VALID_DURATION_MS = 5000;
+
/**
* Callback interface notifying the owner of "results" from the CoexCoordinator's business
* logic.
@@ -50,24 +66,101 @@
* Requests the owner to initiate a vibration for this event.
*/
void sendHapticFeedback();
+
+ /**
+ * Requests the owner to handle the AuthenticationClient's lifecycle (e.g. finish and remove
+ * from scheduler if auth was successful).
+ */
+ void handleLifecycleAfterAuth();
}
private static CoexCoordinator sInstance;
+ @VisibleForTesting
+ public static class SuccessfulAuth {
+ final long mAuthTimestamp;
+ final @SensorType int mSensorType;
+ final AuthenticationClient<?> mAuthenticationClient;
+ final Callback mCallback;
+ final CleanupRunnable mCleanupRunnable;
+
+ public static class CleanupRunnable implements Runnable {
+ @NonNull final LinkedList<SuccessfulAuth> mSuccessfulAuths;
+ @NonNull final SuccessfulAuth mAuth;
+ @NonNull final Callback mCallback;
+
+ public CleanupRunnable(@NonNull LinkedList<SuccessfulAuth> successfulAuths,
+ @NonNull SuccessfulAuth auth, @NonNull Callback callback) {
+ mSuccessfulAuths = successfulAuths;
+ mAuth = auth;
+ mCallback = callback;
+ }
+
+ @Override
+ public void run() {
+ final boolean removed = mSuccessfulAuths.remove(mAuth);
+ Slog.w(TAG, "Removing stale successfulAuth: " + mAuth.toString()
+ + ", success: " + removed);
+ mCallback.handleLifecycleAfterAuth();
+ }
+ }
+
+ public SuccessfulAuth(@NonNull Handler handler,
+ @NonNull LinkedList<SuccessfulAuth> successfulAuths,
+ long currentTimeMillis,
+ @SensorType int sensorType,
+ @NonNull AuthenticationClient<?> authenticationClient,
+ @NonNull Callback callback) {
+ mAuthTimestamp = currentTimeMillis;
+ mSensorType = sensorType;
+ mAuthenticationClient = authenticationClient;
+ mCallback = callback;
+
+ mCleanupRunnable = new CleanupRunnable(successfulAuths, this, callback);
+
+ handler.postDelayed(mCleanupRunnable, SUCCESSFUL_AUTH_VALID_DURATION_MS);
+ }
+
+ @Override
+ public String toString() {
+ return "SensorType: " + sensorTypeToString(mSensorType)
+ + ", mAuthTimestamp: " + mAuthTimestamp
+ + ", authenticationClient: " + mAuthenticationClient;
+ }
+ }
+
+ /**
+ * @return a singleton instance.
+ */
@NonNull
- static CoexCoordinator getInstance() {
+ public static CoexCoordinator getInstance() {
if (sInstance == null) {
sInstance = new CoexCoordinator();
}
return sInstance;
}
+ @VisibleForTesting
+ public void setAdvancedLogicEnabled(boolean enabled) {
+ mAdvancedLogicEnabled = enabled;
+ }
+
+ @VisibleForTesting
+ void reset() {
+ mClientMap.clear();
+ }
+
// SensorType to AuthenticationClient map
private final Map<Integer, AuthenticationClient<?>> mClientMap;
+ @VisibleForTesting final LinkedList<SuccessfulAuth> mSuccessfulAuths;
+ private boolean mAdvancedLogicEnabled;
+ private final Handler mHandler;
private CoexCoordinator() {
// Singleton
mClientMap = new HashMap<>();
+ mSuccessfulAuths = new LinkedList<>();
+ mHandler = new Handler(Looper.getMainLooper());
}
public void addAuthenticationClient(@BiometricScheduler.SensorType int sensorType,
@@ -99,23 +192,125 @@
mClientMap.remove(sensorType);
}
- public void onAuthenticationSucceeded(@NonNull AuthenticationClient<?> client,
+ public void onAuthenticationSucceeded(long currentTimeMillis,
+ @NonNull AuthenticationClient<?> client,
@NonNull Callback callback) {
if (client.isBiometricPrompt()) {
callback.sendHapticFeedback();
// For BP, BiometricService will add the authToken to Keystore.
callback.sendAuthenticationResult(false /* addAuthTokenIfStrong */);
- } else {
- // Keyguard, FingerprintManager, FaceManager, etc
+ callback.handleLifecycleAfterAuth();
+ } else if (isUnknownClient(client)) {
+ // Client doesn't exist in our map for some reason. Give the user feedback so the
+ // device doesn't feel like it's stuck. All other cases below can assume that the
+ // client exists in our map.
callback.sendHapticFeedback();
callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+ callback.handleLifecycleAfterAuth();
+ } else if (mAdvancedLogicEnabled && client.isKeyguard()) {
+ if (isSingleAuthOnly(client)) {
+ // Single sensor authentication
+ callback.sendHapticFeedback();
+ callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+ callback.handleLifecycleAfterAuth();
+ } else {
+ // Multi sensor authentication
+ AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
+ AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
+ if (isCurrentFaceAuth(client)) {
+ if (isUdfpsActivelyAuthing(udfps)) {
+ // Face auth success while UDFPS is actively authing. No callback, no haptic
+ // Feedback will be provided after UDFPS result:
+ // 1) UDFPS succeeds - simply remove this from the queue
+ // 2) UDFPS rejected - use this face auth success to notify clients
+ mSuccessfulAuths.add(new SuccessfulAuth(mHandler, mSuccessfulAuths,
+ currentTimeMillis, SENSOR_TYPE_FACE, client, callback));
+ } else {
+ callback.sendHapticFeedback();
+ callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+ callback.handleLifecycleAfterAuth();
+ }
+ } else if (isCurrentUdfps(client)) {
+ if (isFaceScanning()) {
+ // UDFPS succeeds while face is still scanning
+ // Cancel face auth and/or prevent it from invoking haptics/callbacks after
+ face.cancel();
+ }
+
+ removeAndFinishAllFaceFromQueue();
+
+ callback.sendHapticFeedback();
+ callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+ callback.handleLifecycleAfterAuth();
+ }
+ }
+ } else {
+ // Non-keyguard authentication. For example, Fingerprint Settings use of
+ // FingerprintManager for highlighting fingers
+ callback.sendHapticFeedback();
+ callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+ callback.handleLifecycleAfterAuth();
}
}
- public void onAuthenticationRejected(@NonNull AuthenticationClient<?> client,
+ public void onAuthenticationRejected(long currentTimeMillis,
+ @NonNull AuthenticationClient<?> client,
@LockoutTracker.LockoutMode int lockoutMode,
@NonNull Callback callback) {
- callback.sendHapticFeedback();
+ final boolean keyguardAdvancedLogic = mAdvancedLogicEnabled && client.isKeyguard();
+
+ if (keyguardAdvancedLogic) {
+ if (isSingleAuthOnly(client)) {
+ callback.sendHapticFeedback();
+ callback.handleLifecycleAfterAuth();
+ } else {
+ // Multi sensor authentication
+ AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
+ AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
+ if (isCurrentFaceAuth(client)) {
+ // UDFPS should still be running in this case, do not vibrate. However, we
+ // should notify the callback and finish the client, so that Keyguard and
+ // BiometricScheduler do not get stuck.
+ Slog.d(TAG, "Face rejected in multi-sensor auth, udfps: " + udfps);
+ callback.handleLifecycleAfterAuth();
+ } else if (isCurrentUdfps(client)) {
+ // Face should either be running, or have already finished
+ SuccessfulAuth auth = popSuccessfulFaceAuthIfExists(currentTimeMillis);
+ if (auth != null) {
+ Slog.d(TAG, "Using recent auth: " + auth);
+ callback.handleLifecycleAfterAuth();
+
+ auth.mCallback.sendHapticFeedback();
+ auth.mCallback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+ auth.mCallback.handleLifecycleAfterAuth();
+ } else if (isFaceScanning()) {
+ // UDFPS rejected but face is still scanning
+ Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face: " + face);
+ callback.handleLifecycleAfterAuth();
+
+ // TODO(b/193089985): Enforce/ensure that face auth finishes (whether
+ // accept/reject) within X amount of time. Otherwise users will be stuck
+ // waiting with their finger down for a long time.
+ } else {
+ // Face not scanning, and was not found in the queue. Most likely, face
+ // auth was too long ago.
+ Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face not scanning");
+ callback.sendHapticFeedback();
+ callback.handleLifecycleAfterAuth();
+ }
+ } else {
+ Slog.d(TAG, "Unknown client rejected: " + client);
+ callback.sendHapticFeedback();
+ callback.handleLifecycleAfterAuth();
+ }
+ }
+ } else {
+ callback.sendHapticFeedback();
+ callback.handleLifecycleAfterAuth();
+ }
+
+ // Always notify keyguard, otherwise the cached "running" state in KeyguardUpdateMonitor
+ // will get stuck.
if (lockoutMode == LockoutTracker.LOCKOUT_NONE) {
// Don't send onAuthenticationFailed if we're in lockout, it causes a
// janky UI on Keyguard/BiometricPrompt since "authentication failed"
@@ -123,4 +318,82 @@
callback.sendAuthenticationResult(false /* addAuthTokenIfStrong */);
}
}
+
+ @Nullable
+ private SuccessfulAuth popSuccessfulFaceAuthIfExists(long currentTimeMillis) {
+ for (SuccessfulAuth auth : mSuccessfulAuths) {
+ if (currentTimeMillis - auth.mAuthTimestamp >= SUCCESSFUL_AUTH_VALID_DURATION_MS) {
+ Slog.d(TAG, "Removing stale auth: " + auth);
+ mSuccessfulAuths.remove(auth);
+ } else if (auth.mSensorType == SENSOR_TYPE_FACE) {
+ mSuccessfulAuths.remove(auth);
+ return auth;
+ }
+ }
+ return null;
+ }
+
+ private void removeAndFinishAllFaceFromQueue() {
+ for (SuccessfulAuth auth : mSuccessfulAuths) {
+ if (auth.mSensorType == SENSOR_TYPE_FACE) {
+ Slog.d(TAG, "Removing from queue and finishing: " + auth);
+ auth.mCallback.handleLifecycleAfterAuth();
+ mSuccessfulAuths.remove(auth);
+ }
+ }
+ }
+
+ private boolean isCurrentFaceAuth(@NonNull AuthenticationClient<?> client) {
+ return client == mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
+ }
+
+ private boolean isCurrentUdfps(@NonNull AuthenticationClient<?> client) {
+ return client == mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
+ }
+
+ private boolean isFaceScanning() {
+ AuthenticationClient<?> client = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
+ return client != null && client.getState() == AuthenticationClient.STATE_STARTED;
+ }
+
+ private static boolean isUdfpsActivelyAuthing(@Nullable AuthenticationClient<?> client) {
+ if (client instanceof Udfps) {
+ return client.getState() == AuthenticationClient.STATE_STARTED;
+ }
+ return false;
+ }
+
+ private boolean isUnknownClient(@NonNull AuthenticationClient<?> client) {
+ for (AuthenticationClient<?> c : mClientMap.values()) {
+ if (c == client) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isSingleAuthOnly(@NonNull AuthenticationClient<?> client) {
+ if (mClientMap.values().size() != 1) {
+ return false;
+ }
+
+ for (AuthenticationClient<?> c : mClientMap.values()) {
+ if (c != client) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Enabled: ").append(mAdvancedLogicEnabled);
+ sb.append(", Queue size: " ).append(mSuccessfulAuths.size());
+ for (SuccessfulAuth auth : mSuccessfulAuths) {
+ sb.append(", Auth: ").append(auth.toString());
+ }
+
+ return sb.toString();
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 779558e..219e063 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -215,7 +215,7 @@
@Override // Binder call
public void enroll(int userId, final IBinder token, final byte[] hardwareAuthToken,
final IFaceServiceReceiver receiver, final String opPackageName,
- final int[] disabledFeatures, Surface surface, boolean debugConsent) {
+ final int[] disabledFeatures, Surface previewSurface, boolean debugConsent) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
@@ -225,8 +225,7 @@
}
provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
- receiver, opPackageName, disabledFeatures,
- convertSurfaceToNativeHandle(surface), debugConsent);
+ receiver, opPackageName, disabledFeatures, previewSurface, debugConsent);
}
@Override // Binder call
@@ -703,5 +702,27 @@
publishBinderService(Context.FACE_SERVICE, mServiceWrapper);
}
- private native NativeHandle convertSurfaceToNativeHandle(Surface surface);
+ /**
+ * Acquires a NativeHandle that can be used to access the provided surface. The returned handle
+ * must be explicitly released with {@link #releaseSurfaceHandle(NativeHandle)} to avoid memory
+ * leaks.
+ *
+ * The caller is responsible for ensuring that the surface is valid while using the handle.
+ * This method provides no lifecycle synchronization between the surface and the handle.
+ *
+ * @param surface a valid Surface.
+ * @return {@link android.os.NativeHandle} a NativeHandle for the provided surface.
+ */
+ public static native NativeHandle acquireSurfaceHandle(@NonNull Surface surface);
+
+ /**
+ * Releases resources associated with a NativeHandle that was acquired with
+ * {@link #acquireSurfaceHandle(Surface)}.
+ *
+ * This method has no affect on the surface for which the handle was acquired. It only frees up
+ * the resources that are associated with the handle.
+ *
+ * @param handle a handle that was obtained from {@link #acquireSurfaceHandle(Surface)}.
+ */
+ public static native void releaseSurfaceHandle(@NonNull NativeHandle handle);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
index 6d6c2e9..1d2ac3b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -26,8 +26,8 @@
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.os.IBinder;
-import android.os.NativeHandle;
import android.util.proto.ProtoOutputStream;
+import android.view.Surface;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -75,8 +75,8 @@
int getLockoutModeForUser(int sensorId, int userId);
/**
- * Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to
- * be invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
+ * Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to be
+ * invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient}
*/
default void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
@NonNull IInvalidationCallback callback) {
@@ -96,7 +96,7 @@
void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName,
- @NonNull int[] disabledFeatures, @Nullable NativeHandle surfaceHandle,
+ @NonNull int[] disabledFeatures, @Nullable Surface previewSurface,
boolean debugConsent);
void cancelEnrollment(int sensorId, @NonNull IBinder token);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java
index 57c1c74..66b942b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java
@@ -150,8 +150,8 @@
Utils.checkPermission(mContext, TEST_BIOMETRIC);
mProvider.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
- mContext.getOpPackageName(), new int[0] /* disabledFeatures */, null /* surface */,
- false /* debugConsent */);
+ mContext.getOpPackageName(), new int[0] /* disabledFeatures */,
+ null /* previewSurface */, false /* debugConsent */);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 0525d2d..35c1745 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -89,6 +89,12 @@
R.array.config_face_acquire_vendor_keyguard_ignorelist);
}
+ @Override
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+ mState = STATE_STARTED;
+ }
+
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
@@ -128,10 +134,20 @@
}
@Override
+ protected void handleLifecycleAfterAuth(boolean authenticated) {
+ // For face, the authentication lifecycle ends either when
+ // 1) Authenticated == true
+ // 2) Error occurred
+ // 3) Authenticated == false
+ mCallback.onClientFinished(this, true /* success */);
+ }
+
+ @Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
super.onAuthenticated(identifier, authenticated, token);
+ mState = STATE_STOPPED;
mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
getStartTimeMs(),
System.currentTimeMillis() - getStartTimeMs() /* latency */,
@@ -139,12 +155,6 @@
0 /* error */,
0 /* vendorError */,
getTargetUserId()));
-
- // For face, the authentication lifecycle ends either when
- // 1) Authenticated == true
- // 2) Error occurred
- // 3) Authenticated == false
- mCallback.onClientFinished(this, true /* success */);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index 0400e22..55c987a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -26,21 +26,24 @@
import android.hardware.biometrics.face.Feature;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
+import android.hardware.common.NativeHandle;
import android.hardware.face.Face;
import android.hardware.face.FaceEnrollFrame;
import android.hardware.face.FaceManager;
import android.os.IBinder;
-import android.os.NativeHandle;
import android.os.RemoteException;
import android.util.Slog;
+import android.view.Surface;
import com.android.internal.R;
import com.android.server.biometrics.HardwareAuthTokenUtils;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricNotificationUtils;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.EnrollClient;
+import com.android.server.biometrics.sensors.face.FaceService;
import com.android.server.biometrics.sensors.face.FaceUtils;
import java.io.IOException;
@@ -57,16 +60,31 @@
@NonNull private final int[] mEnrollIgnoreList;
@NonNull private final int[] mEnrollIgnoreListVendor;
@NonNull private final int[] mDisabledFeatures;
+ @Nullable private final Surface mPreviewSurface;
+ @Nullable private android.os.NativeHandle mOsPreviewHandle;
+ @Nullable private NativeHandle mHwPreviewHandle;
@Nullable private ICancellationSignal mCancellationSignal;
- @Nullable private android.hardware.common.NativeHandle mPreviewSurface;
private final int mMaxTemplatesPerUser;
private final boolean mDebugConsent;
+ private final BaseClientMonitor.Callback mPreviewHandleDeleterCallback =
+ new BaseClientMonitor.Callback() {
+ @Override
+ public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
+ }
+
+ @Override
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+ boolean success) {
+ releaseSurfaceHandlesIfNeeded();
+ }
+ };
+
FaceEnrollClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String opPackageName,
@NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
- @Nullable NativeHandle previewSurface, int sensorId, int maxTemplatesPerUser,
+ @Nullable Surface previewSurface, int sensorId, int maxTemplatesPerUser,
boolean debugConsent) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, opPackageName, utils,
timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
@@ -78,14 +96,7 @@
mMaxTemplatesPerUser = maxTemplatesPerUser;
mDebugConsent = debugConsent;
mDisabledFeatures = disabledFeatures;
- try {
- // We must manually close the duplicate handle after it's no longer needed.
- // The caller is responsible for closing the original handle.
- mPreviewSurface = AidlNativeHandleUtils.dup(previewSurface);
- } catch (IOException e) {
- mPreviewSurface = null;
- Slog.e(TAG, "Failed to dup previewSurface", e);
- }
+ mPreviewSurface = previewSurface;
}
@Override
@@ -98,17 +109,7 @@
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
- return new CompositeCallback(createALSCallback(), callback);
- }
-
- @Override
- public void destroy() {
- try {
- AidlNativeHandleUtils.close(mPreviewSurface);
- } catch (IOException e) {
- Slog.e(TAG, "Failed to close mPreviewSurface", e);
- }
- super.destroy();
+ return new CompositeCallback(mPreviewHandleDeleterCallback, createALSCallback(), callback);
}
@Override
@@ -153,22 +154,23 @@
@Override
protected void startHalOperation() {
+ obtainSurfaceHandlesIfNeeded();
try {
List<Byte> featureList = new ArrayList<Byte>();
if (mDebugConsent) {
- featureList.add(new Byte(Feature.DEBUG));
+ featureList.add(Feature.DEBUG);
}
boolean shouldAddDiversePoses = true;
- for (int i = 0; i < mDisabledFeatures.length; i++) {
- if (AidlConversionUtils.convertFrameworkToAidlFeature(mDisabledFeatures[i])
+ for (int disabledFeature : mDisabledFeatures) {
+ if (AidlConversionUtils.convertFrameworkToAidlFeature(disabledFeature)
== Feature.REQUIRE_DIVERSE_POSES) {
shouldAddDiversePoses = false;
}
}
if (shouldAddDiversePoses) {
- featureList.add(new Byte(Feature.REQUIRE_DIVERSE_POSES));
+ featureList.add(Feature.REQUIRE_DIVERSE_POSES);
}
byte[] features = new byte[featureList.size()];
@@ -178,7 +180,7 @@
mCancellationSignal = getFreshDaemon().enroll(
HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken),
- EnrollmentType.DEFAULT, features, mPreviewSurface);
+ EnrollmentType.DEFAULT, features, mHwPreviewHandle);
} catch (RemoteException | IllegalArgumentException e) {
Slog.e(TAG, "Exception when requesting enroll", e);
onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */);
@@ -198,4 +200,55 @@
}
}
}
+
+ private void obtainSurfaceHandlesIfNeeded() {
+ if (mPreviewSurface != null) {
+ // There is no direct way to convert Surface to android.hardware.common.NativeHandle. We
+ // first convert Surface to android.os.NativeHandle, and then android.os.NativeHandle to
+ // android.hardware.common.NativeHandle, which can be passed to the HAL.
+ // The resources for both handles must be explicitly freed to avoid memory leaks.
+ mOsPreviewHandle = FaceService.acquireSurfaceHandle(mPreviewSurface);
+ try {
+ // We must manually free up the resources for both handles after they are no longer
+ // needed. mHwPreviewHandle must be closed, but mOsPreviewHandle must be released
+ // through FaceService.
+ mHwPreviewHandle = AidlNativeHandleUtils.dup(mOsPreviewHandle);
+ Slog.v(TAG, "Obtained handles for the preview surface.");
+ } catch (IOException e) {
+ mHwPreviewHandle = null;
+ Slog.e(TAG, "Failed to dup mOsPreviewHandle", e);
+ }
+ }
+ }
+
+ private void releaseSurfaceHandlesIfNeeded() {
+ if (mPreviewSurface != null && mHwPreviewHandle == null) {
+ Slog.w(TAG, "mHwPreviewHandle is null even though mPreviewSurface is not null.");
+ }
+ if (mHwPreviewHandle != null) {
+ try {
+ Slog.v(TAG, "Closing mHwPreviewHandle");
+ AidlNativeHandleUtils.close(mHwPreviewHandle);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close mPreviewSurface", e);
+ }
+ mHwPreviewHandle = null;
+ }
+ if (mOsPreviewHandle != null) {
+ Slog.v(TAG, "Releasing mOsPreviewHandle");
+ FaceService.releaseSurfaceHandle(mOsPreviewHandle);
+ mOsPreviewHandle = null;
+ }
+ if (mPreviewSurface != null) {
+ Slog.v(TAG, "Releasing mPreviewSurface");
+ // We need to manually release this surface because it's a copy of the original surface
+ // that was sent to us by an app (e.g. Settings). The app cleans up its own surface (as
+ // part of the SurfaceView lifecycle, for example), but there is no mechanism in place
+ // that will clean up this copy.
+ // If this copy isn't cleaned up, it will eventually be garbage collected. However, this
+ // surface could be holding onto the native buffers that the GC is not aware of,
+ // exhausting the native memory before the GC feels the need to garbage collect.
+ mPreviewSurface.release();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 36a1292..5c24108 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -37,13 +37,13 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
-import android.os.NativeHandle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserManager;
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
+import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.Utils;
@@ -327,7 +327,7 @@
public void scheduleEnroll(int sensorId, @NonNull IBinder token,
@NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
@NonNull String opPackageName, @NonNull int[] disabledFeatures,
- @Nullable NativeHandle previewSurface, boolean debugConsent) {
+ @Nullable Surface previewSurface, boolean debugConsent) {
mHandler.post(() -> {
final int maxTemplatesPerUser = mSensors.get(
sensorId).getSensorProperties().maxEnrollmentsPerUser;
@@ -400,7 +400,7 @@
@Override
public void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId,
@NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
- scheduleRemoveSpecifiedIds(sensorId, token, new int[] {faceId}, userId, receiver,
+ scheduleRemoveSpecifiedIds(sensorId, token, new int[]{faceId}, userId, receiver,
opPackageName);
}
@@ -561,7 +561,8 @@
}
@Override
- public void dumpHal(int sensorId, @NonNull FileDescriptor fd, @NonNull String[] args) {}
+ public void dumpHal(int sensorId, @NonNull FileDescriptor fd, @NonNull String[] args) {
+ }
@Override
public void binderDied() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 4abd402..206b8f0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -494,8 +494,8 @@
mToken = new Binder();
mHandler = handler;
mSensorProperties = sensorProperties;
- mScheduler = new UserAwareBiometricScheduler(tag, BiometricScheduler.SENSOR_TYPE_FACE,
- null /* gestureAvailabilityDispatcher */,
+ mScheduler = new UserAwareBiometricScheduler(tag,
+ BiometricScheduler.SENSOR_TYPE_FACE, null /* gestureAvailabilityDispatcher */,
() -> mCurrentSession != null ? mCurrentSession.mUserId : UserHandle.USER_NULL,
new UserAwareBiometricScheduler.UserSwitchCallback() {
@NonNull
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java
index d0580c7..b45578b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/BiometricTestSessionImpl.java
@@ -139,7 +139,7 @@
mFace10.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
mContext.getOpPackageName(), new int[0] /* disabledFeatures */,
- null /* surfaceHandle */, false /* debugConsent */);
+ null /* previewSurface */, false /* debugConsent */);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index e95273a..da4ad86 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -47,6 +47,7 @@
import android.provider.Settings;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
@@ -88,8 +89,8 @@
import java.util.Map;
/**
- * Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or
- * its extended minor versions.
+ * Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or its extended
+ * minor versions.
*/
public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
@@ -325,7 +326,8 @@
}
}
- @VisibleForTesting Face10(@NonNull Context context,
+ @VisibleForTesting
+ Face10(@NonNull Context context,
@NonNull FaceSensorPropertiesInternal sensorProps,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull BiometricScheduler scheduler) {
@@ -571,7 +573,7 @@
public void scheduleEnroll(int sensorId, @NonNull IBinder token,
@NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
@NonNull String opPackageName, @NonNull int[] disabledFeatures,
- @Nullable NativeHandle surfaceHandle, boolean debugConsent) {
+ @Nullable Surface previewSurface, boolean debugConsent) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
@@ -580,7 +582,7 @@
final FaceEnrollClient client = new FaceEnrollClient(mContext, mLazyDaemon, token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, FaceUtils.getLegacyInstance(mSensorId), disabledFeatures,
- ENROLL_TIMEOUT_SEC, surfaceHandle, mSensorId);
+ ENROLL_TIMEOUT_SEC, previewSurface, mSensorId);
mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@Override
@@ -858,8 +860,8 @@
}
/**
- * Schedules the {@link FaceUpdateActiveUserClient} without posting the work onto the
- * handler. Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
+ * Schedules the {@link FaceUpdateActiveUserClient} without posting the work onto the handler.
+ * Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
* invocation prior to authenticate/enroll/etc. Thus, internally we usually want to schedule
* this operation on the same lambda/runnable as those operations so that the ordering is
* correct.
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 5731d73..e65245b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -79,6 +79,12 @@
R.array.config_face_acquire_vendor_keyguard_ignorelist);
}
+ @Override
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+ mState = STATE_STARTED;
+ }
+
@NonNull
@Override
protected Callback wrapCallbackForStart(@NonNull Callback callback) {
@@ -115,10 +121,20 @@
}
@Override
+ protected void handleLifecycleAfterAuth(boolean authenticated) {
+ // For face, the authentication lifecycle ends either when
+ // 1) Authenticated == true
+ // 2) Error occurred
+ // 3) Authenticated == false
+ mCallback.onClientFinished(this, true /* success */);
+ }
+
+ @Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
super.onAuthenticated(identifier, authenticated, token);
+ mState = STATE_STOPPED;
mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
getStartTimeMs(),
System.currentTimeMillis() - getStartTimeMs() /* latency */,
@@ -126,12 +142,6 @@
0 /* error */,
0 /* vendorError */,
getTargetUserId()));
-
- // For face, the authentication lifecycle ends either when
- // 1) Authenticated == true
- // 2) Error occurred
- // 3) Authenticated == false
- mCallback.onClientFinished(this, true /* success */);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
index d3bd18b..455d6f8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
@@ -26,9 +26,9 @@
import android.hardware.face.Face;
import android.hardware.face.FaceManager;
import android.os.IBinder;
-import android.os.NativeHandle;
import android.os.RemoteException;
import android.util.Slog;
+import android.view.Surface;
import com.android.internal.R;
import com.android.server.biometrics.Utils;
@@ -40,15 +40,14 @@
import java.util.Arrays;
/**
- * Face-specific enroll client supporting the {@link android.hardware.biometrics.face.V1_0}
- * HIDL interface.
+ * Face-specific enroll client supporting the {@link android.hardware.biometrics.face.V1_0} HIDL
+ * interface.
*/
public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
private static final String TAG = "FaceEnrollClient";
@NonNull private final int[] mDisabledFeatures;
- @Nullable private final NativeHandle mSurfaceHandle;
@NonNull private final int[] mEnrollIgnoreList;
@NonNull private final int[] mEnrollIgnoreListVendor;
@@ -56,12 +55,11 @@
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String owner,
@NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
- @Nullable NativeHandle surfaceHandle, int sensorId) {
+ @Nullable Surface previewSurface, int sensorId) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
false /* shouldVibrate */);
mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
- mSurfaceHandle = surfaceHandle;
mEnrollIgnoreList = getContext().getResources()
.getIntArray(R.array.config_face_acquire_enroll_ignorelist);
mEnrollIgnoreListVendor = getContext().getResources()
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
index 150e69c6..a2c0751 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
@@ -27,4 +27,5 @@
void onPointerDown(int x, int y, float minor, float major);
void onPointerUp();
void onUiReady();
+ boolean isPointerDown();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index 8681ad7..14d1822 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -54,7 +54,10 @@
@NonNull private final LockoutCache mLockoutCache;
@Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
+ @NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
+
@Nullable private ICancellationSignal mCancellationSignal;
+ private boolean mIsPointerDown;
FingerprintAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@@ -71,6 +74,19 @@
lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */);
mLockoutCache = lockoutCache;
mUdfpsOverlayController = udfpsOverlayController;
+ mSensorProps = sensorProps;
+ }
+
+ @Override
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+
+ if (mSensorProps.isAnyUdfpsType()) {
+ // UDFPS requires user to touch before becoming "active"
+ mState = STATE_STARTED_PAUSED;
+ } else {
+ mState = STATE_STARTED;
+ }
}
@NonNull
@@ -80,13 +96,22 @@
}
@Override
+ protected void handleLifecycleAfterAuth(boolean authenticated) {
+ if (authenticated) {
+ mCallback.onClientFinished(this, true /* success */);
+ }
+ }
+
+ @Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
super.onAuthenticated(identifier, authenticated, token);
if (authenticated) {
+ mState = STATE_STOPPED;
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
- mCallback.onClientFinished(this, true /* success */);
+ } else {
+ mState = STATE_STARTED_PAUSED;
}
}
@@ -143,6 +168,8 @@
@Override
public void onPointerDown(int x, int y, float minor, float major) {
try {
+ mIsPointerDown = true;
+ mState = STATE_STARTED;
getFreshDaemon().onPointerDown(0 /* pointerId */, x, y, minor, major);
if (getListener() != null) {
getListener().onUdfpsPointerDown(getSensorId());
@@ -155,6 +182,8 @@
@Override
public void onPointerUp() {
try {
+ mIsPointerDown = false;
+ mState = STATE_STARTED_PAUSED;
getFreshDaemon().onPointerUp(0 /* pointerId */);
if (getListener() != null) {
getListener().onUdfpsPointerUp(getSensorId());
@@ -165,6 +194,11 @@
}
@Override
+ public boolean isPointerDown() {
+ return mIsPointerDown;
+ }
+
+ @Override
public void onUiReady() {
try {
getFreshDaemon().onUiReady();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index a211bb5..e8200af 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -55,6 +55,7 @@
private final @FingerprintManager.EnrollReason int mEnrollReason;
@Nullable private ICancellationSignal mCancellationSignal;
private final int mMaxTemplatesPerUser;
+ private boolean mIsPointerDown;
FingerprintEnrollClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@@ -167,6 +168,7 @@
@Override
public void onPointerDown(int x, int y, float minor, float major) {
try {
+ mIsPointerDown = true;
getFreshDaemon().onPointerDown(0 /* pointerId */, x, y, minor, major);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to send pointer down", e);
@@ -176,6 +178,7 @@
@Override
public void onPointerUp() {
try {
+ mIsPointerDown = false;
getFreshDaemon().onPointerUp(0 /* pointerId */);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to send pointer up", e);
@@ -183,6 +186,11 @@
}
@Override
+ public boolean isPointerDown() {
+ return mIsPointerDown;
+ }
+
+ @Override
public void onUiReady() {
try {
getFreshDaemon().onUiReady();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index a6385a5..2f5b5c7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -622,7 +622,7 @@
opPackageName, cookie, false /* requireConfirmation */,
mSensorProperties.sensorId, isStrongBiometric, statsClient,
mTaskStackListener, mLockoutTracker, mUdfpsOverlayController,
- allowBackgroundAuthentication);
+ allowBackgroundAuthentication, mSensorProperties);
mScheduler.scheduleClientMonitor(client, fingerprintStateCallback);
});
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index 312c52c..24ce867 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -138,7 +138,8 @@
TestableBiometricScheduler(@NonNull String tag,
@Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
- super(tag, BiometricScheduler.SENSOR_TYPE_FP_OTHER, gestureAvailabilityDispatcher);
+ super(tag, BiometricScheduler.SENSOR_TYPE_FP_OTHER,
+ gestureAvailabilityDispatcher);
mInternalCallback = new TestableInternalCallback();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 40e3bc3..9347244 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -25,6 +25,7 @@
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
import android.os.RemoteException;
@@ -52,6 +53,9 @@
private final LockoutFrameworkImpl mLockoutFrameworkImpl;
@Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
+ @NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
+
+ private boolean mIsPointerDown;
FingerprintAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@@ -61,13 +65,27 @@
@NonNull TaskStackListener taskStackListener,
@NonNull LockoutFrameworkImpl lockoutTracker,
@Nullable IUdfpsOverlayController udfpsOverlayController,
- boolean allowBackgroundAuthentication) {
+ boolean allowBackgroundAuthentication,
+ @NonNull FingerprintSensorPropertiesInternal sensorProps) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */);
mLockoutFrameworkImpl = lockoutTracker;
mUdfpsOverlayController = udfpsOverlayController;
+ mSensorProps = sensorProps;
+ }
+
+ @Override
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+
+ if (mSensorProps.isAnyUdfpsType()) {
+ // UDFPS requires user to touch before becoming "active"
+ mState = STATE_STARTED_PAUSED;
+ } else {
+ mState = STATE_STARTED;
+ }
}
@NonNull
@@ -87,10 +105,11 @@
// Note that authentication doesn't end when Authenticated == false
if (authenticated) {
+ mState = STATE_STOPPED;
resetFailedAttempts(getTargetUserId());
UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
- mCallback.onClientFinished(this, true /* success */);
} else {
+ mState = STATE_STARTED_PAUSED;
final @LockoutTracker.LockoutMode int lockoutMode =
mLockoutFrameworkImpl.getLockoutModeForUser(getTargetUserId());
if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
@@ -124,6 +143,13 @@
}
@Override
+ protected void handleLifecycleAfterAuth(boolean authenticated) {
+ if (authenticated) {
+ mCallback.onClientFinished(this, true /* success */);
+ }
+ }
+
+ @Override
public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
mLockoutFrameworkImpl.addFailedAttemptForUser(userId);
return super.handleFailedAttempt(userId);
@@ -160,6 +186,8 @@
@Override
public void onPointerDown(int x, int y, float minor, float major) {
+ mIsPointerDown = true;
+ mState = STATE_STARTED;
UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major);
if (getListener() != null) {
try {
@@ -172,6 +200,8 @@
@Override
public void onPointerUp() {
+ mIsPointerDown = false;
+ mState = STATE_STARTED_PAUSED;
UdfpsHelper.onFingerUp(getFreshDaemon());
if (getListener() != null) {
try {
@@ -183,6 +213,11 @@
}
@Override
+ public boolean isPointerDown() {
+ return mIsPointerDown;
+ }
+
+ @Override
public void onUiReady() {
// Unsupported in HIDL.
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index af1e49d..8e73ee6b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -49,6 +49,7 @@
private final boolean mIsStrongBiometric;
@Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
+ private boolean mIsPointerDown;
public FingerprintDetectClient(@NonNull Context context,
@NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@@ -99,15 +100,22 @@
@Override
public void onPointerDown(int x, int y, float minor, float major) {
+ mIsPointerDown = true;
UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major);
}
@Override
public void onPointerUp() {
+ mIsPointerDown = false;
UdfpsHelper.onFingerUp(getFreshDaemon());
}
@Override
+ public boolean isPointerDown() {
+ return mIsPointerDown;
+ }
+
+ @Override
public void onUiReady() {
// Unsupported in HIDL.
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index eba445f..250e132 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -52,6 +52,7 @@
@Nullable private final IUdfpsOverlayController mUdfpsOverlayController;
@Nullable private final ISidefpsController mSidefpsController;
private final @FingerprintManager.EnrollReason int mEnrollReason;
+ private boolean mIsPointerDown;
FingerprintEnrollClient(@NonNull Context context,
@NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@@ -157,15 +158,22 @@
@Override
public void onPointerDown(int x, int y, float minor, float major) {
+ mIsPointerDown = true;
UdfpsHelper.onFingerDown(getFreshDaemon(), x, y, minor, major);
}
@Override
public void onPointerUp() {
+ mIsPointerDown = false;
UdfpsHelper.onFingerUp(getFreshDaemon());
}
@Override
+ public boolean isPointerDown() {
+ return mIsPointerDown;
+ }
+
+ @Override
public void onUiReady() {
// Unsupported in HIDL.
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index b6d65197..1edede5 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -96,7 +96,6 @@
*/
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
- private static final String TAG = "DisplayPowerController";
private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
@@ -149,6 +148,8 @@
private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
+ private final String TAG;
+
private final Object mLock = new Object();
private final Context mContext;
@@ -450,6 +451,7 @@
Runnable onBrightnessChangeRunnable) {
mLogicalDisplay = logicalDisplay;
mDisplayId = mLogicalDisplay.getDisplayIdLocked();
+ TAG = "DisplayPowerController[" + mDisplayId + "]";
mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
mHandler = new DisplayControllerHandler(handler.getLooper());
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index c0b8648..7d5b7e5 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2485,6 +2485,7 @@
private void removeUser(int userId, boolean unknownUser) {
Slog.i(TAG, "RemoveUser: " + userId);
+ removeBiometricsForUser(userId);
mSpManager.removeUser(userId);
mStrongAuth.removeUser(userId);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index dfc14bd..2a5a721 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -172,6 +172,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.WeakHashMap;
@@ -180,6 +181,7 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
@@ -219,6 +221,10 @@
/** If the permission of the value is granted, so is the key */
private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>();
+ /** Map of IBinder -> Running AttributionSource */
+ private static final ConcurrentHashMap<IBinder, RegisteredAttribution>
+ sRunningAttributionSources = new ConcurrentHashMap<>();
+
static {
FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
@@ -5555,8 +5561,15 @@
@Override
public void finishDataDelivery(int op,
+ @NonNull AttributionSourceState attributionSourceState, boolean fromDataSource) {
+ finishDataDelivery(mContext, op, attributionSourceState,
+ fromDataSource);
+ }
+
+ private static void finishDataDelivery(Context context, int op,
@NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) {
Objects.requireNonNull(attributionSourceState);
+ AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
if (op == AppOpsManager.OP_NONE) {
return;
@@ -5573,7 +5586,7 @@
// If the call is from a datasource we need to vet only the chain before it. This
// way we can avoid the datasource creating an attribution context for every call.
if (!(fromDatasource && current.asState() == attributionSourceState)
- && next != null && !current.isTrusted(mContext)) {
+ && next != null && !current.isTrusted(context)) {
return;
}
@@ -5589,20 +5602,20 @@
? current : next;
if (selfAccess) {
- final String resolvedPackageName = resolvePackageName(mContext, accessorSource);
+ final String resolvedPackageName = resolvePackageName(context, accessorSource);
if (resolvedPackageName == null) {
return;
}
- mAppOpsManager.finishOp(accessorSource.getToken(), op,
+ appOpsManager.finishOp(accessorSource.getToken(), op,
accessorSource.getUid(), resolvedPackageName,
accessorSource.getAttributionTag());
} else {
final AttributionSource resolvedAttributionSource =
- resolveAttributionSource(mContext, accessorSource);
+ resolveAttributionSource(context, accessorSource);
if (resolvedAttributionSource.getPackageName() == null) {
return;
}
- mAppOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op),
+ appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op),
resolvedAttributionSource, skipCurrentFinish);
}
@@ -5610,6 +5623,11 @@
return;
}
+ RegisteredAttribution registered =
+ sRunningAttributionSources.remove(current.getToken());
+ if (registered != null) {
+ registered.unregister();
+ }
current = next;
}
}
@@ -5827,6 +5845,12 @@
}
}
+ if (startDataDelivery) {
+ RegisteredAttribution registered = new RegisteredAttribution(context, op,
+ current, fromDatasource);
+ sRunningAttributionSources.put(current.getToken(), registered);
+ }
+
if (next == null || next.getNext() == null) {
return PermissionChecker.PERMISSION_GRANTED;
}
@@ -6153,4 +6177,43 @@
attributionSource));
}
}
+
+ private static final class RegisteredAttribution {
+ private final DeathRecipient mDeathRecipient;
+ private final IBinder mToken;
+ private final AtomicBoolean mFinished;
+
+ RegisteredAttribution(Context context, int op, AttributionSource source,
+ boolean fromDatasource) {
+ mFinished = new AtomicBoolean(false);
+ mDeathRecipient = () -> {
+ if (unregister()) {
+ PermissionCheckerService
+ .finishDataDelivery(context, op, source.asState(), fromDatasource);
+ }
+ };
+ mToken = source.getToken();
+ if (mToken != null) {
+ try {
+ mToken.linkToDeath(mDeathRecipient, 0);
+ } catch (RemoteException e) {
+ mDeathRecipient.binderDied();
+ }
+ }
+ }
+
+ public boolean unregister() {
+ if (mFinished.compareAndSet(false, true)) {
+ try {
+ if (mToken != null) {
+ mToken.unlinkToDeath(mDeathRecipient, 0);
+ }
+ } catch (NoSuchElementException e) {
+ // do nothing
+ }
+ return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index f72adb60..1321873 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -970,6 +970,12 @@
final long token = Binder.clearCallingIdentity();
try {
CompressedApexInfoList apexInfoList = getCompressedApexInfoList(packageFile);
+ if (apexInfoList == null) {
+ Log.i(TAG, "apex_info.pb not present in OTA package. "
+ + "Assuming device doesn't support compressed"
+ + "APEX, continueing without allocating space.");
+ return true;
+ }
ApexManager apexManager = ApexManager.getInstance();
apexManager.reserveSpaceForCompressedApex(apexInfoList);
return true;
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
index c1f8240..9999aff 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
@@ -133,13 +133,8 @@
* Throws a {@link SecurityException} iff the originator has permission to receive data.
*/
void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) {
- // TODO(b/186164881): remove
- // START TEMP HACK
- enforcePermissionForPreflight(mContext, identity, RECORD_AUDIO);
- int hotwordOp = AppOpsManager.strOpToOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD);
- mContext.getSystemService(AppOpsManager.class).noteOpNoThrow(hotwordOp, identity.uid,
- identity.packageName, identity.attributionTag, reason);
- // END TEMP HACK
+ enforcePermissionForDataDelivery(mContext, identity, RECORD_AUDIO,
+ reason);
enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD,
reason);
}
@@ -167,8 +162,8 @@
/**
* Throws a {@link SecurityException} if originator permanently doesn't have the given
- * permission, or a {@link ServiceSpecificException} with a {@link
- * Status#TEMPORARY_PERMISSION_DENIED} if caller originator doesn't have the given permission.
+ * permission.
+ * Soft (temporary) denials are considered OK for preflight purposes.
*
* @param context A {@link Context}, used for permission checks.
* @param identity The identity to check.
@@ -180,15 +175,12 @@
permission);
switch (status) {
case PermissionChecker.PERMISSION_GRANTED:
+ case PermissionChecker.PERMISSION_SOFT_DENIED:
return;
case PermissionChecker.PERMISSION_HARD_DENIED:
throw new SecurityException(
String.format("Failed to obtain permission %s for identity %s", permission,
ObjectPrinter.print(identity, true, 16)));
- case PermissionChecker.PERMISSION_SOFT_DENIED:
- throw new ServiceSpecificException(Status.TEMPORARY_PERMISSION_DENIED,
- String.format("Failed to obtain permission %s for identity %s", permission,
- ObjectPrinter.print(identity, true, 16)));
default:
throw new RuntimeException("Unexpected perimission check result.");
}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index 95a30c7..458eae9 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -318,6 +318,8 @@
*/
private Map<Integer, ModelParameterRange> parameterSupport = new HashMap<>();
+ private RecognitionConfig mConfig;
+
/**
* Check that the given parameter is known to be supported for this model.
*
@@ -369,6 +371,14 @@
void setActivityState(Activity activity) {
mActivityState.set(activity.ordinal());
}
+
+ void setRecognitionConfig(@NonNull RecognitionConfig config) {
+ mConfig = config;
+ }
+
+ RecognitionConfig getRecognitionConfig() {
+ return mConfig;
+ }
}
/**
@@ -502,6 +512,7 @@
// Normally, we would set the state after the operation succeeds. However, since
// the activity state may be reset outside of the lock, we set it here first,
// and reset it in case of exception.
+ modelState.setRecognitionConfig(config);
modelState.setActivityState(ModelState.Activity.ACTIVE);
mDelegate.startRecognition(modelHandle, config);
} catch (Exception e) {
@@ -542,6 +553,27 @@
}
}
+ private void restartIfIntercepted(int modelHandle) {
+ synchronized (SoundTriggerMiddlewareValidation.this) {
+ // State validation.
+ if (mState == ModuleStatus.DETACHED) {
+ return;
+ }
+ ModelState modelState = mLoadedModels.get(modelHandle);
+ if (modelState == null
+ || modelState.getActivityState() != ModelState.Activity.INTERCEPTED) {
+ return;
+ }
+ try {
+ mDelegate.startRecognition(modelHandle, modelState.getRecognitionConfig());
+ modelState.setActivityState(ModelState.Activity.ACTIVE);
+ Log.i(TAG, "Restarted intercepted model " + modelHandle);
+ } catch (Exception e) {
+ Log.i(TAG, "Failed to restart intercepted model " + modelHandle, e);
+ }
+ }
+ }
+
@Override
public void forceRecognitionEvent(int modelHandle) {
// Input validation (always valid).
@@ -753,6 +785,10 @@
Log.e(TAG, "Client callback exception.", e);
if (event.status != RecognitionStatus.FORCED) {
modelState.setActivityState(ModelState.Activity.INTERCEPTED);
+ // If we failed to deliver an actual event to the client, they would never
+ // know to restart it whenever circumstances change. Thus, we restart it
+ // here. We do this from a separate thread to avoid any race conditions.
+ new Thread(() -> restartIfIntercepted(modelHandle)).start();
}
}
}
@@ -780,6 +816,10 @@
Log.e(TAG, "Client callback exception.", e);
if (event.common.status != RecognitionStatus.FORCED) {
modelState.setActivityState(ModelState.Activity.INTERCEPTED);
+ // If we failed to deliver an actual event to the client, they would never
+ // know to restart it whenever circumstances change. Thus, we restart it
+ // here. We do this from a separate thread to avoid any race conditions.
+ new Thread(() -> restartIfIntercepted(modelHandle)).start();
}
}
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 8658334..36a854e 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -209,10 +209,11 @@
private void registerBroadcastReceivers() {
PackageMonitor monitor = new PackageMonitor() {
private void buildTvInputList(String[] packages) {
+ int userId = getChangingUserId();
synchronized (mLock) {
- if (mCurrentUserId == getChangingUserId()) {
- buildTvInputListLocked(mCurrentUserId, packages);
- buildTvContentRatingSystemListLocked(mCurrentUserId);
+ if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) {
+ buildTvInputListLocked(userId, packages);
+ buildTvContentRatingSystemListLocked(userId);
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index d3d1c1c..e3459a1 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.Manifest.permission.ACTIVITY_EMBEDDING;
+import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
@@ -88,6 +89,7 @@
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal;
import android.app.IActivityClientController;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
@@ -108,6 +110,8 @@
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.hardware.SensorPrivacyManager;
+import android.hardware.SensorPrivacyManagerInternal;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -141,6 +145,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.LocalServices;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.UserState;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
@@ -1221,6 +1226,24 @@
if (getAppOpsManager().noteOpNoThrow(opCode, callingUid,
callingPackage, callingFeatureId, "") != AppOpsManager.MODE_ALLOWED) {
+ if (CAMERA.equals(permission)) {
+ SensorPrivacyManagerInternal spmi =
+ LocalServices.getService(SensorPrivacyManagerInternal.class);
+
+ final UserHandle user = UserHandle.getUserHandleForUid(callingUid);
+ final boolean cameraPrivacyEnabled = spmi.isSensorPrivacyEnabled(
+ user.getIdentifier(), SensorPrivacyManager.Sensors.CAMERA);
+ if (cameraPrivacyEnabled) {
+ AppOpsManagerInternal aomi = LocalServices.getService(
+ AppOpsManagerInternal.class);
+ int numCameraRestrictions = aomi.getOpRestrictionCount(
+ AppOpsManager.OP_CAMERA, user, callingPackage, null);
+ if (numCameraRestrictions == 1) {
+ // Only restricted by the toggles, do not restrict
+ return ACTIVITY_RESTRICTION_NONE;
+ }
+ }
+ }
return ACTIVITY_RESTRICTION_APPOP;
}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 3dea686..c869ec6 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -362,8 +362,10 @@
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Wallpaper animation!");
switch (firstTransit) {
case TRANSIT_OPEN:
+ case TRANSIT_TO_FRONT:
return TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
case TRANSIT_CLOSE:
+ case TRANSIT_TO_BACK:
return TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
}
} else if (oldWallpaper != null && !openingApps.isEmpty()
diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
index 35add12..f61cc94 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@@ -26,6 +26,7 @@
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.Slog;
import android.view.SurfaceControl;
import android.window.DisplayAreaAppearedInfo;
import android.window.IDisplayAreaOrganizer;
@@ -49,7 +50,8 @@
final ActivityTaskManagerService mService;
private final WindowManagerGlobalLock mGlobalLock;
- private final HashMap<Integer, IDisplayAreaOrganizer> mOrganizersByFeatureIds = new HashMap();
+ private final HashMap<Integer, DisplayAreaOrganizerState> mOrganizersByFeatureIds =
+ new HashMap();
private class DeathRecipient implements IBinder.DeathRecipient {
int mFeature;
@@ -63,12 +65,41 @@
@Override
public void binderDied() {
synchronized (mGlobalLock) {
- mOrganizersByFeatureIds.remove(mFeature);
- removeOrganizer(mOrganizer);
+ mOrganizersByFeatureIds.remove(mFeature).destroy();
}
}
}
+ private class DisplayAreaOrganizerState {
+ private final IDisplayAreaOrganizer mOrganizer;
+ private final DeathRecipient mDeathRecipient;
+
+ DisplayAreaOrganizerState(IDisplayAreaOrganizer organizer, int feature) {
+ mOrganizer = organizer;
+ mDeathRecipient = new DeathRecipient(organizer, feature);
+ try {
+ organizer.asBinder().linkToDeath(mDeathRecipient, 0);
+ } catch (RemoteException e) {
+ // Oh well...
+ }
+ }
+
+ void destroy() {
+ IBinder organizerBinder = mOrganizer.asBinder();
+ mService.mRootWindowContainer.forAllDisplayAreas((da) -> {
+ if (da.mOrganizer != null && da.mOrganizer.asBinder().equals(organizerBinder)) {
+ if (da.isTaskDisplayArea() && da.asTaskDisplayArea().mCreatedByOrganizer) {
+ // Delete the organizer created TDA when unregister.
+ deleteTaskDisplayArea(da.asTaskDisplayArea());
+ } else {
+ da.setOrganizer(null);
+ }
+ }
+ });
+ organizerBinder.unlinkToDeath(mDeathRecipient, 0);
+ }
+ }
+
DisplayAreaOrganizerController(ActivityTaskManagerService atm) {
mService = atm;
mGlobalLock = atm.mGlobalLock;
@@ -80,7 +111,8 @@
@Nullable
IDisplayAreaOrganizer getOrganizerByFeature(int featureId) {
- return mOrganizersByFeatureIds.get(featureId);
+ final DisplayAreaOrganizerState state = mOrganizersByFeatureIds.get(featureId);
+ return state != null ? state.mOrganizer : null;
}
@Override
@@ -94,17 +126,18 @@
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register display organizer=%s uid=%d",
organizer.asBinder(), uid);
if (mOrganizersByFeatureIds.get(feature) != null) {
- throw new IllegalStateException(
- "Replacing existing organizer currently unsupported");
+ if (mOrganizersByFeatureIds.get(feature).mOrganizer.asBinder()
+ .isBinderAlive()) {
+ throw new IllegalStateException(
+ "Replacing existing organizer currently unsupported");
+ }
+
+ mOrganizersByFeatureIds.remove(feature).destroy();
+ Slog.d(TAG, "Replacing dead organizer for feature=" + feature);
}
- final DeathRecipient dr = new DeathRecipient(organizer, feature);
- try {
- organizer.asBinder().linkToDeath(dr, 0);
- } catch (RemoteException e) {
- // Oh well...
- }
-
+ final DisplayAreaOrganizerState state = new DisplayAreaOrganizerState(organizer,
+ feature);
final List<DisplayAreaAppearedInfo> displayAreaInfos = new ArrayList<>();
mService.mRootWindowContainer.forAllDisplays(dc -> {
if (!dc.isTrusted()) {
@@ -120,7 +153,7 @@
});
});
- mOrganizersByFeatureIds.put(feature, organizer);
+ mOrganizersByFeatureIds.put(feature, state);
return new ParceledListSlice<>(displayAreaInfos);
}
} finally {
@@ -137,9 +170,14 @@
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Unregister display organizer=%s uid=%d",
organizer.asBinder(), uid);
- mOrganizersByFeatureIds.entrySet().removeIf(
- entry -> entry.getValue().asBinder() == organizer.asBinder());
- removeOrganizer(organizer);
+ mOrganizersByFeatureIds.entrySet().removeIf((entry) -> {
+ final boolean matches = entry.getValue().mOrganizer.asBinder()
+ == organizer.asBinder();
+ if (matches) {
+ entry.getValue().destroy();
+ }
+ return matches;
+ });
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -190,19 +228,15 @@
}
final int taskDisplayAreaFeatureId = mNextTaskDisplayAreaFeatureId++;
- final DeathRecipient dr = new DeathRecipient(organizer, taskDisplayAreaFeatureId);
- try {
- organizer.asBinder().linkToDeath(dr, 0);
- } catch (RemoteException e) {
- // Oh well...
- }
+ final DisplayAreaOrganizerState state = new DisplayAreaOrganizerState(organizer,
+ taskDisplayAreaFeatureId);
final TaskDisplayArea tda = parentRoot != null
? createTaskDisplayArea(parentRoot, name, taskDisplayAreaFeatureId)
: createTaskDisplayArea(parentTda, name, taskDisplayAreaFeatureId);
final DisplayAreaAppearedInfo tdaInfo = organizeDisplayArea(organizer, tda,
"DisplayAreaOrganizerController.createTaskDisplayArea");
- mOrganizersByFeatureIds.put(taskDisplayAreaFeatureId, organizer);
+ mOrganizersByFeatureIds.put(taskDisplayAreaFeatureId, state);
return tdaInfo;
}
} finally {
@@ -230,8 +264,7 @@
+ "TaskDisplayArea=" + taskDisplayArea);
}
- mOrganizersByFeatureIds.remove(taskDisplayArea.mFeatureId);
- deleteTaskDisplayArea(taskDisplayArea);
+ mOrganizersByFeatureIds.remove(taskDisplayArea.mFeatureId).destroy();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -251,6 +284,10 @@
void onDisplayAreaVanished(IDisplayAreaOrganizer organizer, DisplayArea da) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "DisplayArea vanished name=%s", da.getName());
+ if (!organizer.asBinder().isBinderAlive()) {
+ Slog.d(TAG, "Organizer died before sending onDisplayAreaVanished");
+ return;
+ }
try {
organizer.onDisplayAreaVanished(da.getDisplayAreaInfo());
} catch (RemoteException e) {
@@ -267,20 +304,6 @@
}
}
- private void removeOrganizer(IDisplayAreaOrganizer organizer) {
- IBinder organizerBinder = organizer.asBinder();
- mService.mRootWindowContainer.forAllDisplayAreas((da) -> {
- if (da.mOrganizer != null && da.mOrganizer.asBinder().equals(organizerBinder)) {
- if (da.isTaskDisplayArea() && da.asTaskDisplayArea().mCreatedByOrganizer) {
- // Delete the organizer created TDA when unregister.
- deleteTaskDisplayArea(da.asTaskDisplayArea());
- } else {
- da.setOrganizer(null);
- }
- }
- });
- }
-
private DisplayAreaAppearedInfo organizeDisplayArea(IDisplayAreaOrganizer organizer,
DisplayArea displayArea, String callsite) {
displayArea.setOrganizer(organizer, true /* skipDisplayAreaAppeared */);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a72d9aa..3144c87 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1884,7 +1884,7 @@
forAllWindows(w -> {
w.seamlesslyRotateIfAllowed(transaction, oldRotation, rotation, rotateSeamlessly);
}, true /* traverseTopToBottom */);
- mPinnedTaskController.startSeamlessRotationIfNeeded(transaction);
+ mPinnedTaskController.startSeamlessRotationIfNeeded(transaction, oldRotation, rotation);
}
mWmService.mDisplayManagerInternal.performTraversal(transaction);
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 3208ae3..672ebf1 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -66,6 +66,8 @@
private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_ATM;
+ static final String KEYGUARD_SLEEP_TOKEN_TAG = "keyguard";
+
private final ActivityTaskSupervisor mTaskSupervisor;
private WindowManagerService mWindowManager;
private boolean mKeyguardShowing;
@@ -82,7 +84,7 @@
ActivityTaskSupervisor taskSupervisor) {
mService = service;
mTaskSupervisor = taskSupervisor;
- mSleepTokenAcquirer = mService.new SleepTokenAcquirerImpl("keyguard");
+ mSleepTokenAcquirer = mService.new SleepTokenAcquirerImpl(KEYGUARD_SLEEP_TOKEN_TAG);
}
void setWindowManager(WindowManagerService windowManager) {
diff --git a/services/core/java/com/android/server/wm/PinnedTaskController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java
index 31e2ede..7e95e7d 100644
--- a/services/core/java/com/android/server/wm/PinnedTaskController.java
+++ b/services/core/java/com/android/server/wm/PinnedTaskController.java
@@ -27,13 +27,16 @@
import android.content.ComponentName;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
+import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
+import android.util.RotationUtils;
import android.util.Slog;
import android.view.IPinnedTaskListener;
+import android.view.Surface;
import android.view.SurfaceControl;
import android.window.PictureInPictureSurfaceTransaction;
@@ -237,7 +240,8 @@
* rotation of display. The final surface matrix will be replaced by PiPTaskOrganizer after it
* receives the callback of fixed rotation completion.
*/
- void startSeamlessRotationIfNeeded(SurfaceControl.Transaction t) {
+ void startSeamlessRotationIfNeeded(SurfaceControl.Transaction t,
+ int oldRotation, int newRotation) {
final Rect bounds = mDestRotatedBounds;
final PictureInPictureSurfaceTransaction pipTx = mPipTransaction;
if (bounds == null && pipTx == null) {
@@ -280,6 +284,16 @@
? params.getSourceRectHint()
: null;
Slog.i(TAG, "Seamless rotation PiP bounds=" + bounds + " hintRect=" + sourceHintRect);
+ final int rotationDelta = RotationUtils.deltaRotation(oldRotation, newRotation);
+ // Adjust for display cutout if applicable.
+ if (sourceHintRect != null && rotationDelta == Surface.ROTATION_270) {
+ if (pinnedTask.getDisplayCutoutInsets() != null) {
+ final int rotationBackDelta = RotationUtils.deltaRotation(newRotation, oldRotation);
+ final Rect displayCutoutInsets = RotationUtils.rotateInsets(
+ Insets.of(pinnedTask.getDisplayCutoutInsets()), rotationBackDelta).toRect();
+ sourceHintRect.offset(displayCutoutInsets.left, displayCutoutInsets.top);
+ }
+ }
final Rect contentBounds = sourceHintRect != null && areaBounds.contains(sourceHintRect)
? sourceHintRect : areaBounds;
final int w = contentBounds.width();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 3214721..b6e0d8d 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -66,6 +66,7 @@
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
+import static com.android.server.wm.KeyguardController.KEYGUARD_SLEEP_TOKEN_TAG;
import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT;
import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER;
import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
@@ -2048,7 +2049,7 @@
/**
* Move root task with all its existing content to specified task display area.
*
- * @param rootTaskId Id of root task to move.
+ * @param rootTaskId Id of root task to move.
* @param taskDisplayArea The task display area to move root task to.
* @param onTop Indicates whether container should be place on top or on bottom.
*/
@@ -2086,9 +2087,9 @@
/**
* Move root task with all its existing content to specified display.
*
- * @param rootTaskId Id of root task to move.
- * @param displayId Id of display to move root task to.
- * @param onTop Indicates whether container should be place on top or on bottom.
+ * @param rootTaskId Id of root task to move.
+ * @param displayId Id of display to move root task to.
+ * @param onTop Indicates whether container should be place on top or on bottom.
*/
void moveRootTaskToDisplay(int rootTaskId, int displayId, boolean onTop) {
final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
@@ -2171,7 +2172,7 @@
final ActivityRecord oldTopActivity = task.getTopMostActivity();
if (oldTopActivity != null && oldTopActivity.isState(STOPPED)
&& task.getDisplayContent().mAppTransition.containsTransitRequest(
- TRANSIT_TO_BACK)) {
+ TRANSIT_TO_BACK)) {
task.getDisplayContent().mClosingApps.add(oldTopActivity);
oldTopActivity.mRequestForceTransition = true;
}
@@ -2664,13 +2665,28 @@
}
mSleepTokens.remove(token.mHashKey);
final DisplayContent display = getDisplayContent(token.mDisplayId);
- if (display != null) {
- display.mAllSleepTokens.remove(token);
- if (display.mAllSleepTokens.isEmpty()) {
- mService.updateSleepIfNeededLocked();
- if (token.mTag.equals(DISPLAY_OFF_SLEEP_TOKEN_TAG)) {
- display.mSkipAppTransitionAnimation = true;
- }
+ if (display == null) {
+ Slog.d(TAG, "Remove sleep token for non-existing display: " + token + " from "
+ + Debug.getCallers(6));
+ return;
+ }
+
+ display.mAllSleepTokens.remove(token);
+ if (display.mAllSleepTokens.isEmpty()) {
+ mService.updateSleepIfNeededLocked();
+ // Assuming no lock screen is set and a user launches an activity, turns off the screen
+ // and turn on the screen again, then the launched activity should be displayed on the
+ // screen without app transition animation. When the screen turns on, both keyguard
+ // sleep token and display off sleep token are removed, but the order is
+ // non-deterministic.
+ // Note: Display#mSkipAppTransitionAnimation will be ignored when keyguard related
+ // transition exists, so this affects only when no lock screen is set. Otherwise
+ // keyguard going away animation will be played.
+ // See also AppTransitionController#getTransitCompatType for more details.
+ if ((!mTaskSupervisor.getKeyguardController().isDisplayOccluded(display.mDisplayId)
+ && token.mTag.equals(KEYGUARD_SLEEP_TOKEN_TAG))
+ || token.mTag.equals(DISPLAY_OFF_SLEEP_TOKEN_TAG)) {
+ display.mSkipAppTransitionAnimation = true;
}
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a113254..382a2b1 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4105,7 +4105,7 @@
info.positionInParent = getRelativePosition();
info.pictureInPictureParams = getPictureInPictureParams(top);
- info.displayCutoutInsets = getDisplayCutoutInsets(top);
+ info.displayCutoutInsets = top != null ? top.getDisplayCutoutInsets() : null;
info.topActivityInfo = mReuseActivitiesReport.top != null
? mReuseActivitiesReport.top.info
: null;
@@ -4140,16 +4140,15 @@
? null : new PictureInPictureParams(topVisibleActivity.pictureInPictureArgs);
}
- private Rect getDisplayCutoutInsets(Task top) {
- if (top == null || top.mDisplayContent == null
- || top.getDisplayInfo().displayCutout == null) return null;
- final WindowState w = top.getTopVisibleAppMainWindow();
+ Rect getDisplayCutoutInsets() {
+ if (mDisplayContent == null || getDisplayInfo().displayCutout == null) return null;
+ final WindowState w = getTopVisibleAppMainWindow();
final int displayCutoutMode = w == null
? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
: w.getAttrs().layoutInDisplayCutoutMode;
return (displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
|| displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)
- ? null : top.getDisplayInfo().displayCutout.getSafeInsets();
+ ? null : getDisplayInfo().displayCutout.getSafeInsets();
}
/**
diff --git a/services/core/jni/com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp b/services/core/jni/com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp
index e994c03..d3d532b 100644
--- a/services/core/jni/com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp
+++ b/services/core/jni/com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp
@@ -16,18 +16,19 @@
#define LOG_TAG "SurfaceToNativeHandleConverter"
-#include <nativehelper/JNIHelp.h>
-#include "jni.h"
-
-#include <android/native_window_jni.h>
#include <android_os_NativeHandle.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
+#include <utils/Log.h>
+
+#include "jni.h"
namespace android {
-
namespace {
+
constexpr int WINDOW_HAL_TOKEN_SIZE_MAX = 256;
native_handle_t* convertHalTokenToNativeHandle(const HalToken& halToken) {
@@ -54,33 +55,73 @@
memcpy(&(nh->data[1]), halToken.data(), nhDataByteSize);
return nh;
}
-} // namespace
-using ::android::sp;
+HalToken convertNativeHandleToHalToken(native_handle_t* handle) {
+ int size = handle->data[0];
+ auto data = reinterpret_cast<uint8_t*>(&handle->data[1]);
+ HalToken halToken;
+ halToken.setToExternal(data, size);
+ return halToken;
+}
-static jobject convertSurfaceToNativeHandle(JNIEnv* env, jobject /* clazz */,
- jobject previewSurface) {
- if (previewSurface == nullptr) {
+jobject acquireSurfaceHandle(JNIEnv* env, jobject /* clazz */, jobject jSurface) {
+ ALOGD("%s", __func__);
+ if (jSurface == nullptr) {
+ ALOGE("%s: jSurface is null", __func__);
return nullptr;
}
- ANativeWindow* previewAnw = ANativeWindow_fromSurface(env, previewSurface);
- sp<Surface> surface = static_cast<Surface*>(previewAnw);
+
+ sp<Surface> surface = android_view_Surface_getSurface(env, jSurface);
+ if (surface == nullptr) {
+ ALOGE("%s: surface is null", __func__);
+ return nullptr;
+ }
+
sp<IGraphicBufferProducer> igbp = surface->getIGraphicBufferProducer();
sp<HGraphicBufferProducer> hgbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(igbp);
+ // The HAL token will be closed in releaseSurfaceHandle.
HalToken halToken;
createHalToken(hgbp, &halToken);
+
native_handle_t* native_handle = convertHalTokenToNativeHandle(halToken);
- return JNativeHandle::MakeJavaNativeHandleObj(env, native_handle);
+ if (native_handle == nullptr) {
+ ALOGE("%s: native_handle is null", __func__);
+ return nullptr;
+ }
+ jobject jHandle = JNativeHandle::MakeJavaNativeHandleObj(env, native_handle);
+ native_handle_delete(native_handle);
+
+ return jHandle;
}
-static const JNINativeMethod method_table[] = {
- {"convertSurfaceToNativeHandle", "(Landroid/view/Surface;)Landroid/os/NativeHandle;",
- reinterpret_cast<void*>(convertSurfaceToNativeHandle)},
+void releaseSurfaceHandle(JNIEnv* env, jobject /* clazz */, jobject jHandle) {
+ ALOGD("%s", __func__);
+ // Creates a native handle from a Java handle. We must call native_handle_delete when we're done
+ // with it because we created it, but we shouldn't call native_handle_close because we don't own
+ // the underlying FDs.
+ native_handle_t* handle =
+ JNativeHandle::MakeCppNativeHandle(env, jHandle, nullptr /* storage */);
+ if (handle == nullptr) {
+ ALOGE("%s: handle is null", __func__);
+ return;
+ }
+
+ HalToken token = convertNativeHandleToHalToken(handle);
+ ALOGD("%s: deleteHalToken, success: %d", __func__, deleteHalToken(token));
+ ALOGD("%s: native_handle_delete, success: %d", __func__, !native_handle_delete(handle));
+}
+
+const JNINativeMethod method_table[] = {
+ {"acquireSurfaceHandle", "(Landroid/view/Surface;)Landroid/os/NativeHandle;",
+ reinterpret_cast<void*>(acquireSurfaceHandle)},
+ {"releaseSurfaceHandle", "(Landroid/os/NativeHandle;)V",
+ reinterpret_cast<void*>(releaseSurfaceHandle)},
};
+} // namespace
int register_android_server_FaceService(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "com/android/server/biometrics/sensors/face/FaceService",
- method_table, NELEM(method_table));
+ return AndroidRuntime::
+ registerNativeMethods(env, "com/android/server/biometrics/sensors/face/FaceService",
+ method_table, NELEM(method_table));
}
-
-}; // namespace android
+} // namespace android
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index e31be82..d0205ae 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -350,8 +350,10 @@
}
if (mDeviceConnections != null) {
- for (DeviceConnection connection : mDeviceConnections) {
- connection.notifyClient(server);
+ synchronized (mDeviceConnections) {
+ for (DeviceConnection connection : mDeviceConnections) {
+ connection.notifyClient(server);
+ }
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index a8bf0c7..1fe4123 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -372,6 +372,11 @@
protected void startHalOperation() {
}
+
+ @Override
+ protected void handleLifecycleAfterAuth(boolean authenticated) {
+
+ }
}
private static class TestAuthenticationClient extends AuthenticationClient<Object> {
@@ -395,6 +400,11 @@
protected void startHalOperation() {
}
+
+ @Override
+ protected void handleLifecycleAfterAuth(boolean authenticated) {
+
+ }
}
private static class TestClientMonitor2 extends TestClientMonitor {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
index 589463e..fb05825 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
@@ -16,64 +16,294 @@
package com.android.server.biometrics.sensors;
+import static com.android.server.biometrics.sensors.BiometricScheduler.SENSOR_TYPE_FACE;
+import static com.android.server.biometrics.sensors.BiometricScheduler.SENSOR_TYPE_UDFPS;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
import static org.mockito.ArgumentMatchers.anyBoolean;
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 static org.mockito.Mockito.withSettings;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
import android.platform.test.annotations.Presubmit;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.sensors.fingerprint.Udfps;
+
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.LinkedList;
+
@Presubmit
@SmallTest
public class CoexCoordinatorTest {
- private CoexCoordinator mCoexCoordinator;
+ private static final String TAG = "CoexCoordinatorTest";
+ private CoexCoordinator mCoexCoordinator;
+ private Handler mHandler;
+
+ @Mock
+ private Context mContext;
@Mock
private CoexCoordinator.Callback mCallback;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+
+ mHandler = new Handler(Looper.getMainLooper());
+
mCoexCoordinator = CoexCoordinator.getInstance();
+ mCoexCoordinator.setAdvancedLogicEnabled(true);
}
@Test
public void testBiometricPrompt_authSuccess() {
+ mCoexCoordinator.reset();
+
AuthenticationClient<?> client = mock(AuthenticationClient.class);
when(client.isBiometricPrompt()).thenReturn(true);
- mCoexCoordinator.onAuthenticationSucceeded(client, mCallback);
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+ mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, client, mCallback);
verify(mCallback).sendHapticFeedback();
verify(mCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+ verify(mCallback).handleLifecycleAfterAuth();
}
@Test
public void testBiometricPrompt_authReject_whenNotLockedOut() {
+ mCoexCoordinator.reset();
+
AuthenticationClient<?> client = mock(AuthenticationClient.class);
when(client.isBiometricPrompt()).thenReturn(true);
- mCoexCoordinator.onAuthenticationRejected(client, LockoutTracker.LOCKOUT_NONE, mCallback);
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+ mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */,
+ client, LockoutTracker.LOCKOUT_NONE, mCallback);
verify(mCallback).sendHapticFeedback();
verify(mCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+ verify(mCallback).handleLifecycleAfterAuth();
}
@Test
public void testBiometricPrompt_authReject_whenLockedOut() {
+ mCoexCoordinator.reset();
+
AuthenticationClient<?> client = mock(AuthenticationClient.class);
when(client.isBiometricPrompt()).thenReturn(true);
- mCoexCoordinator.onAuthenticationRejected(client, LockoutTracker.LOCKOUT_TIMED, mCallback);
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+ mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */,
+ client, LockoutTracker.LOCKOUT_TIMED, mCallback);
verify(mCallback).sendHapticFeedback();
verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+ verify(mCallback).handleLifecycleAfterAuth();
+ }
+
+ @Test
+ public void testKeyguard_faceAuthOnly_success() {
+ mCoexCoordinator.reset();
+
+ AuthenticationClient<?> client = mock(AuthenticationClient.class);
+ when(client.isKeyguard()).thenReturn(true);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+ mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, client, mCallback);
+ verify(mCallback).sendHapticFeedback();
+ verify(mCallback).sendAuthenticationResult(eq(true) /* addAuthTokenIfStrong */);
+ verify(mCallback).handleLifecycleAfterAuth();
+ }
+
+ @Test
+ public void testKeyguard_faceAuth_udfpsNotTouching_faceSuccess() {
+ mCoexCoordinator.reset();
+
+ AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+ when(faceClient.isKeyguard()).thenReturn(true);
+
+ AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
+ withSettings().extraInterfaces(Udfps.class));
+ when(udfpsClient.isKeyguard()).thenReturn(true);
+ when(((Udfps) udfpsClient).isPointerDown()).thenReturn(false);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+ mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, faceClient,
+ mCallback);
+ verify(mCallback).sendHapticFeedback();
+ verify(mCallback).sendAuthenticationResult(eq(true) /* addAuthTokenIfStrong */);
+ verify(mCallback).handleLifecycleAfterAuth();
+ }
+
+ @Test
+ public void testKeyguard_faceAuth_udfpsTouching_faceSuccess_thenUdfpsRejectedWithinBounds() {
+ testKeyguard_faceAuth_udfpsTouching_faceSuccess(false /* thenUdfpsAccepted */,
+ 0 /* udfpsRejectedAfterMs */);
+ }
+
+ @Test
+ public void testKeyguard_faceAuth_udfpsTouching_faceSuccess_thenUdfpsRejectedAfterBounds() {
+ testKeyguard_faceAuth_udfpsTouching_faceSuccess(false /* thenUdfpsAccepted */,
+ CoexCoordinator.SUCCESSFUL_AUTH_VALID_DURATION_MS + 1 /* udfpsRejectedAfterMs */);
+ }
+
+ @Test
+ public void testKeyguard_faceAuth_udfpsTouching_faceSuccess_thenUdfpsAccepted() {
+ testKeyguard_faceAuth_udfpsTouching_faceSuccess(true /* thenUdfpsAccepted */,
+ 0 /* udfpsRejectedAfterMs */);
+ }
+
+ private void testKeyguard_faceAuth_udfpsTouching_faceSuccess(boolean thenUdfpsAccepted,
+ long udfpsRejectedAfterMs) {
+ mCoexCoordinator.reset();
+
+ AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+ when(faceClient.isKeyguard()).thenReturn(true);
+
+ AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
+ withSettings().extraInterfaces(Udfps.class));
+ when(udfpsClient.isKeyguard()).thenReturn(true);
+ when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
+ when (udfpsClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+ mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, faceClient,
+ mCallback);
+ verify(mCallback, never()).sendHapticFeedback();
+ verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+ // CoexCoordinator requests the system to hold onto this AuthenticationClient until
+ // UDFPS result is known
+ verify(mCallback, never()).handleLifecycleAfterAuth();
+
+ // Reset the mock
+ CoexCoordinator.Callback udfpsCallback = mock(CoexCoordinator.Callback.class);
+ assertEquals(1, mCoexCoordinator.mSuccessfulAuths.size());
+ assertEquals(faceClient, mCoexCoordinator.mSuccessfulAuths.get(0).mAuthenticationClient);
+ if (thenUdfpsAccepted) {
+ mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, udfpsClient,
+ udfpsCallback);
+ verify(udfpsCallback).sendHapticFeedback();
+ verify(udfpsCallback).sendAuthenticationResult(true /* addAuthTokenIfStrong */);
+ verify(udfpsCallback).handleLifecycleAfterAuth();
+
+ assertTrue(mCoexCoordinator.mSuccessfulAuths.isEmpty());
+ } else {
+ mCoexCoordinator.onAuthenticationRejected(udfpsRejectedAfterMs, udfpsClient,
+ LockoutTracker.LOCKOUT_NONE, udfpsCallback);
+ if (udfpsRejectedAfterMs <= CoexCoordinator.SUCCESSFUL_AUTH_VALID_DURATION_MS) {
+ verify(udfpsCallback, never()).sendHapticFeedback();
+
+ verify(mCallback).sendHapticFeedback();
+ verify(mCallback).sendAuthenticationResult(eq(true) /* addAuthTokenIfStrong */);
+ verify(mCallback).handleLifecycleAfterAuth();
+
+ assertTrue(mCoexCoordinator.mSuccessfulAuths.isEmpty());
+ } else {
+ assertTrue(mCoexCoordinator.mSuccessfulAuths.isEmpty());
+
+ verify(mCallback, never()).sendHapticFeedback();
+ verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+
+ verify(udfpsCallback).sendHapticFeedback();
+ verify(udfpsCallback)
+ .sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+ verify(udfpsCallback).handleLifecycleAfterAuth();
+ }
+ }
+ }
+
+ @Test
+ public void testKeyguard_udfpsAuthSuccess_whileFaceScanning() {
+ mCoexCoordinator.reset();
+
+ AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+ when(faceClient.isKeyguard()).thenReturn(true);
+ when(faceClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+
+ AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
+ withSettings().extraInterfaces(Udfps.class));
+ when(udfpsClient.isKeyguard()).thenReturn(true);
+ when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+ mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, udfpsClient,
+ mCallback);
+ verify(mCallback).sendHapticFeedback();
+ verify(mCallback).sendAuthenticationResult(eq(true));
+ verify(faceClient).cancel();
+ verify(mCallback).handleLifecycleAfterAuth();
+ }
+
+ @Test
+ public void testNonKeyguard_rejectAndNotLockedOut() {
+ mCoexCoordinator.reset();
+
+ AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+ when(faceClient.isKeyguard()).thenReturn(false);
+ when(faceClient.isBiometricPrompt()).thenReturn(true);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+ mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, faceClient,
+ LockoutTracker.LOCKOUT_NONE, mCallback);
+
+ verify(mCallback).sendHapticFeedback();
+ verify(mCallback).sendAuthenticationResult(eq(false));
+ verify(mCallback).handleLifecycleAfterAuth();
+ }
+
+ @Test
+ public void testNonKeyguard_rejectLockedOut() {
+ mCoexCoordinator.reset();
+
+ AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+ when(faceClient.isKeyguard()).thenReturn(false);
+ when(faceClient.isBiometricPrompt()).thenReturn(true);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+ mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, faceClient,
+ LockoutTracker.LOCKOUT_TIMED, mCallback);
+
+ verify(mCallback).sendHapticFeedback();
+ verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+ verify(mCallback).handleLifecycleAfterAuth();
+ }
+
+ @Test
+ public void testCleanupRunnable() {
+ LinkedList<CoexCoordinator.SuccessfulAuth> successfulAuths = mock(LinkedList.class);
+ CoexCoordinator.SuccessfulAuth auth = mock(CoexCoordinator.SuccessfulAuth.class);
+ CoexCoordinator.Callback callback = mock(CoexCoordinator.Callback.class);
+ CoexCoordinator.SuccessfulAuth.CleanupRunnable runnable =
+ new CoexCoordinator.SuccessfulAuth.CleanupRunnable(successfulAuths, auth, callback);
+ runnable.run();
+
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+ verify(callback).handleLifecycleAfterAuth();
+ verify(successfulAuths).remove(eq(auth));
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index c555612..3a6aac9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
@@ -27,6 +28,7 @@
import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -167,6 +169,69 @@
assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_OLD_TASK_OPEN, task));
}
+
+ @Test
+ public void testIntraWallpaper_open() {
+ final ActivityRecord opening = createActivityRecord(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ opening.setVisible(false);
+ final WindowManager.LayoutParams attrOpening = new WindowManager.LayoutParams(
+ TYPE_BASE_APPLICATION);
+ attrOpening.setTitle("WallpaperOpening");
+ attrOpening.flags |= FLAG_SHOW_WALLPAPER;
+ final TestWindowState appWindowOpening = createWindowState(attrOpening, opening);
+ opening.addWindow(appWindowOpening);
+
+ final ActivityRecord closing = createActivityRecord(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final WindowManager.LayoutParams attrClosing = new WindowManager.LayoutParams(
+ TYPE_BASE_APPLICATION);
+ attrOpening.setTitle("WallpaperClosing");
+ attrClosing.flags |= FLAG_SHOW_WALLPAPER;
+ final TestWindowState appWindowClosing = createWindowState(attrClosing, closing);
+ closing.addWindow(appWindowClosing);
+
+ mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
+ mDisplayContent.mOpeningApps.add(opening);
+ mDisplayContent.mClosingApps.add(closing);
+
+ assertEquals(WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN,
+ AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
+ mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
+ appWindowClosing, null, false));
+ }
+
+ @Test
+ public void testIntraWallpaper_toFront() {
+ final ActivityRecord opening = createActivityRecord(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ opening.setVisible(false);
+ final WindowManager.LayoutParams attrOpening = new WindowManager.LayoutParams(
+ TYPE_BASE_APPLICATION);
+ attrOpening.setTitle("WallpaperOpening");
+ attrOpening.flags |= FLAG_SHOW_WALLPAPER;
+ final TestWindowState appWindowOpening = createWindowState(attrOpening, opening);
+ opening.addWindow(appWindowOpening);
+
+ final ActivityRecord closing = createActivityRecord(mDisplayContent,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final WindowManager.LayoutParams attrClosing = new WindowManager.LayoutParams(
+ TYPE_BASE_APPLICATION);
+ attrOpening.setTitle("WallpaperClosing");
+ attrClosing.flags |= FLAG_SHOW_WALLPAPER;
+ final TestWindowState appWindowClosing = createWindowState(attrClosing, closing);
+ closing.addWindow(appWindowClosing);
+
+ mDisplayContent.prepareAppTransition(TRANSIT_TO_FRONT);
+ mDisplayContent.mOpeningApps.add(opening);
+ mDisplayContent.mClosingApps.add(closing);
+
+ assertEquals(WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN,
+ AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
+ mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
+ appWindowClosing, null, false));
+ }
+
@Test
public void testGetAnimationTargets_visibilityAlreadyUpdated() {
// [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, visible)
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
index d5628fc..4e4e0ed 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
@@ -24,6 +24,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
+import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_LAST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -57,6 +58,7 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
+import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
import android.view.View;
@@ -555,6 +557,7 @@
final DisplayArea<WindowContainer> displayArea = new DisplayArea<>(
mWm, BELOW_TASKS, "NewArea", FEATURE_VENDOR_FIRST);
final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class);
+ doReturn(mock(IBinder.class)).when(mockDisplayAreaOrganizer).asBinder();
displayArea.mOrganizer = mockDisplayAreaOrganizer;
spyOn(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController);
mDisplayContent.addChild(displayArea, 0);
@@ -566,6 +569,30 @@
.onDisplayAreaVanished(mockDisplayAreaOrganizer, displayArea);
}
+ @Test
+ public void testRegisterSameFeatureOrganizer_expectThrowsException() {
+ final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class);
+ final IBinder binder = mock(IBinder.class);
+ doReturn(true).when(binder).isBinderAlive();
+ doReturn(binder).when(mockDisplayAreaOrganizer).asBinder();
+ final DisplayAreaOrganizerController controller =
+ mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController;
+ controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST);
+ assertThrows(IllegalStateException.class,
+ () -> controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST));
+ }
+
+ @Test
+ public void testRegisterUnregisterOrganizer() {
+ final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class);
+ doReturn(mock(IBinder.class)).when(mockDisplayAreaOrganizer).asBinder();
+ final DisplayAreaOrganizerController controller =
+ mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController;
+ controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST);
+ controller.unregisterOrganizer(mockDisplayAreaOrganizer);
+ controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST);
+ }
+
private static class TestDisplayArea<T extends WindowContainer> extends DisplayArea<T> {
private TestDisplayArea(WindowManagerService wms, Rect bounds) {
super(wms, ANY, "half display area");
diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
index 9cdaef7..738e68e 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -196,6 +196,47 @@
}
@Test
+ public void testActiveApexIsRevertedOnCheckpointRollback_Prepare() throws Exception {
+ int sessionId = Install.single(TestApp.Apex2).setStaged().commit();
+ assertSessionReady(sessionId);
+ storeSessionId(sessionId);
+ }
+
+ @Test
+ public void testActiveApexIsRevertedOnCheckpointRollback_Commit() throws Exception {
+ // Verify apex installed during preparation was successful
+ int sessionId = retrieveLastSessionId();
+ assertSessionApplied(sessionId);
+ assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(2);
+ // Commit a new staged session
+ sessionId = Install.single(TestApp.Apex3).setStaged().commit();
+ assertSessionReady(sessionId);
+ storeSessionId(sessionId);
+ }
+
+ @Test
+ public void testActiveApexIsRevertedOnCheckpointRollback_VerifyPostReboot() throws Exception {
+ int sessionId = retrieveLastSessionId();
+ assertSessionFailed(sessionId);
+ assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(2);
+ }
+
+ @Test
+ public void testApexIsNotActivatedIfNotInCheckpointMode_Commit() throws Exception {
+ int sessionId = Install.single(TestApp.Apex2).setStaged().commit();
+ assertSessionReady(sessionId);
+ storeSessionId(sessionId);
+ assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+ }
+
+ @Test
+ public void testApexIsNotActivatedIfNotInCheckpointMode_VerifyPostReboot() throws Exception {
+ int sessionId = retrieveLastSessionId();
+ assertSessionFailed(sessionId);
+ assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+ }
+
+ @Test
public void testRebootlessUpdates() throws Exception {
InstallUtils.dropShellPermissionIdentity();
InstallUtils.adoptShellPermissionIdentity(Manifest.permission.INSTALL_PACKAGE_UPDATES);
@@ -257,6 +298,18 @@
}
}
+ private static void assertSessionApplied(int sessionId) {
+ assertSessionState(sessionId, (session) -> {
+ assertThat(session.isStagedSessionApplied()).isTrue();
+ });
+ }
+
+ private static void assertSessionFailed(int sessionId) {
+ assertSessionState(sessionId, (session) -> {
+ assertThat(session.isStagedSessionFailed()).isTrue();
+ });
+ }
+
private static void assertSessionFailedWithMessage(int sessionId, String msg) {
assertSessionState(sessionId, (session) -> {
assertThat(session.isStagedSessionFailed()).isTrue();
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index e19f97b..3bd3767 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -346,6 +346,49 @@
}
@Test
+ public void testActiveApexIsRevertedOnCheckpointRollback() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support file-system checkpoint",
+ mHostUtils.isCheckpointSupported());
+
+ // Install something so that /data/apex/active is not empty
+ runPhase("testActiveApexIsRevertedOnCheckpointRollback_Prepare");
+ getDevice().reboot();
+
+ // Stage another session which will be installed during fs-rollback mode
+ runPhase("testActiveApexIsRevertedOnCheckpointRollback_Commit");
+
+ // Set checkpoint to 0 so that we enter fs-rollback mode immediately on reboot
+ getDevice().enableAdbRoot();
+ getDevice().executeShellCommand("vdc checkpoint startCheckpoint 0");
+ getDevice().disableAdbRoot();
+ getDevice().reboot();
+
+ // Verify that session was reverted and we have fallen back to
+ // apex installed during preparation stage.
+ runPhase("testActiveApexIsRevertedOnCheckpointRollback_VerifyPostReboot");
+ }
+
+ @Test
+ public void testApexIsNotActivatedIfNotInCheckpointMode() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+ assumeTrue("Device does not support file-system checkpoint",
+ mHostUtils.isCheckpointSupported());
+
+ runPhase("testApexIsNotActivatedIfNotInCheckpointMode_Commit");
+ // Delete checkpoint file in /metadata so that device thinks
+ // fs-checkpointing was never activated
+ getDevice().enableAdbRoot();
+ getDevice().executeShellCommand("rm /metadata/vold/checkpoint");
+ getDevice().disableAdbRoot();
+ getDevice().reboot();
+ // Verify that session was not installed when not in fs-checkpoint mode
+ runPhase("testApexIsNotActivatedIfNotInCheckpointMode_VerifyPostReboot");
+ }
+
+ @Test
public void testRebootlessUpdates() throws Exception {
pushTestApex("test.rebootless_apex_v1.apex");
runPhase("testRebootlessUpdates");