Merge "Sharesheet: action bar is independent of WP tabs, should always launch as primary user." into sc-dev
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
index c44fd40..29048b2 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java
@@ -81,6 +81,14 @@
"sampling_interval_for_batch_call_stats";
public static final String KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS =
"sampling_interval_for_put_document_stats";
+ public static final String KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS =
+ "sampling_interval_for_initialize_stats";
+ public static final String KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS =
+ "sampling_interval_for_search_stats";
+ public static final String KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS =
+ "sampling_interval_for_global_search_stats";
+ public static final String KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS =
+ "sampling_interval_for_optimize_stats";
public static final String KEY_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES =
"limit_config_max_document_size_bytes";
public static final String KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT =
@@ -95,6 +103,10 @@
KEY_SAMPLING_INTERVAL_DEFAULT,
KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
+ KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+ KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+ KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+ KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
KEY_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES,
KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT,
KEY_BYTES_OPTIMIZE_THRESHOLD,
@@ -245,6 +257,58 @@
}
}
+ /**
+ * Returns cached value for sampling interval for initialize.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalForInitializeStats() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+ getCachedSamplingIntervalDefault());
+ }
+ }
+
+ /**
+ * Returns cached value for sampling interval for search.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalForSearchStats() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+ getCachedSamplingIntervalDefault());
+ }
+ }
+
+ /**
+ * Returns cached value for sampling interval for globalSearch.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalForGlobalSearchStats() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+ getCachedSamplingIntervalDefault());
+ }
+ }
+
+ /**
+ * Returns cached value for sampling interval for optimize.
+ *
+ * <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
+ */
+ public int getCachedSamplingIntervalForOptimizeStats() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
+ getCachedSamplingIntervalDefault());
+ }
+ }
+
/** Returns the maximum serialized size an indexed document can be, in bytes. */
public int getCachedLimitConfigMaxDocumentSizeBytes() {
synchronized (mLock) {
@@ -343,6 +407,10 @@
case KEY_SAMPLING_INTERVAL_DEFAULT:
case KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS:
case KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS:
+ case KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS:
+ case KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS:
+ case KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS:
+ case KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS:
synchronized (mLock) {
mBundleLocked.putInt(key, properties.getInt(key, DEFAULT_SAMPLING_INTERVAL));
}
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 1d66beb..db23a6d 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -59,6 +59,7 @@
import com.android.server.LocalManagerRegistry;
import com.android.server.SystemService;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
import com.android.server.appsearch.stats.StatsCollector;
import com.android.server.appsearch.util.PackageUtil;
@@ -1479,20 +1480,42 @@
private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
EXECUTOR.execute(() -> {
+ long totalLatencyStartMillis = SystemClock.elapsedRealtime();
+ OptimizeStats.Builder builder = new OptimizeStats.Builder();
try {
- instance.getAppSearchImpl().checkForOptimize(mutateBatchSize);
+ instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
} catch (AppSearchException e) {
Log.w(TAG, "Error occurred when check for optimize", e);
+ } finally {
+ OptimizeStats oStats = builder
+ .setTotalLatencyMillis(
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
+ .build();
+ if (oStats.getOriginalDocumentCount() > 0) {
+ // see if optimize has been run by checking originalDocumentCount
+ instance.getLogger().logStats(oStats);
+ }
}
});
}
private void checkForOptimize(AppSearchUserInstance instance) {
EXECUTOR.execute(() -> {
+ long totalLatencyStartMillis = SystemClock.elapsedRealtime();
+ OptimizeStats.Builder builder = new OptimizeStats.Builder();
try {
- instance.getAppSearchImpl().checkForOptimize();
+ instance.getAppSearchImpl().checkForOptimize(builder);
} catch (AppSearchException e) {
Log.w(TAG, "Error occurred when check for optimize", e);
+ } finally {
+ OptimizeStats oStats = builder
+ .setTotalLatencyMillis(
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
+ .build();
+ if (oStats.getOriginalDocumentCount() > 0) {
+ // see if optimize has been run by checking originalDocumentCount
+ instance.getLogger().logStats(oStats);
+ }
}
});
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 830e76c..15916cc 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -55,6 +55,7 @@
import com.android.server.appsearch.external.localstorage.converter.SetSchemaResponseToProtoConverter;
import com.android.server.appsearch.external.localstorage.converter.TypePropertyPathToProtoConverter;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
@@ -145,6 +146,9 @@
public final class AppSearchImpl implements Closeable {
private static final String TAG = "AppSearchImpl";
+ /** A value 0 means that there're no more pages in the search results. */
+ private static final long EMPTY_PAGE_TOKEN = 0;
+
@VisibleForTesting static final int CHECK_OPTIMIZE_INTERVAL = 100;
private final ReadWriteLock mReadWriteLock = new ReentrantReadWriteLock();
@@ -284,6 +288,9 @@
// Log the time it took to read the data that goes into the cache maps
if (initStatsBuilder != null) {
+ // In case there is some error for getAllNamespaces, we can still
+ // set the latency for preparation.
+ // If there is no error, the value will be overridden by the actual one later.
initStatsBuilder
.setStatusCode(
statusProtoToResultCode(
@@ -1135,6 +1142,16 @@
searchResultProto.getResultsCount(),
searchResultProto);
checkSuccess(searchResultProto.getStatus());
+ if (nextPageToken != EMPTY_PAGE_TOKEN
+ && searchResultProto.getNextPageToken() == EMPTY_PAGE_TOKEN) {
+ // At this point, we're guaranteed that this nextPageToken exists for this package,
+ // otherwise checkNextPageToken would've thrown an exception.
+ // Since the new token is 0, this is the last page. We should remove the old token
+ // from our cache since it no longer refers to this query.
+ synchronized (mNextPageTokensLocked) {
+ mNextPageTokensLocked.get(packageName).remove(nextPageToken);
+ }
+ }
return rewriteSearchResultProto(searchResultProto, mSchemaMapLocked);
} finally {
mReadWriteLock.readLock().unlock();
@@ -1326,8 +1343,7 @@
deleteResultProto.getStatus(), StatusProto.Code.OK, StatusProto.Code.NOT_FOUND);
// Update derived maps
- int numDocumentsDeleted =
- deleteResultProto.getDeleteStats().getNumDocumentsDeleted();
+ int numDocumentsDeleted = deleteResultProto.getDeleteStats().getNumDocumentsDeleted();
updateDocumentCountAfterRemovalLocked(packageName, numDocumentsDeleted);
} finally {
mReadWriteLock.writeLock().unlock();
@@ -2056,6 +2072,10 @@
}
private void addNextPageToken(String packageName, long nextPageToken) {
+ if (nextPageToken == EMPTY_PAGE_TOKEN) {
+ // There is no more pages. No need to add it.
+ return;
+ }
synchronized (mNextPageTokensLocked) {
Set<Long> tokens = mNextPageTokensLocked.get(packageName);
if (tokens == null) {
@@ -2068,6 +2088,11 @@
private void checkNextPageToken(String packageName, long nextPageToken)
throws AppSearchException {
+ if (nextPageToken == EMPTY_PAGE_TOKEN) {
+ // Swallow the check for empty page token, token = 0 means there is no more page and it
+ // won't return anything from Icing.
+ return;
+ }
synchronized (mNextPageTokensLocked) {
Set<Long> nextPageTokens = mNextPageTokensLocked.get(packageName);
if (nextPageTokens == null || !nextPageTokens.contains(nextPageToken)) {
@@ -2162,12 +2187,13 @@
* #CHECK_OPTIMIZE_INTERVAL}, {@link IcingSearchEngine#getOptimizeInfo()} will be triggered
* and the counter will be reset.
*/
- public void checkForOptimize(int mutationSize) throws AppSearchException {
+ public void checkForOptimize(int mutationSize, @Nullable OptimizeStats.Builder builder)
+ throws AppSearchException {
mReadWriteLock.writeLock().lock();
try {
mOptimizeIntervalCountLocked += mutationSize;
if (mOptimizeIntervalCountLocked >= CHECK_OPTIMIZE_INTERVAL) {
- checkForOptimize();
+ checkForOptimize(builder);
}
} finally {
mReadWriteLock.writeLock().unlock();
@@ -2183,14 +2209,15 @@
* <p>{@link IcingSearchEngine#optimize()} should be called only if {@link
* OptimizeStrategy#shouldOptimize(GetOptimizeInfoResultProto)} return true.
*/
- public void checkForOptimize() throws AppSearchException {
+ public void checkForOptimize(@Nullable OptimizeStats.Builder builder)
+ throws AppSearchException {
mReadWriteLock.writeLock().lock();
try {
GetOptimizeInfoResultProto optimizeInfo = getOptimizeInfoResultLocked();
checkSuccess(optimizeInfo.getStatus());
mOptimizeIntervalCountLocked = 0;
if (mOptimizeStrategy.shouldOptimize(optimizeInfo)) {
- optimize();
+ optimize(builder);
}
} finally {
mReadWriteLock.writeLock().unlock();
@@ -2201,13 +2228,18 @@
}
/** Triggers {@link IcingSearchEngine#optimize()} directly. */
- public void optimize() throws AppSearchException {
+ public void optimize(@Nullable OptimizeStats.Builder builder) throws AppSearchException {
mReadWriteLock.writeLock().lock();
try {
mLogUtil.piiTrace("optimize, request");
OptimizeResultProto optimizeResultProto = mIcingSearchEngineLocked.optimize();
mLogUtil.piiTrace(
"optimize, response", optimizeResultProto.getStatus(), optimizeResultProto);
+ if (builder != null) {
+ builder.setStatusCode(statusProtoToResultCode(optimizeResultProto.getStatus()));
+ AppSearchLoggerHelper.copyNativeStats(
+ optimizeResultProto.getOptimizeStats(), builder);
+ }
checkSuccess(optimizeResultProto.getStatus());
} finally {
mReadWriteLock.writeLock().unlock();
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java
index d92f4f0..98cedc7 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java
@@ -17,10 +17,10 @@
package com.android.server.appsearch.external.localstorage;
import android.annotation.NonNull;
-import android.app.appsearch.exceptions.AppSearchException;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
@@ -37,19 +37,22 @@
*/
public interface AppSearchLogger {
/** Logs {@link CallStats} */
- void logStats(@NonNull CallStats stats) throws AppSearchException;
+ void logStats(@NonNull CallStats stats);
/** Logs {@link PutDocumentStats} */
- void logStats(@NonNull PutDocumentStats stats) throws AppSearchException;
+ void logStats(@NonNull PutDocumentStats stats);
/** Logs {@link InitializeStats} */
- void logStats(@NonNull InitializeStats stats) throws AppSearchException;
+ void logStats(@NonNull InitializeStats stats);
/** Logs {@link SearchStats} */
- void logStats(@NonNull SearchStats stats) throws AppSearchException;
+ void logStats(@NonNull SearchStats stats);
/** Logs {@link RemoveStats} */
- void logStats(@NonNull RemoveStats stats) throws AppSearchException;
+ void logStats(@NonNull RemoveStats stats);
+
+ /** Logs {@link OptimizeStats} */
+ void logStats(@NonNull OptimizeStats stats);
// TODO(b/173532925) Add remaining logStats once we add all the stats.
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java
index aa9200a..cd653e5 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java
@@ -19,12 +19,14 @@
import android.annotation.NonNull;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
import com.google.android.icing.proto.DeleteStatsProto;
import com.google.android.icing.proto.InitializeStatsProto;
+import com.google.android.icing.proto.OptimizeStatsProto;
import com.google.android.icing.proto.PutDocumentStatsProto;
import com.google.android.icing.proto.QueryStatsProto;
@@ -92,8 +94,8 @@
.setSchemaTypeCount(fromNativeStats.getNumSchemaTypes());
}
- /*
- * Copy native Query stats to buiilder.
+ /**
+ * Copies native Query stats to builder.
*
* @param fromNativeStats Stats copied from.
* @param toStatsBuilder Stats copied to.
@@ -122,8 +124,8 @@
fromNativeStats.getDocumentRetrievalLatencyMs());
}
- /*
- * Copy native Query stats to buiilder.
+ /**
+ * Copies native Delete stats to builder.
*
* @param fromNativeStats Stats copied from.
* @param toStatsBuilder Stats copied to.
@@ -138,4 +140,28 @@
.setDeleteType(fromNativeStats.getDeleteType().getNumber())
.setDeletedDocumentCount(fromNativeStats.getNumDocumentsDeleted());
}
+
+ /**
+ * Copies native {@link OptimizeStatsProto} to builder.
+ *
+ * @param fromNativeStats Stats copied from.
+ * @param toStatsBuilder Stats copied to.
+ */
+ static void copyNativeStats(
+ @NonNull OptimizeStatsProto fromNativeStats,
+ @NonNull OptimizeStats.Builder toStatsBuilder) {
+ Objects.requireNonNull(fromNativeStats);
+ Objects.requireNonNull(toStatsBuilder);
+ toStatsBuilder
+ .setNativeLatencyMillis(fromNativeStats.getLatencyMs())
+ .setDocumentStoreOptimizeLatencyMillis(
+ fromNativeStats.getDocumentStoreOptimizeLatencyMs())
+ .setIndexRestorationLatencyMillis(fromNativeStats.getIndexRestorationLatencyMs())
+ .setOriginalDocumentCount(fromNativeStats.getNumOriginalDocuments())
+ .setDeletedDocumentCount(fromNativeStats.getNumDeletedDocuments())
+ .setExpiredDocumentCount(fromNativeStats.getNumExpiredDocuments())
+ .setStorageSizeBeforeBytes(fromNativeStats.getStorageSizeBefore())
+ .setStorageSizeAfterBytes(fromNativeStats.getStorageSizeAfter())
+ .setTimeSinceLastOptimizeMillis(fromNativeStats.getTimeSinceLastOptimizeMs());
+ }
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/OptimizeStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/OptimizeStats.java
new file mode 100644
index 0000000..83bd50f
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/OptimizeStats.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.external.localstorage.stats;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchResult;
+
+import java.util.Objects;
+
+/**
+ * Class holds detailed stats for Optimize.
+ *
+ * @hide
+ */
+public final class OptimizeStats {
+ /**
+ * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal
+ * state.
+ */
+ @AppSearchResult.ResultCode private final int mStatusCode;
+
+ private final int mTotalLatencyMillis;
+ private final int mNativeLatencyMillis;
+
+ // Time used to optimize the document store in millis.
+ private final int mNativeDocumentStoreOptimizeLatencyMillis;
+
+ // Time used to restore the index in millis.
+ private final int mNativeIndexRestorationLatencyMillis;
+
+ // Number of documents before the optimization.
+ private final int mNativeOriginalDocumentCount;
+
+ // Number of documents deleted during the optimization.
+ private final int mNativeDeletedDocumentCount;
+
+ // Number of documents expired during the optimization.
+ private final int mNativeExpiredDocumentCount;
+
+ // Size of storage in bytes before the optimization.
+ private final long mNativeStorageSizeBeforeBytes;
+
+ // Size of storage in bytes after the optimization.
+ private final long mNativeStorageSizeAfterBytes;
+
+ // The amount of time in millis since the last optimization ran calculated using wall clock time
+ private final long mNativeTimeSinceLastOptimizeMillis;
+
+ OptimizeStats(@NonNull Builder builder) {
+ Objects.requireNonNull(builder);
+ mStatusCode = builder.mStatusCode;
+ mTotalLatencyMillis = builder.mTotalLatencyMillis;
+ mNativeLatencyMillis = builder.mNativeLatencyMillis;
+ mNativeDocumentStoreOptimizeLatencyMillis =
+ builder.mNativeDocumentStoreOptimizeLatencyMillis;
+ mNativeIndexRestorationLatencyMillis = builder.mNativeIndexRestorationLatencyMillis;
+ mNativeOriginalDocumentCount = builder.mNativeOriginalDocumentCount;
+ mNativeDeletedDocumentCount = builder.mNativeDeletedDocumentCount;
+ mNativeExpiredDocumentCount = builder.mNativeExpiredDocumentCount;
+ mNativeStorageSizeBeforeBytes = builder.mNativeStorageSizeBeforeBytes;
+ mNativeStorageSizeAfterBytes = builder.mNativeStorageSizeAfterBytes;
+ mNativeTimeSinceLastOptimizeMillis = builder.mNativeTimeSinceLastOptimizeMillis;
+ }
+
+ /** Returns status code for this optimization. */
+ @AppSearchResult.ResultCode
+ public int getStatusCode() {
+ return mStatusCode;
+ }
+
+ /** Returns total latency of this optimization in millis. */
+ public int getTotalLatencyMillis() {
+ return mTotalLatencyMillis;
+ }
+
+ /** Returns how much time in millis spent in the native code. */
+ public int getNativeLatencyMillis() {
+ return mNativeLatencyMillis;
+ }
+
+ /** Returns time used to optimize the document store in millis. */
+ public int getDocumentStoreOptimizeLatencyMillis() {
+ return mNativeDocumentStoreOptimizeLatencyMillis;
+ }
+
+ /** Returns time used to restore the index in millis. */
+ public int getIndexRestorationLatencyMillis() {
+ return mNativeIndexRestorationLatencyMillis;
+ }
+
+ /** Returns number of documents before the optimization. */
+ public int getOriginalDocumentCount() {
+ return mNativeOriginalDocumentCount;
+ }
+
+ /** Returns number of documents deleted during the optimization. */
+ public int getDeletedDocumentCount() {
+ return mNativeDeletedDocumentCount;
+ }
+
+ /** Returns number of documents expired during the optimization. */
+ public int getExpiredDocumentCount() {
+ return mNativeExpiredDocumentCount;
+ }
+
+ /** Returns size of storage in bytes before the optimization. */
+ public long getStorageSizeBeforeBytes() {
+ return mNativeStorageSizeBeforeBytes;
+ }
+
+ /** Returns size of storage in bytes after the optimization. */
+ public long getStorageSizeAfterBytes() {
+ return mNativeStorageSizeAfterBytes;
+ }
+
+ /**
+ * Returns the amount of time in millis since the last optimization ran calculated using wall
+ * clock time.
+ */
+ public long getTimeSinceLastOptimizeMillis() {
+ return mNativeTimeSinceLastOptimizeMillis;
+ }
+
+ /** Builder for {@link RemoveStats}. */
+ public static class Builder {
+ /**
+ * The status code returned by {@link AppSearchResult#getResultCode()} for the call or
+ * internal state.
+ */
+ @AppSearchResult.ResultCode int mStatusCode;
+
+ int mTotalLatencyMillis;
+ int mNativeLatencyMillis;
+ int mNativeDocumentStoreOptimizeLatencyMillis;
+ int mNativeIndexRestorationLatencyMillis;
+ int mNativeOriginalDocumentCount;
+ int mNativeDeletedDocumentCount;
+ int mNativeExpiredDocumentCount;
+ long mNativeStorageSizeBeforeBytes;
+ long mNativeStorageSizeAfterBytes;
+ long mNativeTimeSinceLastOptimizeMillis;
+
+ /** Sets the status code. */
+ @NonNull
+ public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) {
+ mStatusCode = statusCode;
+ return this;
+ }
+
+ /** Sets total latency in millis. */
+ @NonNull
+ public Builder setTotalLatencyMillis(int totalLatencyMillis) {
+ mTotalLatencyMillis = totalLatencyMillis;
+ return this;
+ }
+
+ /** Sets native latency in millis. */
+ @NonNull
+ public Builder setNativeLatencyMillis(int nativeLatencyMillis) {
+ mNativeLatencyMillis = nativeLatencyMillis;
+ return this;
+ }
+
+ /** Sets time used to optimize the document store. */
+ @NonNull
+ public Builder setDocumentStoreOptimizeLatencyMillis(
+ int documentStoreOptimizeLatencyMillis) {
+ mNativeDocumentStoreOptimizeLatencyMillis = documentStoreOptimizeLatencyMillis;
+ return this;
+ }
+
+ /** Sets time used to restore the index. */
+ @NonNull
+ public Builder setIndexRestorationLatencyMillis(int indexRestorationLatencyMillis) {
+ mNativeIndexRestorationLatencyMillis = indexRestorationLatencyMillis;
+ return this;
+ }
+
+ /** Sets number of documents before the optimization. */
+ @NonNull
+ public Builder setOriginalDocumentCount(int originalDocumentCount) {
+ mNativeOriginalDocumentCount = originalDocumentCount;
+ return this;
+ }
+
+ /** Sets number of documents deleted during the optimization. */
+ @NonNull
+ public Builder setDeletedDocumentCount(int deletedDocumentCount) {
+ mNativeDeletedDocumentCount = deletedDocumentCount;
+ return this;
+ }
+
+ /** Sets number of documents expired during the optimization. */
+ @NonNull
+ public Builder setExpiredDocumentCount(int expiredDocumentCount) {
+ mNativeExpiredDocumentCount = expiredDocumentCount;
+ return this;
+ }
+
+ /** Sets Storage size in bytes before optimization. */
+ @NonNull
+ public Builder setStorageSizeBeforeBytes(long storageSizeBeforeBytes) {
+ mNativeStorageSizeBeforeBytes = storageSizeBeforeBytes;
+ return this;
+ }
+
+ /** Sets storage size in bytes after optimization. */
+ @NonNull
+ public Builder setStorageSizeAfterBytes(long storageSizeAfterBytes) {
+ mNativeStorageSizeAfterBytes = storageSizeAfterBytes;
+ return this;
+ }
+
+ /**
+ * Sets the amount the time since the last optimize ran calculated using wall clock time.
+ */
+ @NonNull
+ public Builder setTimeSinceLastOptimizeMillis(long timeSinceLastOptimizeMillis) {
+ mNativeTimeSinceLastOptimizeMillis = timeSinceLastOptimizeMillis;
+ return this;
+ }
+
+ /** Creates a {@link OptimizeStats}. */
+ @NonNull
+ public OptimizeStats build() {
+ return new OptimizeStats(/* builder= */ this);
+ }
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
index 2cbce10..fdf6a00 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
@@ -32,6 +32,7 @@
import com.android.server.appsearch.external.localstorage.AppSearchLogger;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
@@ -145,7 +146,7 @@
}
@Override
- public void logStats(@NonNull InitializeStats stats) throws AppSearchException {
+ public void logStats(@NonNull InitializeStats stats) {
Objects.requireNonNull(stats);
synchronized (mLock) {
if (shouldLogForTypeLocked(CallStats.CALL_TYPE_INITIALIZE)) {
@@ -155,7 +156,7 @@
}
@Override
- public void logStats(@NonNull SearchStats stats) throws AppSearchException {
+ public void logStats(@NonNull SearchStats stats) {
Objects.requireNonNull(stats);
synchronized (mLock) {
if (shouldLogForTypeLocked(CallStats.CALL_TYPE_SEARCH)) {
@@ -165,10 +166,20 @@
}
@Override
- public void logStats(@NonNull RemoveStats stats) throws AppSearchException {
+ public void logStats(@NonNull RemoveStats stats) {
// TODO(b/173532925): Log stats
}
+ @Override
+ public void logStats(@NonNull OptimizeStats stats) {
+ Objects.requireNonNull(stats);
+ synchronized (mLock) {
+ if (shouldLogForTypeLocked(CallStats.CALL_TYPE_OPTIMIZE)) {
+ logStatsImplLocked(stats);
+ }
+ }
+ }
+
/**
* Removes cached UID for package.
*
@@ -326,6 +337,27 @@
stats.getResetStatusCode());
}
+ @GuardedBy("mLock")
+ private void logStatsImplLocked(@NonNull OptimizeStats stats) {
+ mLastPushTimeMillisLocked = SystemClock.elapsedRealtime();
+ ExtraStats extraStats = createExtraStatsLocked(/*packageName=*/ null,
+ CallStats.CALL_TYPE_OPTIMIZE);
+ AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_OPTIMIZE_STATS_REPORTED,
+ extraStats.mSamplingInterval,
+ extraStats.mSkippedSampleCount,
+ stats.getStatusCode(),
+ stats.getTotalLatencyMillis(),
+ stats.getNativeLatencyMillis(),
+ stats.getDocumentStoreOptimizeLatencyMillis(),
+ stats.getIndexRestorationLatencyMillis(),
+ stats.getOriginalDocumentCount(),
+ stats.getDeletedDocumentCount(),
+ stats.getExpiredDocumentCount(),
+ stats.getStorageSizeBeforeBytes(),
+ stats.getStorageSizeAfterBytes(),
+ stats.getTimeSinceLastOptimizeMillis());
+ }
+
/**
* Calculate the hash code as an integer by returning the last four bytes of its MD5.
*
@@ -464,15 +496,19 @@
return mConfig.getCachedSamplingIntervalForBatchCallStats();
case CallStats.CALL_TYPE_PUT_DOCUMENT:
return mConfig.getCachedSamplingIntervalForPutDocumentStats();
- case CallStats.CALL_TYPE_UNKNOWN:
case CallStats.CALL_TYPE_INITIALIZE:
+ return mConfig.getCachedSamplingIntervalForInitializeStats();
+ case CallStats.CALL_TYPE_SEARCH:
+ return mConfig.getCachedSamplingIntervalForSearchStats();
+ case CallStats.CALL_TYPE_GLOBAL_SEARCH:
+ return mConfig.getCachedSamplingIntervalForGlobalSearchStats();
+ case CallStats.CALL_TYPE_OPTIMIZE:
+ return mConfig.getCachedSamplingIntervalForOptimizeStats();
+ case CallStats.CALL_TYPE_UNKNOWN:
case CallStats.CALL_TYPE_SET_SCHEMA:
case CallStats.CALL_TYPE_GET_DOCUMENT:
case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_ID:
- case CallStats.CALL_TYPE_SEARCH:
- case CallStats.CALL_TYPE_OPTIMIZE:
case CallStats.CALL_TYPE_FLUSH:
- case CallStats.CALL_TYPE_GLOBAL_SEARCH:
case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH:
// TODO(b/173532925) Some of them above will have dedicated sampling ratio config
default:
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index 6555107..a81d7d80 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-c7387d9b58726a23a0608a9365fb3a1b57b7b8a1
+Ie04f1ecc033faae8085afcb51eb9e40a298998d5
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 98e963e..86fa06c 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -2052,10 +2052,11 @@
+ " -- package not allowed to start");
return;
}
+ final int callerProcState = mActivityManagerInternal.getUidProcessState(callingUid);
removeLocked(operation, directReceiver, REMOVE_REASON_UNDEFINED);
incrementAlarmCount(a.uid);
setImplLocked(a);
- MetricsHelper.pushAlarmScheduled(a);
+ MetricsHelper.pushAlarmScheduled(a, callerProcState);
}
/**
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
index 4e7311f..4c2f8d1 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
@@ -22,6 +22,7 @@
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY;
+import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.StatsManager;
import android.content.Context;
@@ -93,7 +94,7 @@
}
}
- static void pushAlarmScheduled(Alarm a) {
+ static void pushAlarmScheduled(Alarm a, int callerProcState) {
FrameworkStatsLog.write(
FrameworkStatsLog.ALARM_SCHEDULED,
a.uid,
@@ -103,7 +104,8 @@
a.alarmClock != null,
a.repeatInterval != 0,
reasonToStatsReason(a.mExactAllowReason),
- AlarmManagerService.isRtc(a.type));
+ AlarmManagerService.isRtc(a.type),
+ ActivityManager.processStateAmToProto(callerProcState));
}
static void pushAlarmBatchDelivered(int numAlarms, int wakeups) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 3fa1c12..90baa8e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -116,6 +116,16 @@
@VisibleForTesting
int mVerb;
private boolean mCancelled;
+ /**
+ * True if the previous job on this context successfully finished (ie. called jobFinished or
+ * dequeueWork with no work left).
+ */
+ private boolean mPreviousJobHadSuccessfulFinish;
+ /**
+ * The last time a job on this context didn't finish successfully, in the elapsed realtime
+ * timebase.
+ */
+ private long mLastUnsuccessfulFinishElapsed;
/**
* All the information maintained about the job currently being executed.
@@ -439,7 +449,9 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- assertCallerLocked(cb);
+ if (!assertCallerLocked(cb)) {
+ return null;
+ }
if (mVerb == VERB_STOPPING || mVerb == VERB_FINISHED) {
// This job is either all done, or on its way out. Either way, it
// should not dispatch any more work. We will pick up any remaining
@@ -465,7 +477,11 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- assertCallerLocked(cb);
+ if (!assertCallerLocked(cb)) {
+ // Return true instead of false here so we don't just kick the
+ // Exception-throwing-can down the road to JobParameters.completeWork >:(
+ return true;
+ }
return mRunningJob.completeWorkLocked(workId);
}
} finally {
@@ -554,18 +570,34 @@
return true;
}
- private void assertCallerLocked(JobCallback cb) {
+ /**
+ * Will throw a {@link SecurityException} if the callback is not for the currently running job,
+ * but may decide not to throw an exception if the call from the previous job appears to be an
+ * accident.
+ *
+ * @return true if the callback is for the current job, false otherwise
+ */
+ private boolean assertCallerLocked(JobCallback cb) {
if (!verifyCallerLocked(cb)) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ if (!mPreviousJobHadSuccessfulFinish
+ && (nowElapsed - mLastUnsuccessfulFinishElapsed) < 15_000L) {
+ // Don't punish apps for race conditions
+ return false;
+ }
+ // It's been long enough that the app should really not be calling into JS for the
+ // stopped job.
StringBuilder sb = new StringBuilder(128);
sb.append("Caller no longer running");
if (cb.mStoppedReason != null) {
sb.append(", last stopped ");
- TimeUtils.formatDuration(sElapsedRealtimeClock.millis() - cb.mStoppedTime, sb);
+ TimeUtils.formatDuration(nowElapsed - cb.mStoppedTime, sb);
sb.append(" because: ");
sb.append(cb.mStoppedReason);
}
throw new SecurityException(sb.toString());
}
+ return true;
}
/**
@@ -911,6 +943,11 @@
applyStoppedReasonLocked(reason);
completedJob = mRunningJob;
final int internalStopReason = mParams.getInternalStopReasonCode();
+ mPreviousJobHadSuccessfulFinish =
+ (internalStopReason == JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
+ if (!mPreviousJobHadSuccessfulFinish) {
+ mLastUnsuccessfulFinishElapsed = sElapsedRealtimeClock.millis();
+ }
mJobPackageTracker.noteInactive(completedJob, internalStopReason, reason);
FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED,
completedJob.getSourceUid(), null, completedJob.getBatteryName(),
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 6c001f3..26c83ee 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -112,6 +112,8 @@
srcs: [
"android/os/Temperature.aidl",
"android/os/CoolingDevice.aidl",
+ "android/os/IHintManager.aidl",
+ "android/os/IHintSession.aidl",
"android/os/IThermalEventListener.aidl",
"android/os/IThermalStatusListener.aidl",
"android/os/IThermalService.aidl",
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 871d48b..32ea41b 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -158,7 +158,6 @@
import android.os.IBinder;
import android.os.IDumpstate;
import android.os.IHardwarePropertiesManager;
-import android.os.IHintManager;
import android.os.IPowerManager;
import android.os.IRecoverySystem;
import android.os.ISystemUpdateManager;
@@ -600,10 +599,7 @@
@Override
public PerformanceHintManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
- IBinder hintBinder = ServiceManager.getServiceOrThrow(
- Context.PERFORMANCE_HINT_SERVICE);
- IHintManager hintService = IHintManager.Stub.asInterface(hintBinder);
- return new PerformanceHintManager(hintService);
+ return PerformanceHintManager.create();
}});
registerService(Context.RECOVERY_SERVICE, RecoverySystem.class,
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index f5ab2ab..8398be1 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -3518,22 +3518,22 @@
}
/**
- * Determines whether a String Bluetooth address, such as "00:43:A8:23:10:F0"
+ * Determines whether a String Bluetooth address, such as "F0:43:A8:23:10:00"
* is a RANDOM STATIC address.
*
- * RANDOM STATIC: (addr & 0b11) == 0b11
- * RANDOM RESOLVABLE: (addr & 0b11) == 0b10
- * RANDOM non-RESOLVABLE: (addr & 0b11) == 0b00
+ * RANDOM STATIC: (addr & 0xC0) == 0xC0
+ * RANDOM RESOLVABLE: (addr & 0xC0) == 0x40
+ * RANDOM non-RESOLVABLE: (addr & 0xC0) == 0x00
*
* @param address Bluetooth address as string
- * @return true if the 2 Least Significant Bits of the address equals 0b11.
+ * @return true if the 2 Most Significant Bits of the address equals 0xC0.
*
* @hide
*/
public static boolean isAddressRandomStatic(@NonNull String address) {
requireNonNull(address);
return checkBluetoothAddress(address)
- && (Integer.parseInt(address.split(":")[5], 16) & 0b11) == 0b11;
+ && (Integer.parseInt(address.split(":")[0], 16) & 0xC0) == 0xC0;
}
/** {@hide} */
diff --git a/core/java/android/os/PerformanceHintManager.java b/core/java/android/os/PerformanceHintManager.java
index 6791844..a75b5ef 100644
--- a/core/java/android/os/PerformanceHintManager.java
+++ b/core/java/android/os/PerformanceHintManager.java
@@ -24,24 +24,23 @@
import com.android.internal.util.Preconditions;
import java.io.Closeable;
-import java.util.ArrayList;
/** The PerformanceHintManager allows apps to send performance hint to system. */
@SystemService(Context.PERFORMANCE_HINT_SERVICE)
public final class PerformanceHintManager {
- private static final String TAG = "PerformanceHintManager";
- private final IHintManager mService;
- // HAL preferred update rate
- private final long mPreferredRate;
+ private final long mNativeManagerPtr;
/** @hide */
- public PerformanceHintManager(IHintManager service) {
- mService = service;
- try {
- mPreferredRate = mService.getHintSessionPreferredRate();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ public static PerformanceHintManager create() throws ServiceManager.ServiceNotFoundException {
+ long nativeManagerPtr = nativeAcquireManager();
+ if (nativeManagerPtr == 0) {
+ throw new ServiceManager.ServiceNotFoundException(Context.PERFORMANCE_HINT_SERVICE);
}
+ return new PerformanceHintManager(nativeManagerPtr);
+ }
+
+ private PerformanceHintManager(long nativeManagerPtr) {
+ mNativeManagerPtr = nativeManagerPtr;
}
/**
@@ -57,16 +56,13 @@
*/
@Nullable
public Session createHintSession(@NonNull int[] tids, long initialTargetWorkDurationNanos) {
- try {
- IBinder token = new Binder();
- IHintSession session = mService.createHintSession(token, tids,
- initialTargetWorkDurationNanos);
- if (session == null) return null;
- return new Session(session, sNanoClock, mPreferredRate,
- initialTargetWorkDurationNanos);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ Preconditions.checkNotNull(tids, "tids cannot be null");
+ Preconditions.checkArgumentPositive(initialTargetWorkDurationNanos,
+ "the hint target duration should be positive.");
+ long nativeSessionPtr = nativeCreateSession(mNativeManagerPtr, tids,
+ initialTargetWorkDurationNanos);
+ if (nativeSessionPtr == 0) return null;
+ return new Session(nativeSessionPtr);
}
/**
@@ -75,7 +71,7 @@
* @return the preferred update rate supported by device software.
*/
public long getPreferredUpdateRateNanos() {
- return mPreferredRate;
+ return nativeGetPreferredUpdateRateNanos(mNativeManagerPtr);
}
/**
@@ -101,28 +97,21 @@
* <p>All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.</p>
*/
public static class Session implements Closeable {
- private final IHintSession mSession;
- private final NanoClock mElapsedRealtimeClock;
- // Target duration for choosing update rate
- private long mTargetDurationInNanos;
- // HAL preferred update rate
- private long mPreferredRate;
- // Last update timestamp
- private long mLastUpdateTimeStamp = -1L;
- // Cached samples
- private final ArrayList<Long> mActualDurationNanos;
- private final ArrayList<Long> mTimeStampNanos;
+ private long mNativeSessionPtr;
/** @hide */
- public Session(IHintSession session, NanoClock elapsedRealtimeClock, long preferredRate,
- long durationNanos) {
- mSession = session;
- mElapsedRealtimeClock = elapsedRealtimeClock;
- mTargetDurationInNanos = durationNanos;
- mPreferredRate = preferredRate;
- mActualDurationNanos = new ArrayList<Long>();
- mTimeStampNanos = new ArrayList<Long>();
- mLastUpdateTimeStamp = mElapsedRealtimeClock.nanos();
+ public Session(long nativeSessionPtr) {
+ mNativeSessionPtr = nativeSessionPtr;
+ }
+
+ /** @hide */
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
}
/**
@@ -133,19 +122,7 @@
public void updateTargetWorkDuration(long targetDurationNanos) {
Preconditions.checkArgumentPositive(targetDurationNanos, "the hint target duration"
+ " should be positive.");
- try {
- mSession.updateTargetWorkDuration(targetDurationNanos);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- mTargetDurationInNanos = targetDurationNanos;
- /**
- * Most of the workload is target_duration dependent, so now clear the cached samples
- * as they are most likely obsolete.
- */
- mActualDurationNanos.clear();
- mTimeStampNanos.clear();
- mLastUpdateTimeStamp = mElapsedRealtimeClock.nanos();
+ nativeUpdateTargetWorkDuration(mNativeSessionPtr, targetDurationNanos);
}
/**
@@ -161,38 +138,7 @@
public void reportActualWorkDuration(long actualDurationNanos) {
Preconditions.checkArgumentPositive(actualDurationNanos, "the actual duration should"
+ " be positive.");
- final long now = mElapsedRealtimeClock.nanos();
- mActualDurationNanos.add(actualDurationNanos);
- mTimeStampNanos.add(now);
-
- /**
- * Use current sample to determine the rate limit. We can pick a shorter rate limit
- * if any sample underperformed, however, it could be the lower level system is slow
- * to react. So here we explicitly choose the rate limit with the latest sample.
- */
- long rateLimit =
- actualDurationNanos > mTargetDurationInNanos ? mPreferredRate
- : 10 * mPreferredRate;
-
- if (now - mLastUpdateTimeStamp <= rateLimit) {
- return;
- }
- Preconditions.checkState(mActualDurationNanos.size() == mTimeStampNanos.size());
- final int size = mActualDurationNanos.size();
- long[] actualDurationArray = new long[size];
- long[] timeStampArray = new long[size];
- for (int i = 0; i < size; i++) {
- actualDurationArray[i] = mActualDurationNanos.get(i);
- timeStampArray[i] = mTimeStampNanos.get(i);
- }
- try {
- mSession.reportActualWorkDuration(actualDurationArray, timeStampArray);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- mActualDurationNanos.clear();
- mTimeStampNanos.clear();
- mLastUpdateTimeStamp = now;
+ nativeReportActualWorkDuration(mNativeSessionPtr, actualDurationNanos);
}
/**
@@ -201,26 +147,20 @@
* <p>Once called, you should not call anything else on this object.</p>
*/
public void close() {
- try {
- mSession.close();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ if (mNativeSessionPtr != 0) {
+ nativeCloseSession(mNativeSessionPtr);
+ mNativeSessionPtr = 0;
}
}
}
- /**
- * The interface is to make the FakeClock for testing.
- * @hide
- */
- public interface NanoClock {
- /** Gets the current nanosecond instant of the clock. */
- long nanos();
- }
-
- private static final NanoClock sNanoClock = new NanoClock() {
- public long nanos() {
- return SystemClock.elapsedRealtimeNanos();
- }
- };
+ private static native long nativeAcquireManager();
+ private static native long nativeGetPreferredUpdateRateNanos(long nativeManagerPtr);
+ private static native long nativeCreateSession(long nativeManagerPtr,
+ int[] tids, long initialTargetWorkDurationNanos);
+ private static native void nativeUpdateTargetWorkDuration(long nativeSessionPtr,
+ long targetDurationNanos);
+ private static native void nativeReportActualWorkDuration(long nativeSessionPtr,
+ long actualDurationNanos);
+ private static native void nativeCloseSession(long nativeSessionPtr);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 4e2f37f..8143cf9 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -148,6 +148,8 @@
float width, float height, float vecX, float vecY,
float maxStretchAmountX, float maxStretchAmountY, float childRelativeLeft,
float childRelativeTop, float childRelativeRight, float childRelativeBottom);
+ private static native void nativeSetTrustedOverlay(long transactionObj, long nativeObject,
+ boolean isTrustedOverlay);
private static native boolean nativeClearContentFrameStats(long nativeObject);
private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
@@ -3413,6 +3415,17 @@
return this;
}
+ /**
+ * Sets the trusted overlay state on this SurfaceControl and it is inherited to all the
+ * children. The caller must hold the ACCESS_SURFACE_FLINGER permission.
+ * @hide
+ */
+ public Transaction setTrustedOverlay(SurfaceControl sc, boolean isTrustedOverlay) {
+ checkPreconditions(sc);
+ nativeSetTrustedOverlay(mNativeObject, sc.mNativeObject, isTrustedOverlay);
+ return this;
+ }
+
/**
* Merge the other transaction into this transaction, clearing the
* other transaction as if it had been applied.
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 566f154..8c64474 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -22,6 +22,7 @@
import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.TaskInfo;
+import android.content.pm.ActivityInfo;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.InsetsState;
@@ -78,6 +79,14 @@
public ActivityManager.RunningTaskInfo taskInfo;
/**
+ * The {@link ActivityInfo} of the target activity which to create the starting window.
+ * It can be null if the info is the same as the top in task info.
+ * @hide
+ */
+ @Nullable
+ public ActivityInfo targetActivityInfo;
+
+ /**
* InsetsState of TopFullscreenOpaqueWindow
* @hide
*/
@@ -174,6 +183,7 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(taskInfo, flags);
+ dest.writeTypedObject(targetActivityInfo, flags);
dest.writeInt(startingWindowTypeParameter);
dest.writeTypedObject(topOpaqueWindowInsetsState, flags);
dest.writeTypedObject(topOpaqueWindowLayoutParams, flags);
@@ -185,6 +195,7 @@
void readFromParcel(@NonNull Parcel source) {
taskInfo = source.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+ targetActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
startingWindowTypeParameter = source.readInt();
topOpaqueWindowInsetsState = source.readTypedObject(InsetsState.CREATOR);
topOpaqueWindowLayoutParams = source.readTypedObject(
@@ -198,6 +209,7 @@
@Override
public String toString() {
return "StartingWindowInfo{taskId=" + taskInfo.taskId
+ + " targetActivityInfo=" + targetActivityInfo
+ " displayId=" + taskInfo.displayId
+ " topActivityType=" + taskInfo.topActivityType
+ " preferredStartingWindowType="
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index a8dcbaf..6cbace4 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -241,7 +241,11 @@
private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>();
private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>();
- private final ArraySet<String> mAllowedVendorApexes = new ArraySet<>();
+ // A map from package name of vendor APEXes that can be updated to an installer package name
+ // allowed to install updates for it.
+ private final ArrayMap<String, String> mAllowedVendorApexes = new ArrayMap<>();
+
+ private String mModulesInstallerPackageName;
/**
* Map of system pre-defined, uniquely named actors; keys are namespace,
@@ -412,10 +416,14 @@
return mWhitelistedStagedInstallers;
}
- public Set<String> getAllowedVendorApexes() {
+ public Map<String, String> getAllowedVendorApexes() {
return mAllowedVendorApexes;
}
+ public String getModulesInstallerPackageName() {
+ return mModulesInstallerPackageName;
+ }
+
public ArraySet<String> getAppDataIsolationWhitelistedApps() {
return mAppDataIsolationWhitelistedApps;
}
@@ -1210,12 +1218,21 @@
case "whitelisted-staged-installer": {
if (allowAppConfigs) {
String pkgname = parser.getAttributeValue(null, "package");
+ boolean isModulesInstaller = XmlUtils.readBooleanAttribute(
+ parser, "isModulesInstaller", false);
if (pkgname == null) {
Slog.w(TAG, "<" + name + "> without package in " + permFile
+ " at " + parser.getPositionDescription());
} else {
mWhitelistedStagedInstallers.add(pkgname);
}
+ if (isModulesInstaller) {
+ if (mModulesInstallerPackageName != null) {
+ throw new IllegalStateException(
+ "Multiple modules installers");
+ }
+ mModulesInstallerPackageName = pkgname;
+ }
} else {
logNotAllowedInPartition(name, permFile, parser);
}
@@ -1224,11 +1241,18 @@
case "allowed-vendor-apex": {
if (allowVendorApex) {
String pkgName = parser.getAttributeValue(null, "package");
+ String installerPkgName = parser.getAttributeValue(
+ null, "installerPackage");
if (pkgName == null) {
Slog.w(TAG, "<" + name + "> without package in " + permFile
+ " at " + parser.getPositionDescription());
- } else {
- mAllowedVendorApexes.add(pkgName);
+ }
+ if (installerPkgName == null) {
+ Slog.w(TAG, "<" + name + "> without installerPackage in " + permFile
+ + " at " + parser.getPositionDescription());
+ }
+ if (pkgName != null && installerPkgName != null) {
+ mAllowedVendorApexes.put(pkgName, installerPkgName);
}
} else {
logNotAllowedInPartition(name, permFile, parser);
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 91a19e0..6b9d375 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -146,6 +146,7 @@
"android_os_MemoryFile.cpp",
"android_os_MessageQueue.cpp",
"android_os_Parcel.cpp",
+ "android_os_PerformanceHintManager.cpp",
"android_os_SELinux.cpp",
"android_os_ServiceManager.cpp",
"android_os_SharedMemory.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 406ccde..2fd1e54 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -143,6 +143,7 @@
extern int register_android_os_ServiceManager(JNIEnv *env);
extern int register_android_os_MessageQueue(JNIEnv* env);
extern int register_android_os_Parcel(JNIEnv* env);
+extern int register_android_os_PerformanceHintManager(JNIEnv* env);
extern int register_android_os_SELinux(JNIEnv* env);
extern int register_android_os_VintfObject(JNIEnv *env);
extern int register_android_os_VintfRuntimeInfo(JNIEnv *env);
@@ -1518,6 +1519,7 @@
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_os_Parcel),
+ REG_JNI(register_android_os_PerformanceHintManager),
REG_JNI(register_android_os_HidlMemory),
REG_JNI(register_android_os_HidlSupport),
REG_JNI(register_android_os_HwBinder),
diff --git a/core/jni/android_os_PerformanceHintManager.cpp b/core/jni/android_os_PerformanceHintManager.cpp
new file mode 100644
index 0000000..d05a24f
--- /dev/null
+++ b/core/jni/android_os_PerformanceHintManager.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PerfHint-jni"
+
+#include "jni.h"
+
+#include <dlfcn.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <utils/Log.h>
+#include <vector>
+
+#include "core_jni_helpers.h"
+
+namespace android {
+
+namespace {
+
+struct APerformanceHintManager;
+struct APerformanceHintSession;
+
+typedef APerformanceHintManager* (*APH_getManager)();
+typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
+ size_t, int64_t);
+typedef int64_t (*APH_getPreferredUpdateRateNanos)(APerformanceHintManager* manager);
+typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_closeSession)(APerformanceHintSession* session);
+
+bool gAPerformanceHintBindingInitialized = false;
+APH_getManager gAPH_getManagerFn = nullptr;
+APH_createSession gAPH_createSessionFn = nullptr;
+APH_getPreferredUpdateRateNanos gAPH_getPreferredUpdateRateNanosFn = nullptr;
+APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
+APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
+APH_closeSession gAPH_closeSessionFn = nullptr;
+
+void ensureAPerformanceHintBindingInitialized() {
+ if (gAPerformanceHintBindingInitialized) return;
+
+ void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
+ LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
+
+ gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
+ LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
+ "Failed to find required symbol APerformanceHint_getManager!");
+
+ gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
+ LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
+ "Failed to find required symbol APerformanceHint_createSession!");
+
+ gAPH_getPreferredUpdateRateNanosFn =
+ (APH_getPreferredUpdateRateNanos)dlsym(handle_,
+ "APerformanceHint_getPreferredUpdateRateNanos");
+ LOG_ALWAYS_FATAL_IF(gAPH_getPreferredUpdateRateNanosFn == nullptr,
+ "Failed to find required symbol "
+ "APerformanceHint_getPreferredUpdateRateNanos!");
+
+ gAPH_updateTargetWorkDurationFn =
+ (APH_updateTargetWorkDuration)dlsym(handle_,
+ "APerformanceHint_updateTargetWorkDuration");
+ LOG_ALWAYS_FATAL_IF(gAPH_updateTargetWorkDurationFn == nullptr,
+ "Failed to find required symbol "
+ "APerformanceHint_updateTargetWorkDuration!");
+
+ gAPH_reportActualWorkDurationFn =
+ (APH_reportActualWorkDuration)dlsym(handle_,
+ "APerformanceHint_reportActualWorkDuration");
+ LOG_ALWAYS_FATAL_IF(gAPH_reportActualWorkDurationFn == nullptr,
+ "Failed to find required symbol "
+ "APerformanceHint_reportActualWorkDuration!");
+
+ gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
+ LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
+ "Failed to find required symbol APerformanceHint_closeSession!");
+
+ gAPerformanceHintBindingInitialized = true;
+}
+
+} // namespace
+
+static jlong nativeAcquireManager(JNIEnv* env, jclass clazz) {
+ ensureAPerformanceHintBindingInitialized();
+ return reinterpret_cast<jlong>(gAPH_getManagerFn());
+}
+
+static jlong nativeGetPreferredUpdateRateNanos(JNIEnv* env, jclass clazz, jlong nativeManagerPtr) {
+ ensureAPerformanceHintBindingInitialized();
+ return gAPH_getPreferredUpdateRateNanosFn(
+ reinterpret_cast<APerformanceHintManager*>(nativeManagerPtr));
+}
+
+static jlong nativeCreateSession(JNIEnv* env, jclass clazz, jlong nativeManagerPtr, jintArray tids,
+ jlong initialTargetWorkDurationNanos) {
+ ensureAPerformanceHintBindingInitialized();
+ if (tids == nullptr) return 0;
+ std::vector<int32_t> tidsVector;
+ ScopedIntArrayRO tidsArray(env, tids);
+ for (size_t i = 0; i < tidsArray.size(); ++i) {
+ tidsVector.push_back(static_cast<int32_t>(tidsArray[i]));
+ }
+ return reinterpret_cast<jlong>(
+ gAPH_createSessionFn(reinterpret_cast<APerformanceHintManager*>(nativeManagerPtr),
+ tidsVector.data(), tidsVector.size(),
+ initialTargetWorkDurationNanos));
+}
+
+static void nativeUpdateTargetWorkDuration(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
+ jlong targetDurationNanos) {
+ ensureAPerformanceHintBindingInitialized();
+ gAPH_updateTargetWorkDurationFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
+ targetDurationNanos);
+}
+
+static void nativeReportActualWorkDuration(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
+ jlong actualDurationNanos) {
+ ensureAPerformanceHintBindingInitialized();
+ gAPH_reportActualWorkDurationFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
+ actualDurationNanos);
+}
+
+static void nativeCloseSession(JNIEnv* env, jclass clazz, jlong nativeSessionPtr) {
+ ensureAPerformanceHintBindingInitialized();
+ gAPH_closeSessionFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr));
+}
+
+static const JNINativeMethod gPerformanceHintMethods[] = {
+ {"nativeAcquireManager", "()J", (void*)nativeAcquireManager},
+ {"nativeGetPreferredUpdateRateNanos", "(J)J", (void*)nativeGetPreferredUpdateRateNanos},
+ {"nativeCreateSession", "(J[IJ)J", (void*)nativeCreateSession},
+ {"nativeUpdateTargetWorkDuration", "(JJ)V", (void*)nativeUpdateTargetWorkDuration},
+ {"nativeReportActualWorkDuration", "(JJ)V", (void*)nativeReportActualWorkDuration},
+ {"nativeCloseSession", "(J)V", (void*)nativeCloseSession},
+};
+
+int register_android_os_PerformanceHintManager(JNIEnv* env) {
+ return RegisterMethodsOrDie(env, "android/os/PerformanceHintManager", gPerformanceHintMethods,
+ NELEM(gPerformanceHintMethods));
+}
+
+} // namespace android
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 1695e1a..8d12df22 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -823,6 +823,14 @@
transaction->setShadowRadius(ctrl, shadowRadius);
}
+static void nativeSetTrustedOverlay(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jboolean isTrustedOverlay) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ transaction->setTrustedOverlay(ctrl, isTrustedOverlay);
+}
+
static void nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
jfloat frameRate, jint compatibility, jint changeFrameRateStrategy) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -1984,6 +1992,8 @@
(void*)nativeSetTransformHint },
{"nativeGetTransformHint", "(J)I",
(void*)nativeGetTransformHint },
+ {"nativeSetTrustedOverlay", "(JJZ)V",
+ (void*)nativeSetTrustedOverlay },
// clang-format on
};
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 0970fc5..2d94ffe 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1248,9 +1248,9 @@
<string name="whichImageCaptureApplication" msgid="2737413019463215284">"Зрабіць здымак з дапамогай"</string>
<string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"Зрабіць здымак з дапамогай %1$s"</string>
<string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"Зрабіць здымак"</string>
- <string name="alwaysUse" msgid="3153558199076112903">"Выкарыстоўваць па змаўчанні для гэтага дзеяння."</string>
+ <string name="alwaysUse" msgid="3153558199076112903">"Выкарыстоўваць стандартна для гэтага дзеяння."</string>
<string name="use_a_different_app" msgid="4987790276170972776">"Выкарыстоўваць іншую праграму"</string>
- <string name="clearDefaultHintMsg" msgid="1325866337702524936">"Ачысціць па змаўчанні ў раздзеле \"Налады сістэмы > Прыкладанні > Спампаваныя\"."</string>
+ <string name="clearDefaultHintMsg" msgid="1325866337702524936">"Ачысціць стандартныя налады ў раздзеле \"Налады сістэмы > Праграмы > Спампаваныя\"."</string>
<string name="chooseActivity" msgid="8563390197659779956">"Выберыце дзеянне"</string>
<string name="chooseUsbActivity" msgid="2096269989990986612">"Выберыце прыкладанне для USB-прылады"</string>
<string name="noApplications" msgid="1186909265235544019">"Няма прыкладанняў, якія могуць выконваць гэты працэс."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 141cf4e..8cf968d 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -700,8 +700,8 @@
<string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
<string name="permlab_bindDreamService" msgid="4776175992848982706">"bind to a dream service"</string>
<string name="permdesc_bindDreamService" msgid="9129615743300572973">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
- <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the carrier-provided configuration app"</string>
- <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
+ <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the operator-provided configuration app"</string>
+ <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the operator-provided configuration app. Should never be needed for normal apps."</string>
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"listen for observations on network conditions"</string>
<string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"change input device calibration"</string>
@@ -712,8 +712,8 @@
<string name="permdesc_handoverStatus" msgid="3842269451732571070">"Allows this application to receive information about current Android Beam transfers"</string>
<string name="permlab_removeDrmCertificates" msgid="710576248717404416">"remove DRM certificates"</string>
<string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
- <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to a carrier messaging service"</string>
- <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+ <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to an operator messaging service"</string>
+ <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of an operator messaging service. Should never be needed for normal apps."</string>
<string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to operator services"</string>
<string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to operator services. Should never be needed for normal apps."</string>
<string name="permlab_access_notification_policy" msgid="5524112842876975537">"access Do Not Disturb"</string>
@@ -1655,7 +1655,7 @@
<string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Enter SIM PIN"</string>
<string name="kg_pin_instructions" msgid="7355933174673539021">"Enter PIN"</string>
<string name="kg_password_instructions" msgid="7179782578809398050">"Enter Password"</string>
- <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
<string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Enter desired PIN code"</string>
<string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Confirm desired PIN code"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"Unlocking SIM card…"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 2b1d3e0..b772335 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -700,8 +700,8 @@
<string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
<string name="permlab_bindDreamService" msgid="4776175992848982706">"bind to a dream service"</string>
<string name="permdesc_bindDreamService" msgid="9129615743300572973">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
- <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the carrier-provided configuration app"</string>
- <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
+ <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the operator-provided configuration app"</string>
+ <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the operator-provided configuration app. Should never be needed for normal apps."</string>
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"listen for observations on network conditions"</string>
<string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"change input device calibration"</string>
@@ -712,8 +712,8 @@
<string name="permdesc_handoverStatus" msgid="3842269451732571070">"Allows this application to receive information about current Android Beam transfers"</string>
<string name="permlab_removeDrmCertificates" msgid="710576248717404416">"remove DRM certificates"</string>
<string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
- <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to a carrier messaging service"</string>
- <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+ <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to an operator messaging service"</string>
+ <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of an operator messaging service. Should never be needed for normal apps."</string>
<string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to operator services"</string>
<string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to operator services. Should never be needed for normal apps."</string>
<string name="permlab_access_notification_policy" msgid="5524112842876975537">"access Do Not Disturb"</string>
@@ -1655,7 +1655,7 @@
<string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Enter SIM PIN"</string>
<string name="kg_pin_instructions" msgid="7355933174673539021">"Enter PIN"</string>
<string name="kg_password_instructions" msgid="7179782578809398050">"Enter Password"</string>
- <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
<string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Enter desired PIN code"</string>
<string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Confirm desired PIN code"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"Unlocking SIM card…"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 01d8b39..e1e8187 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -700,8 +700,8 @@
<string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
<string name="permlab_bindDreamService" msgid="4776175992848982706">"bind to a dream service"</string>
<string name="permdesc_bindDreamService" msgid="9129615743300572973">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
- <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the carrier-provided configuration app"</string>
- <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
+ <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the operator-provided configuration app"</string>
+ <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the operator-provided configuration app. Should never be needed for normal apps."</string>
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"listen for observations on network conditions"</string>
<string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"change input device calibration"</string>
@@ -712,8 +712,8 @@
<string name="permdesc_handoverStatus" msgid="3842269451732571070">"Allows this application to receive information about current Android Beam transfers"</string>
<string name="permlab_removeDrmCertificates" msgid="710576248717404416">"remove DRM certificates"</string>
<string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
- <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to a carrier messaging service"</string>
- <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+ <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to an operator messaging service"</string>
+ <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of an operator messaging service. Should never be needed for normal apps."</string>
<string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to operator services"</string>
<string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to operator services. Should never be needed for normal apps."</string>
<string name="permlab_access_notification_policy" msgid="5524112842876975537">"access Do Not Disturb"</string>
@@ -1655,7 +1655,7 @@
<string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Enter SIM PIN"</string>
<string name="kg_pin_instructions" msgid="7355933174673539021">"Enter PIN"</string>
<string name="kg_password_instructions" msgid="7179782578809398050">"Enter Password"</string>
- <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
<string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Enter desired PIN code"</string>
<string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Confirm desired PIN code"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"Unlocking SIM card…"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 3ed0279..892041c 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -700,8 +700,8 @@
<string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
<string name="permlab_bindDreamService" msgid="4776175992848982706">"bind to a dream service"</string>
<string name="permdesc_bindDreamService" msgid="9129615743300572973">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
- <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the carrier-provided configuration app"</string>
- <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
+ <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"invoke the operator-provided configuration app"</string>
+ <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"Allows the holder to invoke the operator-provided configuration app. Should never be needed for normal apps."</string>
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"listen for observations on network conditions"</string>
<string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"change input device calibration"</string>
@@ -712,8 +712,8 @@
<string name="permdesc_handoverStatus" msgid="3842269451732571070">"Allows this application to receive information about current Android Beam transfers"</string>
<string name="permlab_removeDrmCertificates" msgid="710576248717404416">"remove DRM certificates"</string>
<string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
- <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to a carrier messaging service"</string>
- <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+ <string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"bind to an operator messaging service"</string>
+ <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"Allows the holder to bind to the top-level interface of an operator messaging service. Should never be needed for normal apps."</string>
<string name="permlab_bindCarrierServices" msgid="2395596978626237474">"bind to operator services"</string>
<string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Allows the holder to bind to operator services. Should never be needed for normal apps."</string>
<string name="permlab_access_notification_policy" msgid="5524112842876975537">"access Do Not Disturb"</string>
@@ -1655,7 +1655,7 @@
<string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Enter SIM PIN"</string>
<string name="kg_pin_instructions" msgid="7355933174673539021">"Enter PIN"</string>
<string name="kg_password_instructions" msgid="7179782578809398050">"Enter Password"</string>
- <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact carrier for details."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
<string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Enter desired PIN code"</string>
<string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Confirm desired PIN code"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"Unlocking SIM card…"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 8c465f1..9a07025 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -244,7 +244,7 @@
<string name="global_actions" product="default" msgid="6410072189971495460">"Opciones del teléfono"</string>
<string name="global_action_lock" msgid="6949357274257655383">"Bloqueo de pantalla"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"Apagar"</string>
- <string name="global_action_power_options" msgid="1185286119330160073">"Encender o apagar"</string>
+ <string name="global_action_power_options" msgid="1185286119330160073">"Apagar o reiniciar"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Reiniciar"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"Emergencia"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Informe de errores"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 5add36b..e473ab6 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -34,7 +34,7 @@
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"કનેક્શન સમસ્યા અથવા અમાન્ય MMI કોડ."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"ઑપરેશન ફક્ત સ્થિર ડાયલિંગ નંબર્સ પર પ્રતિબંધિત છે."</string>
- <string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"તમે રોમિંગમાં હોવ તે વખતે તમારા ફોન પરથી કૉલ ફોરવર્ડિગ સેટિંગ્સ બદલી શકતાં નથી."</string>
+ <string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"તમે રોમિંગમાં હો તે વખતે તમારા ફોન પરથી કૉલ ફૉરવર્ડિગ સેટિંગ બદલી શકતાં નથી."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"સેવા સક્ષમ હતી."</string>
<string name="serviceEnabledFor" msgid="1463104778656711613">"સેવા આ માટે સક્ષમ હતી:"</string>
<string name="serviceDisabled" msgid="641878791205871379">"સેવા અક્ષમ કરવામાં આવી છે."</string>
@@ -124,7 +124,7 @@
<string name="roamingTextSearching" msgid="5323235489657753486">"સેવા શોધી રહ્યું છે"</string>
<string name="wfcRegErrorTitle" msgid="3193072971584858020">"વાઇ-ફાઇ કૉલિંગ સેટ કરી શકાયું નથી"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="468830943567116703">"વાઇ-ફાઇ પરથી કૉલ કરવા અને સંદેશા મોકલવા માટે પહેલાં તમારા કૅરિઅરને આ સેવા સેટ કરવા માટે કહો. પછી સેટિંગ્સમાંથી વાઇ-ફાઇ કૉલિંગ ફરીથી ચાલુ કરો. (ભૂલ કોડ: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="468830943567116703">"વાઇ-ફાઇ પરથી કૉલ કરવા અને સંદેશા મોકલવા માટે પહેલાં તમારા કૅરિઅરને આ સેવા સેટ કરવા માટે કહો. પછી સેટિંગમાંથી વાઇ-ફાઇ કૉલિંગ ફરીથી ચાલુ કરો. (ભૂલ કોડ: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="4795145070505729156">"તમારા કૅરિઅરમાં વાઇ-ફાઇ કૉલિંગ રજિસ્ટર કરવામાં સમસ્યા આવી: <xliff:g id="CODE">%1$s</xliff:g>"</item>
@@ -401,7 +401,7 @@
<string name="permlab_getPackageSize" msgid="375391550792886641">"ઍપ્લિકેશન સંગ્રહ સ્થાન માપો"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"એપ્લિકેશનને તેનો કોડ, ડેટા અને કેશ કદ પુનઃપ્રાપ્ત કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"સિસ્ટમ સેટિંગમાં ફેરફાર કરો"</string>
- <string name="permdesc_writeSettings" msgid="8293047411196067188">"એપ્લિકેશનને તમારા સિસ્ટમના સેટિંગ્સ ડેટાને સંશોધિત કરવાની મંજૂરી આપે છે. દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારા સિસ્ટમની ગોઠવણીને દૂષિત કરી શકે છે."</string>
+ <string name="permdesc_writeSettings" msgid="8293047411196067188">"ઍપને તમારા સિસ્ટમના સેટિંગ ડેટાને સંશોધિત કરવાની મંજૂરી આપે છે. દુર્ભાવનાપૂર્ણ ઍપ તમારા સિસ્ટમની ગોઠવણીને દૂષિત કરી શકે છે."</string>
<string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"સ્ટાર્ટઅપ પર શરૂ કરો"</string>
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"એપ્લિકેશનને સિસ્ટમ બૂટ થવાનું સમાપ્ત કરી લે કે તરત જ પોતાની જાતે પ્રારંભ થવાની મંજૂરી આપે છે. આનાથી ટેબ્લેટને પ્રારંભ થવામાં વધુ લાંબો સમય લાગી શકે છે અને એપ્લિકેશનને હંમેશા ચાલુ રહીને ટેબ્લેટને એકંદર ધીમું કરવાની મંજૂરી આપી શકે છે."</string>
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"ઍપને સિસ્ટમ બૂટ થવાનું સમાપ્ત કરી લે કે તરત જ પોતાની જાતે પ્રારંભ થવાની મંજૂરી આપે છે. આનાથી તમારા Android TV ડિવાઇસને શરૂ થવામાં વધુ સમય લાગી શકે છે અને ઍપને હંમેશાં ચાલુ રહીને ડિવાઇસને એકંદર ધીમું કરવાની મંજૂરી આપે છે."</string>
@@ -442,8 +442,8 @@
<string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"ઍપ ઉપયોગમાં હોય તે વખતે સ્થાન સેવાઓમાંથી આ ઍપ તમારું અંદાજિત સ્થાન મેળવી શકે છે. ઍપ સ્થાન મેળવી શકે તે માટે તમારા ડિવાઇસમાં સ્થાન સેવાઓ ચાલુ કરેલી હોવી જરૂરી છે."</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"બૅકગ્રાઉન્ડમાં સ્થાન ઍક્સેસ કરો"</string>
<string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"આ ઍપ કોઈપણ સમયે સ્થાનને ઍક્સેસ કરી શકે છે, પછી ભલેને આ ઍપ ઉપયોગમાં ન હોય."</string>
- <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"તમારી ઑડિઓ સેટિંગ્સ બદલો"</string>
- <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"એપ્લિકેશનને વૈશ્વિક ઑડિઓ સેટિંગ્સને સંશોધિત કરવાની મંજૂરી આપે છે, જેમ કે વૉલ્યૂમ અને આઉટપુટ માટે કયા સ્પીકરનો ઉપયોગ કરવો."</string>
+ <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"તમારા ઑડિયો સેટિંગ બદલો"</string>
+ <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"ઍપને વૈશ્વિક ઑડિયો સેટિંગમાં ફેરફાર કરવાની મંજૂરી આપે છે, જેમ કે વૉલ્યૂમ અને આઉટપુટ માટે કયા સ્પીકરનો ઉપયોગ કરવો."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"ઑડિઓ રેકોર્ડ કરવાની"</string>
<string name="permdesc_recordAudio" msgid="5857246765327514062">"આ ઍપ ઉપયોગમાં હોય ત્યારે તે માઇક્રોફોનનો ઉપયોગ કરીને ઑડિયો રેકોર્ડ કરી શકે છે."</string>
<string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"બૅકગ્રાઉન્ડમાં ઑડિયો રેકોર્ડ કરો"</string>
@@ -519,7 +519,7 @@
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"એપ્લિકેશનને ફક્ત તમારા ટેબ્લેટ પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને વાઇ-ફાઇ નેટવર્ક પરના તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string>
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"ઍપને ફક્ત તમારા Android TV ડિવાઇસ પર નહીં, પણ મલ્ટિકાસ્ટ ઍડ્રેસનો ઉપયોગ કરીને વાઇ-ફાઇ નેટવર્ક પરના તમામ ડિવાઇસને મોકલાયેલા પૅકેટ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"એપ્લિકેશનને ફક્ત તમારા ફોન પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને વાઇ-ફાઇ નેટવર્ક પર તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string>
- <string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"બ્લૂટૂથ સેટિંગ્સ ઍક્સેસ કરો"</string>
+ <string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"બ્લૂટૂથ સેટિંગ ઍક્સેસ કરો"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"એપ્લિકેશનને સ્થાનિક બ્લૂટૂથ ટેબ્લેટ ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"ઍપને તમારા Android TV ડિવાઇસ પર બ્લૂટૂથને ગોઠવવાની અને રિમોટ ડિવાઇસ શોધવા અને તેમની સાથે જોડાણ કરવાની મંજૂરી આપે છે."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"એપ્લિકેશનને સ્થાનિક બ્લૂટૂથ ફોન ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string>
@@ -662,10 +662,10 @@
<string-array name="face_error_vendor">
</string-array>
<string name="face_icon_content_description" msgid="465030547475916280">"ચહેરા આઇકન"</string>
- <string name="permlab_readSyncSettings" msgid="6250532864893156277">"સમન્વયન સેટિંગ્સ વાંચો"</string>
- <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ઍપ્લિકેશનને એકાઉન્ટ માટે સમન્વયન સેટિંગ્સને વાંચવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આ એકાઉન્ટ સાથે લોકો ઍપ્લિકેશન સમન્વયિત થઈ છે કે કેમ તે નિર્ધારિત કરી શકે છે."</string>
+ <string name="permlab_readSyncSettings" msgid="6250532864893156277">"સિંક સેટિંગ વાંચો"</string>
+ <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ઍપને એકાઉન્ટ માટે સિંક સેટિંગને વાંચવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આ એકાઉન્ટ સાથે લોકો ઍપ સિંક થઈ છે કે કેમ તે નિર્ધારિત કરી શકે છે."</string>
<string name="permlab_writeSyncSettings" msgid="6583154300780427399">"સમન્વયન ચાલુ અને બંધ ટોગલ કરો"</string>
- <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"એપ્લિકેશનને એકાઉન્ટ માટે સમન્વયન સેટિંગ્સ સંશોધિત કરવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આનો ઉપયોગ એકાઉન્ટ સાથે લોકો એપ્લિકેશનના સમન્વયનને સક્ષમ કરવા માટે થઈ શકે છે."</string>
+ <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"ઍપને એકાઉન્ટ માટે સિંક સેટિંગમાં ફેરફાર કરવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આનો ઉપયોગ એકાઉન્ટ સાથે લોકો ઍપના સિંકને ચાલુ કરવા માટે થઈ શકે છે."</string>
<string name="permlab_readSyncStats" msgid="3747407238320105332">"સમન્વયન આંકડા વાંચો"</string>
<string name="permdesc_readSyncStats" msgid="3867809926567379434">"એપ્લિકેશનને સમન્વયન ઇવેન્ટ્સનો ઇતિહાસ અને કેટલો ડેટા સમન્વયિત થયો છે તે સહિત કોઈ એકાઉન્ટ માટેનાં સમન્વયન આંકડા વાંચવાની મંજૂરી આપે છે."</string>
<string name="permlab_sdcardRead" msgid="5791467020950064920">"તમારા શેર કરેલા સ્ટોરેજના કન્ટેન્ટને વાંચો"</string>
@@ -1210,7 +1210,7 @@
<string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"છબી કૅપ્ચર કરો"</string>
<string name="alwaysUse" msgid="3153558199076112903">"આ ક્રિયા માટે ડિફોલ્ટ તરીકે ઉપયોગમાં લો."</string>
<string name="use_a_different_app" msgid="4987790276170972776">"અલગ એપ્લિકેશનનો ઉપયોગ કરો"</string>
- <string name="clearDefaultHintMsg" msgid="1325866337702524936">"સિસ્ટમ સેટિંગ્સ > ઍપ્લિકેશનો > ડાઉનલોડ કરેલમાં ડિફોલ્ટ સાફ કરો."</string>
+ <string name="clearDefaultHintMsg" msgid="1325866337702524936">"સિસ્ટમ સેટિંગ > ઍપ > ડાઉનલોડ કરેલામાં ડિફૉલ્ટ સાફ કરો."</string>
<string name="chooseActivity" msgid="8563390197659779956">"એક ક્રિયા પસંદ કરો"</string>
<string name="chooseUsbActivity" msgid="2096269989990986612">"USB ઉપકરણ માટે ઍપ્લિકેશન પસંદ કરો"</string>
<string name="noApplications" msgid="1186909265235544019">"કોઈ ઍપ્લિકેશન આ ક્રિયા કરી શકતી નથી."</string>
@@ -1238,8 +1238,8 @@
<string name="launch_warning_original" msgid="3332206576800169626">"<xliff:g id="APP_NAME">%1$s</xliff:g> મૂળરૂપે લોંચ થઈ હતી."</string>
<string name="screen_compat_mode_scale" msgid="8627359598437527726">"સ્કેલ"</string>
<string name="screen_compat_mode_show" msgid="5080361367584709857">"હંમેશા બતાવો"</string>
- <string name="screen_compat_mode_hint" msgid="4032272159093750908">"આને સિસ્ટમ સેટિંગ્સ > ઍપ્લિકેશનો > ડાઉનલોડ કરેલમાં ફરીથી સક્ષમ કરો."</string>
- <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> વર્તમાન પ્રદર્શન કદની સેટિંગનું સમર્થન કરતું નથી અને અનપેક્ષિત રીતે વર્તી શકે છે."</string>
+ <string name="screen_compat_mode_hint" msgid="4032272159093750908">"આને સિસ્ટમ સેટિંગ > ઍપ > ડાઉનલોડ કરેલામાં ફરીથી ચાલુ કરો."</string>
+ <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> વર્તમાન ડિસ્પ્લે કદની સેટિંગને સપોર્ટ કરતું નથી અને અનપેક્ષિત રીતે વર્તી શકે છે."</string>
<string name="unsupported_display_size_show" msgid="980129850974919375">"હંમેશાં બતાવો"</string>
<string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g>ને Android OSના અસંગત વર્ઝન માટે બનાવવામાં આવ્યું હતું અને તે અનપેક્ષિત રીતે કાર્ય કરી શકે છે. ઍપનું અપડેટ કરેલ વર્ઝન ઉપલબ્ધ હોઈ શકે છે."</string>
<string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"હંમેશાં બતાવો"</string>
@@ -1335,7 +1335,7 @@
<string name="sms_short_code_confirm_allow" msgid="920477594325526691">"મોકલો"</string>
<string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"રદ કરો"</string>
<string name="sms_short_code_remember_choice" msgid="1374526438647744862">"મારી પસંદગી યાદ રાખો"</string>
- <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"તમે પછીથી આને સેટિંગ્સ > એપ્લિકેશન્સમાં બદલી શકો છો"</string>
+ <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"તમે પછીથી આને સેટિંગ > ઍપમાં બદલી શકો છો"</string>
<string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"હંમેશા મંજૂરી આપો"</string>
<string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"ક્યારેય મંજૂરી આપશો નહીં"</string>
<string name="sim_removed_title" msgid="5387212933992546283">"સિમ કાર્ડ કાઢી નાખ્યો"</string>
@@ -1502,7 +1502,7 @@
<string name="vpn_lockdown_connected" msgid="2853127976590658469">"હંમેશા-ચાલુ VPN કનેક્ટ થયું"</string>
<string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"હંમેશાં-ચાલુ VPN થી ડિસ્કનેક્ટ થયું"</string>
<string name="vpn_lockdown_error" msgid="4453048646854247947">"હંમેશાં-ચાલુ VPN સાથે કનેક્ટ કરી શકાયું નથી"</string>
- <string name="vpn_lockdown_config" msgid="8331697329868252169">"નેટવર્ક અથવા VPN સેટિંગ્સ બદલો"</string>
+ <string name="vpn_lockdown_config" msgid="8331697329868252169">"નેટવર્ક અથવા VPN સેટિંગ બદલો"</string>
<string name="upload_file" msgid="8651942222301634271">"ફાઇલ પસંદ કરો"</string>
<string name="no_file_chosen" msgid="4146295695162318057">"કોઈ ફાઇલ પસંદ કરેલી નથી"</string>
<string name="reset" msgid="3865826612628171429">"ફરીથી સેટ કરો"</string>
@@ -1616,7 +1616,7 @@
<string name="SetupCallDefault" msgid="5581740063237175247">"કૉલ સ્વીકારીએ?"</string>
<string name="activity_resolver_use_always" msgid="5575222334666843269">"હંમેશાં"</string>
<string name="activity_resolver_use_once" msgid="948462794469672658">"ફક્ત એક વાર"</string>
- <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s કાર્ય પ્રોફાઇલનું સમર્થન કરતું નથી"</string>
+ <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s ઑફિસની પ્રોફાઇલને સપોર્ટ કરતું નથી"</string>
<string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"ટેબ્લેટ"</string>
<string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ફોન"</string>
@@ -2067,7 +2067,7 @@
<string name="popup_window_default_title" msgid="6907717596694826919">"પૉપઅપ વિંડો"</string>
<string name="slice_more_content" msgid="3377367737876888459">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="shortcut_restored_on_lower_version" msgid="9206301954024286063">"આ ઍપનું વર્ઝન ડાઉનગ્રેડ કરવામાં આવ્યું છે અથવા આ શૉર્ટકટ સાથે સુસંગત નથી"</string>
- <string name="shortcut_restore_not_supported" msgid="4763198938588468400">"શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપ બૅકઅપ અને ફરી મેળવવાનું સમર્થન કરતી નથી"</string>
+ <string name="shortcut_restore_not_supported" msgid="4763198938588468400">"શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપ બૅકઅપ અને ફરી મેળવવાને સપોર્ટ કરતી નથી"</string>
<string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"શૉર્ટકટ ફરી મેળવી શકાયો નથી કારણ કે ઍપમાં છે તે સહી મેળ ખાતી નથી"</string>
<string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"શૉર્ટકટ પાછો મેળવી શકાયો નથી"</string>
<string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"શૉર્ટકટને બંધ કરવામાં આવ્યો છે"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 93f2d742..d632e0c 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -434,7 +434,7 @@
<string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"Aplikaciji omogoča dostop do podatkov tipal, ki nadzirajo vaše fizično stanje, med drugim vaš srčni utrip."</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"Branje dogodkov v koledarjih in podrobnosti koledarjev"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v tabličnem računalniku, ter shrani podatke koledarja ali jih deli z drugimi."</string>
- <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v napravi Android TV, ter shrani podatke koledarja ali jih da v skupno rabo z drugimi."</string>
+ <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v napravi Android TV, ter shrani podatke koledarja ali jih deli z drugimi."</string>
<string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v telefonu, ter shrani podatke koledarja ali jih deli z drugimi."</string>
<string name="permlab_writeCalendar" msgid="6422137308329578076">"dodajanje ali spreminjanje dogodkov v koledarju in pošiljanje e-pošte gostom brez vedenja lastnikov"</string>
<string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"Ta aplikacija lahko dodaja, odstranjuje in spreminja dogodke v koledarju, ki so shranjeni v tabličnem računalniku. Ta aplikacija lahko pošilja sporočila, ki bodo morda videti, kot da prihajajo od lastnikov koledarjev, ali spreminja dogodke brez vednosti lastnikov."</string>
@@ -932,7 +932,7 @@
<string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Ali ste pozabili vzorec?"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Odklepanje računa"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"Preveč poskusov vzorca"</string>
- <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Če želite odkleniti telefon, se prijavite z Google Računom."</string>
+ <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Če želite odkleniti telefon, se prijavite z računom Google."</string>
<string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Uporabniško ime (e-pošta)"</string>
<string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"Geslo"</string>
<string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"Prijava"</string>
@@ -1237,8 +1237,8 @@
<string name="whichEditApplicationNamed" msgid="8096494987978521514">"Urejanje z aplikacijo %1$s"</string>
<string name="whichEditApplicationLabel" msgid="1463288652070140285">"Urejanje"</string>
<string name="whichSendApplication" msgid="4143847974460792029">"Deljenje z drugimi"</string>
- <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Skupna raba z aplikacijo %1$s"</string>
- <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Skupna raba"</string>
+ <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Deljenje z aplikacijo %1$s"</string>
+ <string name="whichSendApplicationLabel" msgid="7467813004769188515">"Deljenje"</string>
<string name="whichSendToApplication" msgid="77101541959464018">"Pošiljanje z aplikacijo"</string>
<string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Pošiljanje z aplikacijo %1$s"</string>
<string name="whichSendToApplicationLabel" msgid="3543240188816513303">"Pošiljanje"</string>
@@ -1400,14 +1400,14 @@
<string name="perm_costs_money" msgid="749054595022779685">"to je lahko plačljivo"</string>
<string name="dlg_ok" msgid="5103447663504839312">"V redu"</string>
<string name="usb_charging_notification_title" msgid="1674124518282666955">"Polnjenje naprave prek USB-ja"</string>
- <string name="usb_supplying_notification_title" msgid="5378546632408101811">"Polnjenje akumulatorja v povezani napravi prek USB-ja"</string>
+ <string name="usb_supplying_notification_title" msgid="5378546632408101811">"Polnjenje baterije v povezani napravi prek USB-ja"</string>
<string name="usb_mtp_notification_title" msgid="1065989144124499810">"Vklopljen je prenos datotek prek USB-ja"</string>
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Vklopljen je način PTP prek USB-ja"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Vklopljen je internet prek USB-ja"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Vklopljen je način MIDI prek USB-ja"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Dodatek USB je priključen"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Dotaknite se za več možnosti."</string>
- <string name="usb_power_notification_message" msgid="7284765627437897702">"Polnjenje akumulatorja v povezani napravi. Dotaknite se za več možnosti."</string>
+ <string name="usb_power_notification_message" msgid="7284765627437897702">"Polnjenje baterije v povezani napravi. Dotaknite se za več možnosti."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Zaznana je analogna dodatna zvočna oprema"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Priključena naprava ni združljiva s tem telefonom. Dotaknite se za več informacij."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"Iskanje napak prek USB-ja je povezano"</string>
@@ -1427,8 +1427,8 @@
<string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"Zajemanje poročila o napakah …"</string>
<string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"Želite poslati poročilo o napakah?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"Pošiljanje poročila o napakah …"</string>
- <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"Skrbnik je zahteval poročilo o napakah za pomoč pri odpravljanju napak v tej napravi. Aplikacije in podatki bodo morda dani v skupno rabo."</string>
- <string name="share_remote_bugreport_action" msgid="7630880678785123682">"SKUPNA RABA"</string>
+ <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"Skrbnik je zahteval poročilo o napakah za pomoč pri odpravljanju napak v tej napravi. Aplikacije in podatki bodo morda deljeni."</string>
+ <string name="share_remote_bugreport_action" msgid="7630880678785123682">"DELJENJE"</string>
<string name="decline_remote_bugreport_action" msgid="4040894777519784346">"NE SPREJMEM"</string>
<string name="select_input_method" msgid="3971267998568587025">"Izberite način vnosa"</string>
<string name="show_ime" msgid="6406112007347443383">"Ohrani na zaslonu, dokler je aktivna fizična tipkovnica"</string>
@@ -1616,7 +1616,7 @@
<string name="action_menu_overflow_description" msgid="4579536843510088170">"Več možnosti"</string>
<string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="8490227947584914460">"Notranja shramba v skupni rabi"</string>
+ <string name="storage_internal" msgid="8490227947584914460">"Notranja deljena shramba"</string>
<string name="storage_sd_card" msgid="3404740277075331881">"Kartica SD"</string>
<string name="storage_sd_card_label" msgid="7526153141147470509">"Kartica SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="448030813201444573">"Pogon USB"</string>
@@ -1709,7 +1709,7 @@
<string name="kg_invalid_puk" msgid="4809502818518963344">"Vnovič vnesite pravilno kodo PUK. Večkratni poskusi bodo trajno onemogočili kartico SIM."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"Kodi PIN se ne ujemata"</string>
<string name="kg_login_too_many_attempts" msgid="699292728290654121">"Preveč poskusov vzorca"</string>
- <string name="kg_login_instructions" msgid="3619844310339066827">"Če želite odkleniti napravo, se prijavite z Google Računom."</string>
+ <string name="kg_login_instructions" msgid="3619844310339066827">"Če želite odkleniti napravo, se prijavite z računom Google."</string>
<string name="kg_login_username_hint" msgid="1765453775467133251">"Uporabniško ime (e-pošta)"</string>
<string name="kg_login_password_hint" msgid="3330530727273164402">"Geslo"</string>
<string name="kg_login_submit_button" msgid="893611277617096870">"Prijava"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 25e2820..239c9f8 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1197,7 +1197,7 @@
<string name="whichEditApplicationNamed" msgid="8096494987978521514">"Redakto me %1$s"</string>
<string name="whichEditApplicationLabel" msgid="1463288652070140285">"Redakto"</string>
<string name="whichSendApplication" msgid="4143847974460792029">"Ndaj"</string>
- <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Shpërnda publikisht me %1$s"</string>
+ <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Shpërndaj me %1$s"</string>
<string name="whichSendApplicationLabel" msgid="7467813004769188515">"Ndaj"</string>
<string name="whichSendToApplication" msgid="77101541959464018">"Dërgo me"</string>
<string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Dërgo me %1$s"</string>
@@ -1565,8 +1565,8 @@
<string name="keyboardview_keycode_enter" msgid="168054869339091055">"Enter"</string>
<string name="activitychooserview_choose_application" msgid="3500574466367891463">"Zgjidh një aplikacion"</string>
<string name="activitychooserview_choose_application_error" msgid="6937782107559241734">"Nuk mundi ta hapte <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
- <string name="shareactionprovider_share_with" msgid="2753089758467748982">"Shpërnda publikisht me"</string>
- <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"Shpërnda me <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="shareactionprovider_share_with" msgid="2753089758467748982">"Shpërndaj me"</string>
+ <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"Shpërndaj me <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="content_description_sliding_handle" msgid="982510275422590757">"Dorezë me rrëshqitje. Preke dhe mbaje të shtypur."</string>
<string name="description_target_unlock_tablet" msgid="7431571180065859551">"Rrëshqit për të shkyçur."</string>
<string name="action_bar_home_description" msgid="1501655419158631974">"Orientohu për në shtëpi"</string>
@@ -1610,7 +1610,7 @@
<string name="sha1_fingerprint" msgid="2339915142825390774">"Gjurma e gishtit SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="3917045206812726099">"Shikoji të gjitha"</string>
<string name="activity_chooser_view_dialog_title_default" msgid="8880731437191978314">"Zgjidh aktivitetin"</string>
- <string name="share_action_provider_share_with" msgid="1904096863622941880">"Shpërnda publikisht me"</string>
+ <string name="share_action_provider_share_with" msgid="1904096863622941880">"Shpërndaj me"</string>
<string name="sending" msgid="206925243621664438">"Po dërgon…"</string>
<string name="launchBrowserDefault" msgid="6328349989932924119">"Të hapet shfletuesi?"</string>
<string name="SetupCallDefault" msgid="5581740063237175247">"Dëshiron ta pranosh telefonatën?"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index cb0b420..940ee56 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -572,7 +572,7 @@
<string name="biometric_error_user_canceled" msgid="6732303949695293730">"Autentiseringen avbröts"</string>
<string name="biometric_not_recognized" msgid="5106687642694635888">"Identifierades inte"</string>
<string name="biometric_error_canceled" msgid="8266582404844179778">"Autentiseringen avbröts"</string>
- <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Pinkod, grafiskt lösenord eller lösenord har inte angetts"</string>
+ <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Pinkod, mönster eller lösenord har inte angetts"</string>
<string name="biometric_error_generic" msgid="6784371929985434439">"Ett fel uppstod vid autentiseringen"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Använd skärmlåset"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Fortsätt med hjälp av ditt skärmlås"</string>
@@ -881,7 +881,7 @@
<string name="lockscreen_screen_locked" msgid="7364905540516041817">"Skärmen har låsts."</string>
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Tryck på Menu för att låsa upp eller ringa nödsamtal."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Tryck på Menu för att låsa upp."</string>
- <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Rita grafiskt lösenord för att låsa upp"</string>
+ <string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Rita mönster för att låsa upp"</string>
<string name="lockscreen_emergency_call" msgid="7549683825868928636">"Nödsamtal"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Tillbaka till samtal"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Korrekt!"</string>
@@ -925,7 +925,7 @@
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"Försök igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Glömt ditt grafiska lösenord?"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Lås upp konto"</string>
- <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"För många försök med grafiskt lösenord"</string>
+ <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"För många försök med mönster"</string>
<string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Logga in med ditt Google-konto om du vill låsa upp."</string>
<string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Användarnamn (e-post)"</string>
<string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"Lösenord"</string>
@@ -936,12 +936,12 @@
<string name="lockscreen_unlock_label" msgid="4648257878373307582">"Lås upp"</string>
<string name="lockscreen_sound_on_label" msgid="1660281470535492430">"Ljud på"</string>
<string name="lockscreen_sound_off_label" msgid="2331496559245450053">"Ljud av"</string>
- <string name="lockscreen_access_pattern_start" msgid="3778502525702613399">"Skriver grafiskt lösenord"</string>
- <string name="lockscreen_access_pattern_cleared" msgid="7493849102641167049">"Grafiskt lösenord har tagits bort"</string>
+ <string name="lockscreen_access_pattern_start" msgid="3778502525702613399">"Ritar mönster"</string>
+ <string name="lockscreen_access_pattern_cleared" msgid="7493849102641167049">"Mönster har tagits bort"</string>
<string name="lockscreen_access_pattern_cell_added" msgid="6746676335293144163">"En cell har lagts till"</string>
<string name="lockscreen_access_pattern_cell_added_verbose" msgid="2931364927622563465">"Cell <xliff:g id="CELL_INDEX">%1$s</xliff:g> har lagts till"</string>
- <string name="lockscreen_access_pattern_detected" msgid="3931150554035194012">"Grafiskt lösenord har slutförts"</string>
- <string name="lockscreen_access_pattern_area" msgid="1288780416685002841">"Fält för grafiskt lösenord."</string>
+ <string name="lockscreen_access_pattern_detected" msgid="3931150554035194012">"Mönster har slutförts"</string>
+ <string name="lockscreen_access_pattern_area" msgid="1288780416685002841">"Fält för mönster."</string>
<string name="keyguard_accessibility_widget_changed" msgid="7298011259508200234">"%1$s. Widget %2$d av %3$d."</string>
<string name="keyguard_accessibility_add_widget" msgid="8245795023551343672">"Lägg till en widget."</string>
<string name="keyguard_accessibility_widget_empty_slot" msgid="544239307077644480">"Tom"</string>
@@ -957,13 +957,13 @@
<string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"Widgeten <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> har tagits bort."</string>
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Expandera upplåsningsytan."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Lås upp genom att dra."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Lås upp med grafiskt lösenord."</string>
+ <string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Lås upp med mönster."</string>
<string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Ansiktslås."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Lås upp med PIN-kod."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Lås upp med SIM-kortets pinkod."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Lås upp med SIM-kortets PUK-kod."</string>
<string name="keyguard_accessibility_password_unlock" msgid="6130186108581153265">"Lås upp med lösenord."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="1419570880512350689">"Fält för grafiskt lösenord."</string>
+ <string name="keyguard_accessibility_pattern_area" msgid="1419570880512350689">"Fält för mönster."</string>
<string name="keyguard_accessibility_slide_area" msgid="4331399051142520176">"Fält med dragreglage."</string>
<string name="password_keyboard_label_symbol_key" msgid="2716255580853511949">"?123"</string>
<string name="password_keyboard_label_alpha_key" msgid="5294837425652726684">"ABC"</string>
@@ -1644,7 +1644,7 @@
<string name="display_manager_overlay_display_title" msgid="1480158037150469170">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="2810034719482834679">", säker"</string>
<string name="kg_forgot_pattern_button_text" msgid="406145459223122537">"Har du glömt ditt grafiska lösenord?"</string>
- <string name="kg_wrong_pattern" msgid="1342812634464179931">"Fel grafiskt lösenord"</string>
+ <string name="kg_wrong_pattern" msgid="1342812634464179931">"Fel mönster"</string>
<string name="kg_wrong_password" msgid="2384677900494439426">"Fel lösenord"</string>
<string name="kg_wrong_pin" msgid="3680925703673166482">"Fel PIN-kod"</string>
<plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
@@ -1664,7 +1664,7 @@
<string name="kg_invalid_sim_puk_hint" msgid="2539364558870734339">"PUK-koden ska vara åtta siffror."</string>
<string name="kg_invalid_puk" msgid="4809502818518963344">"Ange rätt PUK-kod igen. Om försöken upprepas inaktiveras SIM-kortet permanent."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"PIN-koderna stämmer inte överens"</string>
- <string name="kg_login_too_many_attempts" msgid="699292728290654121">"För många försök med grafiskt lösenord"</string>
+ <string name="kg_login_too_many_attempts" msgid="699292728290654121">"För många försök med mönster"</string>
<string name="kg_login_instructions" msgid="3619844310339066827">"Logga in med ditt Google-konto om du vill låsa upp."</string>
<string name="kg_login_username_hint" msgid="1765453775467133251">"Användarnamn (e-post)"</string>
<string name="kg_login_password_hint" msgid="3330530727273164402">"Lösenord"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index d68c088..89a7749 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/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/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java b/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java
index d51004c..07e4333 100644
--- a/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/AppSearchSessionUnitTest.java
@@ -16,6 +16,8 @@
package android.app.appsearch;
+import static android.app.appsearch.SearchSpec.TERM_MATCH_PREFIX;
+
import static com.google.common.truth.Truth.assertThat;
import static org.testng.Assert.expectThrows;
@@ -30,6 +32,8 @@
import org.junit.Before;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -100,4 +104,127 @@
.isEqualTo(AppSearchResult.RESULT_INTERNAL_ERROR);
assertThat(appSearchException.getMessage()).startsWith("NullPointerException");
}
+
+ @Test
+ public void testGetEmptyNextPage() throws Exception {
+ // Set the schema.
+ CompletableFuture<AppSearchResult<SetSchemaResponse>> schemaFuture =
+ new CompletableFuture<>();
+ mSearchSession.setSchema(
+ new SetSchemaRequest.Builder()
+ .addSchemas(new AppSearchSchema.Builder("schema1").build())
+ .setForceOverride(true).build(),
+ mExecutor, mExecutor, schemaFuture::complete);
+ schemaFuture.get().getResultValue();
+
+ // Create a document and index it.
+ GenericDocument document1 = new GenericDocument.Builder<>("namespace", "id1",
+ "schema1").build();
+ CompletableFuture<AppSearchBatchResult<String, Void>> putDocumentsFuture =
+ new CompletableFuture<>();
+ mSearchSession.put(
+ new PutDocumentsRequest.Builder().addGenericDocuments(document1).build(),
+ mExecutor, new BatchResultCallback<String, Void>() {
+ @Override
+ public void onResult(AppSearchBatchResult<String, Void> result) {
+ putDocumentsFuture.complete(result);
+ }
+
+ @Override
+ public void onSystemError(Throwable throwable) {
+ putDocumentsFuture.completeExceptionally(throwable);
+ }
+ });
+ putDocumentsFuture.get();
+
+ // Search and get the first page.
+ SearchSpec searchSpec = new SearchSpec.Builder()
+ .setTermMatch(TERM_MATCH_PREFIX)
+ .setResultCountPerPage(1)
+ .build();
+ SearchResults searchResults = mSearchSession.search("", searchSpec);
+
+ CompletableFuture<AppSearchResult<List<SearchResult>>> getNextPageFuture =
+ new CompletableFuture<>();
+ searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+ List<SearchResult> results = getNextPageFuture.get().getResultValue();
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).getGenericDocument()).isEqualTo(document1);
+
+ // We get all documents, and it shouldn't fail if we keep calling getNextPage().
+ getNextPageFuture = new CompletableFuture<>();
+ searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+ results = getNextPageFuture.get().getResultValue();
+ assertThat(results).isEmpty();
+ }
+
+ @Test
+ public void testGetEmptyNextPage_multiPages() throws Exception {
+ // Set the schema.
+ CompletableFuture<AppSearchResult<SetSchemaResponse>> schemaFuture =
+ new CompletableFuture<>();
+ mSearchSession.setSchema(
+ new SetSchemaRequest.Builder()
+ .addSchemas(new AppSearchSchema.Builder("schema1").build())
+ .setForceOverride(true).build(),
+ mExecutor, mExecutor, schemaFuture::complete);
+ schemaFuture.get().getResultValue();
+
+ // Create a document and insert 3 package1 documents
+ GenericDocument document1 = new GenericDocument.Builder<>("namespace", "id1",
+ "schema1").build();
+ GenericDocument document2 = new GenericDocument.Builder<>("namespace", "id2",
+ "schema1").build();
+ GenericDocument document3 = new GenericDocument.Builder<>("namespace", "id3",
+ "schema1").build();
+ CompletableFuture<AppSearchBatchResult<String, Void>> putDocumentsFuture =
+ new CompletableFuture<>();
+ mSearchSession.put(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocuments(document1, document2, document3).build(),
+ mExecutor, new BatchResultCallback<String, Void>() {
+ @Override
+ public void onResult(AppSearchBatchResult<String, Void> result) {
+ putDocumentsFuture.complete(result);
+ }
+
+ @Override
+ public void onSystemError(Throwable throwable) {
+ putDocumentsFuture.completeExceptionally(throwable);
+ }
+ });
+ putDocumentsFuture.get();
+
+ // Search for only 2 result per page
+ SearchSpec searchSpec = new SearchSpec.Builder()
+ .setTermMatch(TERM_MATCH_PREFIX)
+ .setResultCountPerPage(2)
+ .build();
+ SearchResults searchResults = mSearchSession.search("", searchSpec);
+
+ // Get the first page, it contains 2 results.
+ List<GenericDocument> outDocs = new ArrayList<>();
+ CompletableFuture<AppSearchResult<List<SearchResult>>> getNextPageFuture =
+ new CompletableFuture<>();
+ searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+ List<SearchResult> results = getNextPageFuture.get().getResultValue();
+ assertThat(results).hasSize(2);
+ outDocs.add(results.get(0).getGenericDocument());
+ outDocs.add(results.get(1).getGenericDocument());
+
+ // Get the second page, it contains only 1 result.
+ getNextPageFuture = new CompletableFuture<>();
+ searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+ results = getNextPageFuture.get().getResultValue();
+ assertThat(results).hasSize(1);
+ outDocs.add(results.get(0).getGenericDocument());
+
+ assertThat(outDocs).containsExactly(document1, document2, document3);
+
+ // We get all documents, and it shouldn't fail if we keep calling getNextPage().
+ getNextPageFuture = new CompletableFuture<>();
+ searchResults.getNextPage(mExecutor, getNextPageFuture::complete);
+ results = getNextPageFuture.get().getResultValue();
+ assertThat(results).isEmpty();
+ }
}
diff --git a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
index 7dea82d..69eb13f 100644
--- a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
+++ b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
@@ -22,12 +22,6 @@
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNotNull;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
import android.os.PerformanceHintManager.Session;
@@ -120,92 +114,9 @@
}
@Test
- public void testRateLimitWithDurationFastEnough() throws Exception {
- FakeClock fakeClock = new FakeClock();
- Session s = new Session(mIHintSessionMock, fakeClock, RATE_1000, TARGET_166);
-
- reset(mIHintSessionMock);
- fakeClock.setNow(0);
- s.updateTargetWorkDuration(TARGET_166);
-
- s.reportActualWorkDuration(TARGET_166 - 1);
- s.reportActualWorkDuration(TARGET_166);
- // we should not see update as the rate should be 10X for over-perform case.
- verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
- fakeClock.incrementClock(10 * RATE_1000);
- s.reportActualWorkDuration(TARGET_166);
- verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
- fakeClock.incrementClock(1);
- s.reportActualWorkDuration(TARGET_166);
- // we should see update after rate limit
- verify(mIHintSessionMock, times(1)).reportActualWorkDuration(
- eq(new long[] {TARGET_166 - 1, TARGET_166, TARGET_166, TARGET_166}),
- eq(new long[] {0, 0, 10 * RATE_1000, 10 * RATE_1000 + 1}));
-
- reset(mIHintSessionMock);
- s.reportActualWorkDuration(TARGET_166);
- s.reportActualWorkDuration(TARGET_166 - 1);
- s.reportActualWorkDuration(TARGET_166 - 2);
- // we should not see update as the rate should be 10X for over-perform case.
- verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
- fakeClock.incrementClock(10 * RATE_1000 + 1);
- s.reportActualWorkDuration(TARGET_166);
- s.reportActualWorkDuration(TARGET_166 - 1);
- // we should see update now
- verify(mIHintSessionMock, times(1)).reportActualWorkDuration(
- eq(new long[] {TARGET_166, TARGET_166 - 1, TARGET_166 - 2, TARGET_166}),
- eq(new long[] {10 * RATE_1000 + 1, 10 * RATE_1000 + 1, 10 * RATE_1000 + 1,
- (10 * RATE_1000 + 1) * 2}));
- }
-
- @Test
- public void testRateLimitWithDurationTooSlow() throws Exception {
- FakeClock fakeClock = new FakeClock();
- Session s = new Session(mIHintSessionMock, fakeClock, RATE_1000, TARGET_166);
-
- reset(mIHintSessionMock);
- fakeClock.setNow(0);
- s.updateTargetWorkDuration(TARGET_166);
-
- verify(mIHintSessionMock, times(1)).updateTargetWorkDuration(eq(TARGET_166));
- // shouldn't update before rate limit
- s.reportActualWorkDuration(TARGET_166 + 1);
- verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
-
- // shouldn't update when the time is exactly at rate limit
- fakeClock.incrementClock(RATE_1000);
- s.reportActualWorkDuration(TARGET_166 + 1);
- verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
-
- // should be ready for sending hint
- fakeClock.incrementClock(1);
- s.reportActualWorkDuration(TARGET_166 + 1);
- verify(mIHintSessionMock, times(1)).reportActualWorkDuration(
- eq(new long[] {TARGET_166 + 1, TARGET_166 + 1, TARGET_166 + 1}),
- eq(new long[] {0 , RATE_1000, RATE_1000 + 1}));
- }
-
- @Test
public void testCloseHintSession() {
Session s = createSession();
assumeNotNull(s);
s.close();
}
-
- private static class FakeClock implements PerformanceHintManager.NanoClock {
- private long mCurrentTime = 0L;
-
- @Override
- public long nanos() {
- return mCurrentTime;
- }
-
- public void setNow(long nanos) {
- mCurrentTime = nanos;
- }
-
- public void incrementClock(long nanos) {
- mCurrentTime += nanos;
- }
- }
}
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index fe04f0d..c3b1cd74 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -28,7 +28,6 @@
import android.hardware.display.DisplayManager;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
-import android.os.PerformanceHintManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
@@ -856,36 +855,6 @@
callback.onPictureCaptured(picture);
}
- /** called by native */
- static PerformanceHintManager.Session createHintSession(int[] tids) {
- PerformanceHintManager performanceHintManager =
- ProcessInitializer.sInstance.getHintManager();
- if (performanceHintManager == null) {
- return null;
- }
- // Native code will always set a target duration before reporting actual durations.
- // So this is just a placeholder value that's never used.
- long targetDurationNanos = 16666667;
- return performanceHintManager.createHintSession(tids, targetDurationNanos);
- }
-
- /** called by native */
- static void updateTargetWorkDuration(PerformanceHintManager.Session session,
- long targetDurationNanos) {
- session.updateTargetWorkDuration(targetDurationNanos);
- }
-
- /** called by native */
- static void reportActualWorkDuration(PerformanceHintManager.Session session,
- long actualDurationNanos) {
- session.reportActualWorkDuration(actualDurationNanos);
- }
-
- /** called by native */
- static void closeHintSession(PerformanceHintManager.Session session) {
- session.close();
- }
-
/**
* Interface used to receive callbacks when Webview requests a surface control.
*
@@ -1152,7 +1121,6 @@
private boolean mIsolated = false;
private Context mContext;
private String mPackageName;
- private PerformanceHintManager mPerformanceHintManager;
private IGraphicsStats mGraphicsStatsService;
private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
@Override
@@ -1164,10 +1132,6 @@
private ProcessInitializer() {
}
- synchronized PerformanceHintManager getHintManager() {
- return mPerformanceHintManager;
- }
-
synchronized void setPackageName(String name) {
if (mInitialized) return;
mPackageName = name;
@@ -1218,10 +1182,6 @@
initDisplayInfo();
- // HintManager and HintSession are designed to be accessible from isoalted processes
- // so not checking for isolated process here.
- initHintSession();
-
nSetIsHighEndGfx(ActivityManager.isHighEndGfx());
// Defensively clear out the context in case we were passed a context that can leak
// if we live longer than it, e.g. an activity context.
@@ -1265,11 +1225,6 @@
mDisplayInitialized = true;
}
- private void initHintSession() {
- if (mContext == null) return;
- mPerformanceHintManager = mContext.getSystemService(PerformanceHintManager.class);
- }
-
private void rotateBuffer() {
nRotateProcessStatsBuffer();
requestBuffer();
diff --git a/libs/WindowManager/Shell/res/color/one_handed_tutorial_background_color.xml b/libs/WindowManager/Shell/res/color/one_handed_tutorial_background_color.xml
new file mode 100644
index 0000000..4f56e0f
--- /dev/null
+++ b/libs/WindowManager/Shell/res/color/one_handed_tutorial_background_color.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:color="?androidprv:attr/colorSurfaceVariant"/>
+</selector>
diff --git a/libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png b/libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png
deleted file mode 100644
index 6c1f1cf..0000000
--- a/libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png
+++ /dev/null
Binary files differ
diff --git a/libs/WindowManager/Shell/res/drawable/one_handed_tutorial_icon.xml b/libs/WindowManager/Shell/res/drawable/one_handed_tutorial_icon.xml
new file mode 100644
index 0000000..b32f34e
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/one_handed_tutorial_icon.xml
@@ -0,0 +1,14 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32dp"
+ android:height="60dp"
+ android:viewportWidth="32"
+ android:viewportHeight="60">
+ <path
+ android:pathData="M1.9703,30.5041C1.9703,28.295 3.7612,26.5042 5.9703,26.5042H25.5551C27.7642,26.5042 29.5551,28.295 29.5551,30.5042V54.0296C29.5551,56.2387 27.7642,58.0296 25.5551,58.0296H5.9703C3.7612,58.0296 1.9703,56.2387 1.9703,54.0296V30.5041Z"
+ android:fillColor="#000000"
+ android:fillAlpha="0.16"/>
+ <path
+ android:pathData="M25.5254,2H6C3.7909,2 2,3.7909 2,6V54C2,56.2091 3.7909,58 6,58H25.5254C27.7346,58 29.5254,56.2091 29.5254,54V6C29.5254,3.7909 27.7346,2 25.5254,2ZM6,0C2.6863,0 0,2.6863 0,6V54C0,57.3137 2.6863,60 6,60H25.5254C28.8391,60 31.5254,57.3137 31.5254,54V6C31.5254,2.6863 28.8391,0 25.5254,0H6ZM12.2034,47.2336L12.8307,47.861L15.3178,45.3783V52.1277H16.2076V45.3783L18.6903,47.8654L19.322,47.2336L15.7627,43.6743L12.2034,47.2336ZM19.7034,55.0742H11.822V56.552H19.7034V55.0742Z"
+ android:fillColor="#000000"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml b/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
index 0190aad..d29ed8b 100644
--- a/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
+++ b/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml
@@ -31,7 +31,7 @@
android:layout_marginTop="6dp"
android:layout_marginBottom="0dp"
android:gravity="center_horizontal"
- android:src="@drawable/one_handed_tutorial"
+ android:src="@drawable/one_handed_tutorial_icon"
android:scaleType="centerInside" />
<TextView
@@ -45,7 +45,6 @@
android:fontFamily="google-sans-medium"
android:text="@string/one_handed_tutorial_title"
android:textSize="16sp"
- android:textStyle="bold"
android:textColor="@android:color/white"/>
<TextView
@@ -54,8 +53,8 @@
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginBottom="0dp"
- android:layout_marginStart="46dp"
- android:layout_marginEnd="46dp"
+ android:layout_marginStart="60dp"
+ android:layout_marginEnd="60dp"
android:gravity="center_horizontal"
android:fontFamily="roboto-regular"
android:text="@string/one_handed_tutorial_description"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 92e455c..c0df06f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -45,6 +45,7 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
@@ -205,6 +206,7 @@
* between bubble activities without needing both to be alive at the same time.
*/
private SurfaceView mAnimatingOutSurfaceView;
+ private boolean mAnimatingOutSurfaceReady;
/** Container for the animating-out SurfaceView. */
private FrameLayout mAnimatingOutSurfaceContainer;
@@ -811,6 +813,20 @@
mAnimatingOutSurfaceView.setZOrderOnTop(true);
mAnimatingOutSurfaceView.setCornerRadius(mCornerRadius);
mAnimatingOutSurfaceView.setLayoutParams(new ViewGroup.LayoutParams(0, 0));
+ mAnimatingOutSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {}
+
+ @Override
+ public void surfaceCreated(SurfaceHolder surfaceHolder) {
+ mAnimatingOutSurfaceReady = true;
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
+ mAnimatingOutSurfaceReady = false;
+ }
+ });
mAnimatingOutSurfaceContainer.addView(mAnimatingOutSurfaceView);
mAnimatingOutSurfaceContainer.setPadding(
@@ -2653,7 +2669,7 @@
return;
}
- if (!mIsExpanded) {
+ if (!mIsExpanded || !mAnimatingOutSurfaceReady) {
onComplete.accept(false);
return;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
index 481b948..3ccb9e7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
@@ -20,7 +20,6 @@
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.util.Log;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.window.DisplayAreaAppearedInfo;
@@ -30,7 +29,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import androidx.core.content.ContextCompat;
import com.android.internal.annotations.GuardedBy;
import com.android.wm.shell.R;
@@ -48,14 +46,17 @@
public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer
implements OneHandedTransitionCallback {
private static final String TAG = "OneHandedBackgroundPanelOrganizer";
+ private static final int THEME_COLOR_OFFSET = 10;
+ private final Context mContext;
private final Object mLock = new Object();
private final SurfaceSession mSurfaceSession = new SurfaceSession();
- private final float[] mDefaultColor;
private final Executor mMainExecutor;
private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
mSurfaceControlTransactionFactory;
+ private float[] mDefaultColor;
+
/**
* The background to distinguish the boundary of translated windows and empty region when
* one handed mode triggered.
@@ -88,15 +89,14 @@
public OneHandedBackgroundPanelOrganizer(Context context, DisplayLayout displayLayout,
Executor executor) {
super(executor);
+ mContext = context;
// Ensure the mBkgBounds is portrait, due to OHM only support on portrait
if (displayLayout.height() > displayLayout.width()) {
mBkgBounds = new Rect(0, 0, displayLayout.width(), displayLayout.height());
} else {
mBkgBounds = new Rect(0, 0, displayLayout.height(), displayLayout.width());
}
- final int defaultColor = ContextCompat.getColor(context, R.color.GM2_grey_800);
- mDefaultColor = new float[]{Color.red(defaultColor) / 255.0f,
- Color.green(defaultColor) / 255.0f, Color.blue(defaultColor) / 255.0f};
+ updateThemeColors();
mMainExecutor = executor;
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
}
@@ -170,7 +170,6 @@
}
if (getBackgroundSurface() == null) {
- Log.w(TAG, "mBackgroundSurface is null !");
return;
}
@@ -201,6 +200,30 @@
}
}
+ /**
+ * onConfigurationChanged events for updating tutorial text.
+ */
+ public void onConfigurationChanged() {
+ synchronized (mLock) {
+ if (mBackgroundSurface == null) {
+ getBackgroundSurface();
+ } else {
+ removeBackgroundPanelLayer();
+ }
+ updateThemeColors();
+ showBackgroundPanelLayer();
+ }
+ }
+
+ private void updateThemeColors() {
+ synchronized (mLock) {
+ final int themeColor = mContext.getColor(R.color.one_handed_tutorial_background_color);
+ mDefaultColor = new float[]{(Color.red(themeColor) - THEME_COLOR_OFFSET) / 255.0f,
+ (Color.green(themeColor) - THEME_COLOR_OFFSET) / 255.0f,
+ (Color.blue(themeColor) - THEME_COLOR_OFFSET) / 255.0f};
+ }
+ }
+
void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 2038cff..09cde38 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -658,12 +658,13 @@
}
private void onConfigChanged(Configuration newConfig) {
- if (mTutorialHandler == null) {
+ if (mTutorialHandler == null || mBackgroundPanelOrganizer == null) {
return;
}
if (!mIsOneHandedEnabled || newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
return;
}
+ mBackgroundPanelOrganizer.onConfigurationChanged();
mTutorialHandler.onConfigurationChanged();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
index d0206a4..97e04b5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
@@ -25,8 +25,11 @@
import static com.android.wm.shell.onehanded.OneHandedState.STATE_EXITING;
import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;
+import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.SystemProperties;
@@ -35,9 +38,13 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
import androidx.annotation.NonNull;
+import androidx.appcompat.view.ContextThemeWrapper;
import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.R;
@@ -53,11 +60,14 @@
public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
OneHandedState.OnStateChangedListener {
private static final String TAG = "OneHandedTutorialHandler";
- private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
- "persist.debug.one_handed_offset_percentage";
+ private static final String OFFSET_PERCENTAGE = "persist.debug.one_handed_offset_percentage";
+ private static final String TRANSLATE_ANIMATION_DURATION =
+ "persist.debug.one_handed_translate_animation_duration";
+ private static final float START_TRANSITION_FRACTION = 0.7f;
private final float mTutorialHeightRatio;
private final WindowManager mWindowManager;
+ private final OneHandedAnimationCallback mAnimationCallback;
private @OneHandedState.State int mCurrentState;
private int mTutorialAreaHeight;
@@ -67,7 +77,9 @@
private @Nullable View mTutorialView;
private @Nullable ViewGroup mTargetViewContainer;
- private final OneHandedAnimationCallback mAnimationCallback;
+ private float mAlphaTransitionStart;
+ private ValueAnimator mAlphaAnimator;
+ private int mAlphaAnimationDurationMs;
public OneHandedTutorialHandler(Context context, WindowManager windowManager) {
mContext = context;
@@ -75,15 +87,35 @@
final float offsetPercentageConfig = context.getResources().getFraction(
R.fraction.config_one_handed_offset, 1, 1);
final int sysPropPercentageConfig = SystemProperties.getInt(
- ONE_HANDED_MODE_OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
+ OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
mTutorialHeightRatio = sysPropPercentageConfig / 100.0f;
+ final int animationDuration = context.getResources().getInteger(
+ R.integer.config_one_handed_translate_animation_duration);
+ mAlphaAnimationDurationMs = SystemProperties.getInt(TRANSLATE_ANIMATION_DURATION,
+ animationDuration);
mAnimationCallback = new OneHandedAnimationCallback() {
@Override
+ public void onOneHandedAnimationCancel(
+ OneHandedAnimationController.OneHandedTransitionAnimator animator) {
+ if (mAlphaAnimator != null) {
+ mAlphaAnimator.cancel();
+ }
+ }
+
+ @Override
public void onAnimationUpdate(float xPos, float yPos) {
if (!isAttached()) {
return;
}
- mTargetViewContainer.setTranslationY(yPos - mTutorialAreaHeight);
+ if (yPos < mAlphaTransitionStart) {
+ checkTransitionEnd();
+ return;
+ }
+ if (mAlphaAnimator == null || mAlphaAnimator.isStarted()
+ || mAlphaAnimator.isRunning()) {
+ return;
+ }
+ mAlphaAnimator.start();
}
};
}
@@ -94,12 +126,16 @@
switch (newState) {
case STATE_ENTERING:
createViewAndAttachToWindow(mContext);
+ updateThemeColor();
+ setupAlphaTransition(true /* isEntering */);
break;
case STATE_ACTIVE:
- case STATE_EXITING:
- // no - op
+ checkTransitionEnd();
+ setupAlphaTransition(false /* isEntering */);
break;
+ case STATE_EXITING:
case STATE_NONE:
+ checkTransitionEnd();
removeTutorialFromWindowManager();
break;
default:
@@ -119,6 +155,7 @@
mDisplayBounds = new Rect(0, 0, displayLayout.height(), displayLayout.width());
}
mTutorialAreaHeight = Math.round(mDisplayBounds.height() * mTutorialHeightRatio);
+ mAlphaTransitionStart = mTutorialAreaHeight * START_TRANSITION_FRACTION;
}
@VisibleForTesting
@@ -129,6 +166,7 @@
mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
mTargetViewContainer = new FrameLayout(context);
mTargetViewContainer.setClipChildren(false);
+ mTargetViewContainer.setAlpha(mCurrentState == STATE_ACTIVE ? 1.0f : 0.0f);
mTargetViewContainer.addView(mTutorialView);
mTargetViewContainer.setLayerType(LAYER_TYPE_HARDWARE, null);
@@ -192,6 +230,52 @@
removeTutorialFromWindowManager();
if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
createViewAndAttachToWindow(mContext);
+ updateThemeColor();
+ checkTransitionEnd();
+ }
+ }
+
+ private void updateThemeColor() {
+ if (mTutorialView == null) {
+ return;
+ }
+
+ final Context themedContext = new ContextThemeWrapper(mTutorialView.getContext(),
+ com.android.internal.R.style.Theme_DeviceDefault_DayNight);
+ final int textColorPrimary;
+ final int themedTextColorSecondary;
+ TypedArray ta = themedContext.obtainStyledAttributes(new int[]{
+ com.android.internal.R.attr.textColorPrimary,
+ com.android.internal.R.attr.textColorSecondary});
+ textColorPrimary = ta.getColor(0, 0);
+ themedTextColorSecondary = ta.getColor(1, 0);
+ ta.recycle();
+
+ final ImageView iconView = mTutorialView.findViewById(R.id.one_handed_tutorial_image);
+ iconView.setImageTintList(ColorStateList.valueOf(textColorPrimary));
+
+ final TextView tutorialTitle = mTutorialView.findViewById(R.id.one_handed_tutorial_title);
+ final TextView tutorialDesc = mTutorialView.findViewById(
+ R.id.one_handed_tutorial_description);
+ tutorialTitle.setTextColor(textColorPrimary);
+ tutorialDesc.setTextColor(themedTextColorSecondary);
+ }
+
+ private void setupAlphaTransition(boolean isEntering) {
+ final float start = isEntering ? 0.0f : 1.0f;
+ final float end = isEntering ? 1.0f : 0.0f;
+ mAlphaAnimator = ValueAnimator.ofFloat(start, end);
+ mAlphaAnimator.setInterpolator(new LinearInterpolator());
+ mAlphaAnimator.setDuration(mAlphaAnimationDurationMs);
+ mAlphaAnimator.addUpdateListener(
+ animator -> mTargetViewContainer.setAlpha((float) animator.getAnimatedValue()));
+ }
+
+ private void checkTransitionEnd() {
+ if (mAlphaAnimator != null && mAlphaAnimator.isRunning()) {
+ mAlphaAnimator.end();
+ mAlphaAnimator.removeAllUpdateListeners();
+ mAlphaAnimator = null;
}
}
@@ -206,5 +290,9 @@
pw.println(mDisplayBounds);
pw.print(innerPrefix + "mTutorialAreaHeight=");
pw.println(mTutorialAreaHeight);
+ pw.print(innerPrefix + "mAlphaTransitionStart=");
+ pw.println(mAlphaTransitionStart);
+ pw.print(innerPrefix + "mAlphaAnimationDurationMs=");
+ pw.println(mAlphaAnimationDurationMs);
}
}
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 5a50619..f2bad6c 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
@@ -1384,11 +1384,20 @@
final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f);
animator.setDuration(mCrossFadeAnimationDuration);
animator.addUpdateListener(animation -> {
- final float alpha = (float) animation.getAnimatedValue();
- final SurfaceControl.Transaction transaction =
- mSurfaceControlTransactionFactory.getTransaction();
- transaction.setAlpha(surface, alpha);
- transaction.apply();
+ if (mState == State.UNDEFINED) {
+ // Could happen if onTaskVanished happens during the animation since we may have
+ // set a start delay on this animation.
+ Log.d(TAG, "Task vanished, skip fadeOutAndRemoveOverlay");
+ animation.removeAllListeners();
+ animation.removeAllUpdateListeners();
+ animation.cancel();
+ } else {
+ final float alpha = (float) animation.getAnimatedValue();
+ final SurfaceControl.Transaction transaction =
+ mSurfaceControlTransactionFactory.getTransaction();
+ transaction.setAlpha(surface, alpha);
+ transaction.apply();
+ }
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
@@ -1401,6 +1410,10 @@
}
private void removeContentOverlay(SurfaceControl surface, Runnable callback) {
+ if (mState == State.UNDEFINED) {
+ // Avoid double removal, which is fatal.
+ return;
+ }
final SurfaceControl.Transaction tx =
mSurfaceControlTransactionFactory.getTransaction();
tx.remove(surface);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 56ad2be..dff5577 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -23,6 +23,7 @@
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
import android.annotation.ColorInt;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.ActivityThread;
import android.content.BroadcastReceiver;
@@ -64,6 +65,7 @@
import java.util.List;
import java.util.function.Consumer;
+import java.util.function.IntPredicate;
import java.util.function.IntSupplier;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
@@ -132,7 +134,6 @@
* @param splashScreenViewConsumer Receiving the SplashScreenView object, which will also be
* executed on splash screen thread. Note that the view can be
* null if failed.
- * @param bgColorConsumer Receiving the background color once it's estimated complete.
*/
void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
int taskId, Consumer<SplashScreenView> splashScreenViewConsumer) {
@@ -209,9 +210,9 @@
}
private static int estimateWindowBGColor(Drawable themeBGDrawable) {
- final DrawableColorTester themeBGTester =
- new DrawableColorTester(themeBGDrawable, true /* filterTransparent */);
- if (themeBGTester.nonTransparentRatio() == 0) {
+ final DrawableColorTester themeBGTester = new DrawableColorTester(
+ themeBGDrawable, DrawableColorTester.TRANSPARENT_FILTER /* filterType */);
+ if (themeBGTester.passFilterRatio() == 0) {
// the window background is transparent, unable to draw
Slog.w(TAG, "Window background is transparent, fill background with black color");
return getSystemBGColor();
@@ -414,7 +415,8 @@
final ColorCache.IconColor iconColor = mColorCache.getIconColor(
mActivityInfo.packageName, mActivityInfo.getIconResource(),
mLastPackageContextConfigHash,
- () -> new DrawableColorTester(iconForeground, true /* filterTransparent */),
+ () -> new DrawableColorTester(iconForeground,
+ DrawableColorTester.TRANSLUCENT_FILTER /* filterType */),
() -> new DrawableColorTester(adaptiveIconDrawable.getBackground()));
if (DEBUG) {
@@ -443,7 +445,7 @@
// Reference AdaptiveIcon description, outer is 108 and inner is 72, so we
// scale by 192/160 if we only draw adaptiveIcon's foreground.
final float noBgScale =
- iconColor.mFgNonTransparentRatio < ENLARGE_FOREGROUND_ICON_THRESHOLD
+ iconColor.mFgNonTranslucentRatio < ENLARGE_FOREGROUND_ICON_THRESHOLD
? NO_BACKGROUND_SCALE : 1f;
// Using AdaptiveIconDrawable here can help keep the shape consistent with the
// current settings.
@@ -545,13 +547,26 @@
}
private static class DrawableColorTester {
+ private static final int NO_ALPHA_FILTER = 0;
+ // filter out completely invisible pixels
+ private static final int TRANSPARENT_FILTER = 1;
+ // filter out translucent and invisible pixels
+ private static final int TRANSLUCENT_FILTER = 2;
+
+ @IntDef(flag = true, value = {
+ NO_ALPHA_FILTER,
+ TRANSPARENT_FILTER,
+ TRANSLUCENT_FILTER
+ })
+ private @interface QuantizerFilterType {}
+
private final ColorTester mColorChecker;
DrawableColorTester(Drawable drawable) {
- this(drawable, false /* filterTransparent */);
+ this(drawable, NO_ALPHA_FILTER /* filterType */);
}
- DrawableColorTester(Drawable drawable, boolean filterTransparent) {
+ DrawableColorTester(Drawable drawable, @QuantizerFilterType int filterType) {
// Some applications use LayerDrawable for their windowBackground. To ensure that we
// only get the real background, so that the color is not affected by the alpha of the
// upper layer, try to get the lower layer here. This can also speed up the calculation.
@@ -570,12 +585,12 @@
} else {
mColorChecker = drawable instanceof ColorDrawable
? new SingleColorTester((ColorDrawable) drawable)
- : new ComplexDrawableTester(drawable, filterTransparent);
+ : new ComplexDrawableTester(drawable, filterType);
}
}
- public float nonTransparentRatio() {
- return mColorChecker.nonTransparentRatio();
+ public float passFilterRatio() {
+ return mColorChecker.passFilterRatio();
}
public boolean isComplexColor() {
@@ -594,7 +609,7 @@
* A help class to check the color information from a Drawable.
*/
private interface ColorTester {
- float nonTransparentRatio();
+ float passFilterRatio();
boolean isComplexColor();
@@ -622,7 +637,7 @@
}
@Override
- public float nonTransparentRatio() {
+ public float passFilterRatio() {
final int alpha = mColorDrawable.getAlpha();
return (float) (alpha / 255);
}
@@ -651,15 +666,21 @@
private static final int MAX_BITMAP_SIZE = 40;
private final Palette mPalette;
private final boolean mFilterTransparent;
- private static final TransparentFilterQuantizer TRANSPARENT_FILTER_QUANTIZER =
- new TransparentFilterQuantizer();
+ private static final AlphaFilterQuantizer ALPHA_FILTER_QUANTIZER =
+ new AlphaFilterQuantizer();
- ComplexDrawableTester(Drawable drawable, boolean filterTransparent) {
+ /**
+ * @param drawable The test target.
+ * @param filterType Targeting to filter out transparent or translucent pixels,
+ * this would be needed if want to check
+ * {@link #passFilterRatio()}, also affecting the estimated result
+ * of the dominant color.
+ */
+ ComplexDrawableTester(Drawable drawable, @QuantizerFilterType int filterType) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "ComplexDrawableTester");
final Rect initialBounds = drawable.copyBounds();
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
-
// Some drawables do not have intrinsic dimensions
if (width <= 0 || height <= 0) {
width = MAX_BITMAP_SIZE;
@@ -680,9 +701,10 @@
// The Palette API will ignore Alpha, so it cannot handle transparent pixels, but
// sometimes we will need this information to know if this Drawable object is
// transparent.
- mFilterTransparent = filterTransparent;
+ mFilterTransparent = filterType != NO_ALPHA_FILTER;
if (mFilterTransparent) {
- builder = new Palette.Builder(bitmap, TRANSPARENT_FILTER_QUANTIZER)
+ ALPHA_FILTER_QUANTIZER.setFilter(filterType);
+ builder = new Palette.Builder(bitmap, ALPHA_FILTER_QUANTIZER)
.maximumColorCount(5);
} else {
builder = new Palette.Builder(bitmap, null)
@@ -694,8 +716,8 @@
}
@Override
- public float nonTransparentRatio() {
- return mFilterTransparent ? TRANSPARENT_FILTER_QUANTIZER.mNonTransparentRatio : 1;
+ public float passFilterRatio() {
+ return mFilterTransparent ? ALPHA_FILTER_QUANTIZER.mPassFilterRatio : 1;
}
@Override
@@ -726,17 +748,34 @@
return true;
}
- private static class TransparentFilterQuantizer implements Quantizer {
+ private static class AlphaFilterQuantizer implements Quantizer {
private static final int NON_TRANSPARENT = 0xFF000000;
private final Quantizer mInnerQuantizer = new VariationalKMeansQuantizer();
- private float mNonTransparentRatio;
+ private final IntPredicate mTransparentFilter = i -> (i & NON_TRANSPARENT) != 0;
+ private final IntPredicate mTranslucentFilter = i ->
+ (i & NON_TRANSPARENT) == NON_TRANSPARENT;
+
+ private IntPredicate mFilter = mTransparentFilter;
+ private float mPassFilterRatio;
+
+ void setFilter(@QuantizerFilterType int filterType) {
+ switch (filterType) {
+ case TRANSLUCENT_FILTER:
+ mFilter = mTranslucentFilter;
+ break;
+ case TRANSPARENT_FILTER:
+ default:
+ mFilter = mTransparentFilter;
+ break;
+ }
+ }
@Override
public void quantize(final int[] pixels, final int maxColors) {
- mNonTransparentRatio = 0;
+ mPassFilterRatio = 0;
int realSize = 0;
for (int i = pixels.length - 1; i > 0; i--) {
- if ((pixels[i] & NON_TRANSPARENT) != 0) {
+ if (mFilter.test(pixels[i])) {
realSize++;
}
}
@@ -747,11 +786,11 @@
mInnerQuantizer.quantize(pixels, maxColors);
return;
}
- mNonTransparentRatio = (float) realSize / pixels.length;
+ mPassFilterRatio = (float) realSize / pixels.length;
final int[] samplePixels = new int[realSize];
int rowIndex = 0;
for (int i = pixels.length - 1; i > 0; i--) {
- if ((pixels[i] & NON_TRANSPARENT) == NON_TRANSPARENT) {
+ if (mFilter.test(pixels[i])) {
samplePixels[rowIndex] = pixels[i];
rowIndex++;
}
@@ -810,16 +849,16 @@
final int mBgColor;
final boolean mIsBgComplex;
final boolean mIsBgGrayscale;
- final float mFgNonTransparentRatio;
+ final float mFgNonTranslucentRatio;
IconColor(int hash, int fgColor, int bgColor, boolean isBgComplex,
- boolean isBgGrayscale, float fgNonTransparentRatio) {
+ boolean isBgGrayscale, float fgNonTranslucnetRatio) {
super(hash);
mFgColor = fgColor;
mBgColor = bgColor;
mIsBgComplex = isBgComplex;
mIsBgGrayscale = isBgGrayscale;
- mFgNonTransparentRatio = fgNonTransparentRatio;
+ mFgNonTranslucentRatio = fgNonTranslucnetRatio;
}
}
@@ -905,7 +944,7 @@
final DrawableColorTester bgTester = bgColorTesterSupplier.get();
final IconColor iconColor = new IconColor(hash, fgTester.getDominateColor(),
bgTester.getDominateColor(), bgTester.isComplexColor(), bgTester.isGrayscale(),
- fgTester.nonTransparentRatio());
+ fgTester.passFilterRatio());
colors.mIconColors[leastUsedIndex[0]] = iconColor;
return iconColor;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 243751fe..fc7c86d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -168,16 +168,14 @@
void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken,
@StartingWindowType int suggestType) {
final RunningTaskInfo taskInfo = windowInfo.taskInfo;
- final ActivityInfo activityInfo = taskInfo.topActivityInfo;
- if (activityInfo == null) {
+ final ActivityInfo activityInfo = windowInfo.targetActivityInfo != null
+ ? windowInfo.targetActivityInfo
+ : taskInfo.topActivityInfo;
+ if (activityInfo == null || activityInfo.packageName == null) {
return;
}
final int displayId = taskInfo.displayId;
- if (activityInfo.packageName == null) {
- return;
- }
-
final int taskId = taskInfo.taskId;
Context context = mContext;
// replace with the default theme if the application didn't set
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 284f384..d536adb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -214,6 +214,7 @@
final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
taskInfo.topActivityInfo = info;
taskInfo.taskId = taskId;
+ windowInfo.targetActivityInfo = info;
windowInfo.taskInfo = taskInfo;
return windowInfo;
}
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index c4cdb7d..54367b8 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -44,8 +44,6 @@
#include <utils/StrongPointer.h>
#include <utils/Timers.h>
-#include <pthread.h>
-
#include <algorithm>
#include <atomic>
#include <vector>
@@ -60,10 +58,6 @@
struct {
jclass clazz;
jmethodID invokePictureCapturedCallback;
- jmethodID createHintSession;
- jmethodID updateTargetWorkDuration;
- jmethodID reportActualWorkDuration;
- jmethodID closeHintSession;
} gHardwareRenderer;
struct {
@@ -90,14 +84,6 @@
return env;
}
-static bool hasExceptionAndClear(JNIEnv* env) {
- if (GraphicsJNI::hasException(env)) {
- env->ExceptionClear();
- return true;
- }
- return false;
-}
-
typedef ANativeWindow* (*ANW_fromSurface)(JNIEnv* env, jobject surface);
ANW_fromSurface fromSurface;
@@ -147,67 +133,6 @@
}
};
-class HintSessionWrapper : public LightRefBase<HintSessionWrapper> {
-public:
- static sp<HintSessionWrapper> create(JNIEnv* env, RenderProxy* proxy) {
- if (!Properties::useHintManager) return nullptr;
-
- // Include UI thread (self), render thread, and thread pool.
- std::vector<int> tids = CommonPool::getThreadIds();
- tids.push_back(proxy->getRenderThreadTid());
- tids.push_back(pthread_gettid_np(pthread_self()));
-
- jintArray tidsArray = env->NewIntArray(tids.size());
- if (hasExceptionAndClear(env)) return nullptr;
- env->SetIntArrayRegion(tidsArray, 0, tids.size(), reinterpret_cast<jint*>(tids.data()));
- if (hasExceptionAndClear(env)) return nullptr;
- jobject session = env->CallStaticObjectMethod(
- gHardwareRenderer.clazz, gHardwareRenderer.createHintSession, tidsArray);
- if (hasExceptionAndClear(env) || !session) return nullptr;
- return new HintSessionWrapper(env, session);
- }
-
- ~HintSessionWrapper() {
- if (!mSession) return;
- JNIEnv* env = getenv(mVm);
- env->CallStaticVoidMethod(gHardwareRenderer.clazz, gHardwareRenderer.closeHintSession,
- mSession);
- hasExceptionAndClear(env);
- env->DeleteGlobalRef(mSession);
- mSession = nullptr;
- }
-
- void updateTargetWorkDuration(long targetDurationNanos) {
- if (!mSession) return;
- JNIEnv* env = getenv(mVm);
- env->CallStaticVoidMethod(gHardwareRenderer.clazz,
- gHardwareRenderer.updateTargetWorkDuration, mSession,
- static_cast<jlong>(targetDurationNanos));
- hasExceptionAndClear(env);
- }
-
- void reportActualWorkDuration(long actualDurationNanos) {
- if (!mSession) return;
- JNIEnv* env = getenv(mVm);
- env->CallStaticVoidMethod(gHardwareRenderer.clazz,
- gHardwareRenderer.reportActualWorkDuration, mSession,
- static_cast<jlong>(actualDurationNanos));
- hasExceptionAndClear(env);
- }
-
-private:
- HintSessionWrapper(JNIEnv* env, jobject jobject) {
- env->GetJavaVM(&mVm);
- if (jobject) {
- mSession = env->NewGlobalRef(jobject);
- LOG_ALWAYS_FATAL_IF(!mSession, "Failed to make global ref");
- }
- }
-
- JavaVM* mVm = nullptr;
- jobject mSession = nullptr;
-};
-
static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
RenderProxy::rotateProcessStatsBuffer();
}
@@ -235,12 +160,6 @@
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
ContextFactoryImpl factory(rootRenderNode);
RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
- sp<HintSessionWrapper> wrapper = HintSessionWrapper::create(env, proxy);
- if (wrapper) {
- proxy->setHintSessionCallbacks(
- [wrapper](int64_t nanos) { wrapper->updateTargetWorkDuration(nanos); },
- [wrapper](int64_t nanos) { wrapper->reportActualWorkDuration(nanos); });
- }
return (jlong) proxy;
}
@@ -1059,18 +978,6 @@
gHardwareRenderer.invokePictureCapturedCallback = GetStaticMethodIDOrDie(env, hardwareRenderer,
"invokePictureCapturedCallback",
"(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V");
- gHardwareRenderer.createHintSession =
- GetStaticMethodIDOrDie(env, hardwareRenderer, "createHintSession",
- "([I)Landroid/os/PerformanceHintManager$Session;");
- gHardwareRenderer.updateTargetWorkDuration =
- GetStaticMethodIDOrDie(env, hardwareRenderer, "updateTargetWorkDuration",
- "(Landroid/os/PerformanceHintManager$Session;J)V");
- gHardwareRenderer.reportActualWorkDuration =
- GetStaticMethodIDOrDie(env, hardwareRenderer, "reportActualWorkDuration",
- "(Landroid/os/PerformanceHintManager$Session;J)V");
- gHardwareRenderer.closeHintSession =
- GetStaticMethodIDOrDie(env, hardwareRenderer, "closeHintSession",
- "(Landroid/os/PerformanceHintManager$Session;)V");
jclass aSurfaceTransactionCallbackClass =
FindClassOrDie(env, "android/graphics/HardwareRenderer$ASurfaceTransactionCallback");
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index db29e34..e7081df 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -16,6 +16,7 @@
#include "DrawFrameTask.h"
+#include <dlfcn.h>
#include <gui/TraceUtils.h>
#include <utils/Log.h>
#include <algorithm>
@@ -26,11 +27,63 @@
#include "../RenderNode.h"
#include "CanvasContext.h"
#include "RenderThread.h"
+#include "thread/CommonPool.h"
namespace android {
namespace uirenderer {
namespace renderthread {
+namespace {
+
+typedef APerformanceHintManager* (*APH_getManager)();
+typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
+ size_t, int64_t);
+typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_closeSession)(APerformanceHintSession* session);
+
+bool gAPerformanceHintBindingInitialized = false;
+APH_getManager gAPH_getManagerFn = nullptr;
+APH_createSession gAPH_createSessionFn = nullptr;
+APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
+APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
+APH_closeSession gAPH_closeSessionFn = nullptr;
+
+void ensureAPerformanceHintBindingInitialized() {
+ if (gAPerformanceHintBindingInitialized) return;
+
+ void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
+ LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
+
+ gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
+ LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
+ "Failed to find required symbol APerformanceHint_getManager!");
+
+ gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
+ LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
+ "Failed to find required symbol APerformanceHint_createSession!");
+
+ gAPH_updateTargetWorkDurationFn = (APH_updateTargetWorkDuration)dlsym(
+ handle_, "APerformanceHint_updateTargetWorkDuration");
+ LOG_ALWAYS_FATAL_IF(
+ gAPH_updateTargetWorkDurationFn == nullptr,
+ "Failed to find required symbol APerformanceHint_updateTargetWorkDuration!");
+
+ gAPH_reportActualWorkDurationFn = (APH_reportActualWorkDuration)dlsym(
+ handle_, "APerformanceHint_reportActualWorkDuration");
+ LOG_ALWAYS_FATAL_IF(
+ gAPH_reportActualWorkDurationFn == nullptr,
+ "Failed to find required symbol APerformanceHint_reportActualWorkDuration!");
+
+ gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
+ LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
+ "Failed to find required symbol APerformanceHint_closeSession!");
+
+ gAPerformanceHintBindingInitialized = true;
+}
+
+} // namespace
+
DrawFrameTask::DrawFrameTask()
: mRenderThread(nullptr)
, mContext(nullptr)
@@ -39,17 +92,13 @@
DrawFrameTask::~DrawFrameTask() {}
-void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
- RenderNode* targetNode) {
+void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode,
+ int32_t uiThreadId, int32_t renderThreadId) {
mRenderThread = thread;
mContext = context;
mTargetNode = targetNode;
-}
-
-void DrawFrameTask::setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
- std::function<void(int64_t)> reportActualWorkDuration) {
- mUpdateTargetWorkDuration = std::move(updateTargetWorkDuration);
- mReportActualWorkDuration = std::move(reportActualWorkDuration);
+ mUiThreadId = uiThreadId;
+ mRenderThreadId = renderThreadId;
}
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
@@ -144,27 +193,25 @@
unblockUiThread();
}
- // These member callbacks are effectively const as they are set once during init, so it's safe
- // to use these directly instead of making local copies.
- if (mUpdateTargetWorkDuration && mReportActualWorkDuration) {
- constexpr int64_t kSanityCheckLowerBound = 100000; // 0.1ms
- constexpr int64_t kSanityCheckUpperBound = 10000000000; // 10s
- int64_t targetWorkDuration = frameDeadline - intendedVsync;
- targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
- if (targetWorkDuration > kSanityCheckLowerBound &&
- targetWorkDuration < kSanityCheckUpperBound &&
- targetWorkDuration != mLastTargetWorkDuration) {
- mLastTargetWorkDuration = targetWorkDuration;
- mUpdateTargetWorkDuration(targetWorkDuration);
- }
- int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
- int64_t actualDuration = frameDuration -
- (std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
- dequeueBufferDuration;
- if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
- mReportActualWorkDuration(actualDuration);
- }
+ if (!mHintSessionWrapper) mHintSessionWrapper.emplace(mUiThreadId, mRenderThreadId);
+ constexpr int64_t kSanityCheckLowerBound = 100000; // 0.1ms
+ constexpr int64_t kSanityCheckUpperBound = 10000000000; // 10s
+ int64_t targetWorkDuration = frameDeadline - intendedVsync;
+ targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
+ if (targetWorkDuration > kSanityCheckLowerBound &&
+ targetWorkDuration < kSanityCheckUpperBound &&
+ targetWorkDuration != mLastTargetWorkDuration) {
+ mLastTargetWorkDuration = targetWorkDuration;
+ mHintSessionWrapper->updateTargetWorkDuration(targetWorkDuration);
}
+ int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
+ int64_t actualDuration = frameDuration -
+ (std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
+ dequeueBufferDuration;
+ if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
+ mHintSessionWrapper->reportActualWorkDuration(actualDuration);
+ }
+
mLastDequeueBufferDuration = dequeueBufferDuration;
}
@@ -216,6 +263,44 @@
mSignal.signal();
}
+DrawFrameTask::HintSessionWrapper::HintSessionWrapper(int32_t uiThreadId, int32_t renderThreadId) {
+ if (!Properties::useHintManager) return;
+ if (uiThreadId < 0 || renderThreadId < 0) return;
+
+ ensureAPerformanceHintBindingInitialized();
+
+ APerformanceHintManager* manager = gAPH_getManagerFn();
+ if (!manager) return;
+
+ std::vector<int32_t> tids = CommonPool::getThreadIds();
+ tids.push_back(uiThreadId);
+ tids.push_back(renderThreadId);
+
+ // DrawFrameTask code will always set a target duration before reporting actual durations.
+ // So this is just a placeholder value that's never used.
+ int64_t dummyTargetDurationNanos = 16666667;
+ mHintSession =
+ gAPH_createSessionFn(manager, tids.data(), tids.size(), dummyTargetDurationNanos);
+}
+
+DrawFrameTask::HintSessionWrapper::~HintSessionWrapper() {
+ if (mHintSession) {
+ gAPH_closeSessionFn(mHintSession);
+ }
+}
+
+void DrawFrameTask::HintSessionWrapper::updateTargetWorkDuration(long targetDurationNanos) {
+ if (mHintSession) {
+ gAPH_updateTargetWorkDurationFn(mHintSession, targetDurationNanos);
+ }
+}
+
+void DrawFrameTask::HintSessionWrapper::reportActualWorkDuration(long actualDurationNanos) {
+ if (mHintSession) {
+ gAPH_reportActualWorkDurationFn(mHintSession, actualDurationNanos);
+ }
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 2455ea8..6a61a2b 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -16,8 +16,10 @@
#ifndef DRAWFRAMETASK_H
#define DRAWFRAMETASK_H
+#include <optional>
#include <vector>
+#include <performance_hint_private.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <utils/StrongPointer.h>
@@ -60,9 +62,8 @@
DrawFrameTask();
virtual ~DrawFrameTask();
- void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode);
- void setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
- std::function<void(int64_t)> reportActualWorkDuration);
+ void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode,
+ int32_t uiThreadId, int32_t renderThreadId);
void setContentDrawBounds(int left, int top, int right, int bottom) {
mContentDrawBounds.set(left, top, right, bottom);
}
@@ -85,6 +86,18 @@
}
private:
+ class HintSessionWrapper {
+ public:
+ HintSessionWrapper(int32_t uiThreadId, int32_t renderThreadId);
+ ~HintSessionWrapper();
+
+ void updateTargetWorkDuration(long targetDurationNanos);
+ void reportActualWorkDuration(long actualDurationNanos);
+
+ private:
+ APerformanceHintSession* mHintSession = nullptr;
+ };
+
void postAndWait();
bool syncFrameState(TreeInfo& info);
void unblockUiThread();
@@ -95,6 +108,8 @@
RenderThread* mRenderThread;
CanvasContext* mContext;
RenderNode* mTargetNode = nullptr;
+ int32_t mUiThreadId = -1;
+ int32_t mRenderThreadId = -1;
Rect mContentDrawBounds;
/*********************************************
@@ -112,8 +127,7 @@
nsecs_t mLastDequeueBufferDuration = 0;
nsecs_t mLastTargetWorkDuration = 0;
- std::function<void(int64_t)> mUpdateTargetWorkDuration;
- std::function<void(int64_t)> mReportActualWorkDuration;
+ std::optional<HintSessionWrapper> mHintSessionWrapper;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index a77b5b5..c485ce2 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -29,6 +29,8 @@
#include "utils/Macros.h"
#include "utils/TimeUtils.h"
+#include <pthread.h>
+
namespace android {
namespace uirenderer {
namespace renderthread {
@@ -39,7 +41,8 @@
mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
});
- mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
+ mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode,
+ pthread_gettid_np(pthread_self()), getRenderThreadTid());
}
RenderProxy::~RenderProxy() {
@@ -48,7 +51,7 @@
void RenderProxy::destroyContext() {
if (mContext) {
- mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
+ mDrawFrameTask.setContext(nullptr, nullptr, nullptr, -1, -1);
// This is also a fence as we need to be certain that there are no
// outstanding mDrawFrame tasks posted before it is destroyed
mRenderThread.queue().runSync([this]() { delete mContext; });
@@ -76,12 +79,6 @@
mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
}
-void RenderProxy::setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
- std::function<void(int64_t)> reportActualWorkDuration) {
- mDrawFrameTask.setHintSessionCallbacks(std::move(updateTargetWorkDuration),
- std::move(reportActualWorkDuration));
-}
-
void RenderProxy::setSurface(ANativeWindow* window, bool enableTimeout) {
if (window) { ANativeWindow_acquire(window); }
mRenderThread.queue().post([this, win = window, enableTimeout]() mutable {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 1b0f22e..2b5405c 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -71,8 +71,6 @@
void setSwapBehavior(SwapBehavior swapBehavior);
bool loadSystemProperties();
void setName(const char* name);
- void setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
- std::function<void(int64_t)> reportActualWorkDuration);
void setSurface(ANativeWindow* window, bool enableTimeout = true);
void setSurfaceControl(ASurfaceControl* surfaceControl);
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index ac89fecd..8436ba4 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -416,20 +416,14 @@
return -1;
}
- MtpProperty* property = new MtpProperty(MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO,
- MTP_TYPE_STR, true);
- if (!property) {
- env->ThrowNew(clazz_io_exception, "Failed to obtain property.");
- return -1;
- }
-
- if (property->getDataType() != MTP_TYPE_STR) {
+ MtpProperty property(MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO, MTP_TYPE_STR, true);
+ if (property.getDataType() != MTP_TYPE_STR) {
env->ThrowNew(clazz_io_exception, "Unexpected property data type.");
return -1;
}
- property->setCurrentValue(propertyStr);
- if (!device->setDevicePropValueStr(property)) {
+ property.setCurrentValue(propertyStr);
+ if (!device->setDevicePropValueStr(&property)) {
env->ThrowNew(clazz_io_exception, "Failed to obtain property value.");
return -1;
}
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 3ee2c18..32b7a07 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -57,6 +57,7 @@
"net.c",
"obb.cpp",
"permission_manager.cpp",
+ "performance_hint.cpp",
"sensor.cpp",
"sharedmem.cpp",
"storage_manager.cpp",
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index de6db1a..f33e118 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -312,6 +312,13 @@
LIBANDROID_PLATFORM {
global:
+ APerformanceHint_getManager;
+ APerformanceHint_createSession;
+ APerformanceHint_getPreferredUpdateRateNanos;
+ APerformanceHint_updateTargetWorkDuration;
+ APerformanceHint_reportActualWorkDuration;
+ APerformanceHint_closeSession;
+ APerformanceHint_setIHintManagerForTesting;
extern "C++" {
ASurfaceControl_registerSurfaceStatsListener*;
ASurfaceControl_unregisterSurfaceStatsListener*;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
new file mode 100644
index 0000000..95a2da9
--- /dev/null
+++ b/native/android/performance_hint.cpp
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "perf_hint"
+
+#include <utility>
+#include <vector>
+
+#include <android/os/IHintManager.h>
+#include <android/os/IHintSession.h>
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+#include <performance_hint_private.h>
+#include <utils/SystemClock.h>
+
+using namespace android;
+using namespace android::os;
+
+struct APerformanceHintSession;
+
+struct APerformanceHintManager {
+public:
+ static APerformanceHintManager* getInstance();
+ APerformanceHintManager(sp<IHintManager> service, int64_t preferredRateNanos);
+ APerformanceHintManager() = delete;
+ ~APerformanceHintManager() = default;
+
+ APerformanceHintSession* createSession(const int32_t* threadIds, size_t size,
+ int64_t initialTargetWorkDurationNanos);
+ int64_t getPreferredRateNanos() const;
+
+private:
+ static APerformanceHintManager* create(sp<IHintManager> iHintManager);
+
+ sp<IHintManager> mHintManager;
+ const int64_t mPreferredRateNanos;
+};
+
+struct APerformanceHintSession {
+public:
+ APerformanceHintSession(sp<IHintSession> session, int64_t preferredRateNanos,
+ int64_t targetDurationNanos);
+ APerformanceHintSession() = delete;
+ ~APerformanceHintSession();
+
+ int updateTargetWorkDuration(int64_t targetDurationNanos);
+ int reportActualWorkDuration(int64_t actualDurationNanos);
+
+private:
+ friend struct APerformanceHintManager;
+
+ sp<IHintSession> mHintSession;
+ // HAL preferred update rate
+ const int64_t mPreferredRateNanos;
+ // Target duration for choosing update rate
+ int64_t mTargetDurationNanos;
+ // Last update timestamp
+ int64_t mLastUpdateTimestamp;
+ // Cached samples
+ std::vector<int64_t> mActualDurationsNanos;
+ std::vector<int64_t> mTimestampsNanos;
+};
+
+static IHintManager* gIHintManagerForTesting = nullptr;
+static APerformanceHintManager* gHintManagerForTesting = nullptr;
+
+// ===================================== APerformanceHintManager implementation
+APerformanceHintManager::APerformanceHintManager(sp<IHintManager> manager,
+ int64_t preferredRateNanos)
+ : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {}
+
+APerformanceHintManager* APerformanceHintManager::getInstance() {
+ if (gHintManagerForTesting) return gHintManagerForTesting;
+ if (gIHintManagerForTesting) {
+ APerformanceHintManager* manager = create(gIHintManagerForTesting);
+ gIHintManagerForTesting = nullptr;
+ return manager;
+ }
+ static APerformanceHintManager* instance = create(nullptr);
+ return instance;
+}
+
+APerformanceHintManager* APerformanceHintManager::create(sp<IHintManager> manager) {
+ if (!manager) {
+ manager = interface_cast<IHintManager>(
+ defaultServiceManager()->checkService(String16("performance_hint")));
+ }
+ if (manager == nullptr) {
+ ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
+ return nullptr;
+ }
+ int64_t preferredRateNanos = -1L;
+ binder::Status ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
+ if (!ret.isOk()) {
+ ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__,
+ ret.exceptionMessage().c_str());
+ return nullptr;
+ }
+ if (preferredRateNanos <= 0) {
+ ALOGE("%s: PerformanceHint invalid preferred rate.", __FUNCTION__);
+ return nullptr;
+ }
+ return new APerformanceHintManager(std::move(manager), preferredRateNanos);
+}
+
+APerformanceHintSession* APerformanceHintManager::createSession(
+ const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos) {
+ sp<IBinder> token = sp<BBinder>::make();
+ std::vector<int32_t> tids(threadIds, threadIds + size);
+ sp<IHintSession> session;
+ binder::Status ret =
+ mHintManager->createHintSession(token, tids, initialTargetWorkDurationNanos, &session);
+ if (!ret.isOk() || !session) {
+ return nullptr;
+ }
+ return new APerformanceHintSession(std::move(session), mPreferredRateNanos,
+ initialTargetWorkDurationNanos);
+}
+
+int64_t APerformanceHintManager::getPreferredRateNanos() const {
+ return mPreferredRateNanos;
+}
+
+// ===================================== APerformanceHintSession implementation
+
+APerformanceHintSession::APerformanceHintSession(sp<IHintSession> session,
+ int64_t preferredRateNanos,
+ int64_t targetDurationNanos)
+ : mHintSession(std::move(session)),
+ mPreferredRateNanos(preferredRateNanos),
+ mTargetDurationNanos(targetDurationNanos),
+ mLastUpdateTimestamp(elapsedRealtimeNano()) {}
+
+APerformanceHintSession::~APerformanceHintSession() {
+ binder::Status ret = mHintSession->close();
+ if (!ret.isOk()) {
+ ALOGE("%s: HintSession close failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ }
+}
+
+int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) {
+ if (targetDurationNanos <= 0) {
+ ALOGE("%s: targetDurationNanos must be positive", __FUNCTION__);
+ return EINVAL;
+ }
+ binder::Status ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
+ if (!ret.isOk()) {
+ ALOGE("%s: HintSessionn updateTargetWorkDuration failed: %s", __FUNCTION__,
+ ret.exceptionMessage().c_str());
+ return EPIPE;
+ }
+ mTargetDurationNanos = targetDurationNanos;
+ /**
+ * Most of the workload is target_duration dependent, so now clear the cached samples
+ * as they are most likely obsolete.
+ */
+ mActualDurationsNanos.clear();
+ mTimestampsNanos.clear();
+ mLastUpdateTimestamp = elapsedRealtimeNano();
+ return 0;
+}
+
+int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNanos) {
+ if (actualDurationNanos <= 0) {
+ ALOGE("%s: actualDurationNanos must be positive", __FUNCTION__);
+ return EINVAL;
+ }
+ int64_t now = elapsedRealtimeNano();
+ mActualDurationsNanos.push_back(actualDurationNanos);
+ mTimestampsNanos.push_back(now);
+
+ /**
+ * Use current sample to determine the rate limit. We can pick a shorter rate limit
+ * if any sample underperformed, however, it could be the lower level system is slow
+ * to react. So here we explicitly choose the rate limit with the latest sample.
+ */
+ int64_t rateLimit = actualDurationNanos > mTargetDurationNanos ? mPreferredRateNanos
+ : 10 * mPreferredRateNanos;
+ if (now - mLastUpdateTimestamp <= rateLimit) return 0;
+
+ binder::Status ret =
+ mHintSession->reportActualWorkDuration(mActualDurationsNanos, mTimestampsNanos);
+ mActualDurationsNanos.clear();
+ mTimestampsNanos.clear();
+ if (!ret.isOk()) {
+ ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
+ ret.exceptionMessage().c_str());
+ return EPIPE;
+ }
+ mLastUpdateTimestamp = now;
+ return 0;
+}
+
+// ===================================== C API
+APerformanceHintManager* APerformanceHint_getManager() {
+ return APerformanceHintManager::getInstance();
+}
+
+APerformanceHintSession* APerformanceHint_createSession(APerformanceHintManager* manager,
+ const int32_t* threadIds, size_t size,
+ int64_t initialTargetWorkDurationNanos) {
+ return manager->createSession(threadIds, size, initialTargetWorkDurationNanos);
+}
+
+int64_t APerformanceHint_getPreferredUpdateRateNanos(APerformanceHintManager* manager) {
+ return manager->getPreferredRateNanos();
+}
+
+int APerformanceHint_updateTargetWorkDuration(APerformanceHintSession* session,
+ int64_t targetDurationNanos) {
+ return session->updateTargetWorkDuration(targetDurationNanos);
+}
+
+int APerformanceHint_reportActualWorkDuration(APerformanceHintSession* session,
+ int64_t actualDurationNanos) {
+ return session->reportActualWorkDuration(actualDurationNanos);
+}
+
+void APerformanceHint_closeSession(APerformanceHintSession* session) {
+ delete session;
+}
+
+void APerformanceHint_setIHintManagerForTesting(void* iManager) {
+ delete gHintManagerForTesting;
+ gHintManagerForTesting = nullptr;
+ gIHintManagerForTesting = static_cast<IHintManager*>(iManager);
+}
diff --git a/native/android/tests/performance_hint/Android.bp b/native/android/tests/performance_hint/Android.bp
new file mode 100644
index 0000000..fdc1bc6
--- /dev/null
+++ b/native/android/tests/performance_hint/Android.bp
@@ -0,0 +1,65 @@
+// Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+cc_test {
+ name: "PerformanceHintNativeTestCases",
+
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+
+ srcs: ["PerformanceHintNativeTest.cpp"],
+
+ shared_libs: [
+ "libandroid",
+ "liblog",
+ "libbinder",
+ "libpowermanager",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libbase",
+ "libgmock",
+ "libgtest",
+ ],
+ stl: "c++_shared",
+
+ test_suites: [
+ "device-tests",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ header_libs: [
+ "libandroid_headers_private",
+ ],
+}
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
new file mode 100644
index 0000000..284e9ee
--- /dev/null
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PerformanceHintNativeTest"
+
+#include <android/os/IHintManager.h>
+#include <android/os/IHintSession.h>
+#include <binder/IBinder.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <performance_hint_private.h>
+#include <memory>
+#include <vector>
+
+using android::binder::Status;
+using android::os::IHintManager;
+using android::os::IHintSession;
+
+using namespace android;
+using namespace testing;
+
+class MockIHintManager : public IHintManager {
+public:
+ MOCK_METHOD(Status, createHintSession,
+ (const ::android::sp<::android::IBinder>& token, const ::std::vector<int32_t>& tids,
+ int64_t durationNanos, ::android::sp<::android::os::IHintSession>* _aidl_return),
+ (override));
+ MOCK_METHOD(Status, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
+ MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+};
+
+class MockIHintSession : public IHintSession {
+public:
+ MOCK_METHOD(Status, updateTargetWorkDuration, (int64_t targetDurationNanos), (override));
+ MOCK_METHOD(Status, reportActualWorkDuration,
+ (const ::std::vector<int64_t>& actualDurationNanos,
+ const ::std::vector<int64_t>& timeStampNanos),
+ (override));
+ MOCK_METHOD(Status, close, (), (override));
+ MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+};
+
+class PerformanceHintTest : public Test {
+public:
+ void SetUp() override {
+ mMockIHintManager = new StrictMock<MockIHintManager>();
+ APerformanceHint_setIHintManagerForTesting(mMockIHintManager);
+ }
+
+ void TearDown() override {
+ mMockIHintManager = nullptr;
+ // Destroys MockIHintManager.
+ APerformanceHint_setIHintManagerForTesting(nullptr);
+ }
+
+ APerformanceHintManager* createManager() {
+ EXPECT_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(123L), Return(Status())));
+ return APerformanceHint_getManager();
+ }
+
+ StrictMock<MockIHintManager>* mMockIHintManager = nullptr;
+};
+
+TEST_F(PerformanceHintTest, TestGetPreferredUpdateRateNanos) {
+ APerformanceHintManager* manager = createManager();
+ int64_t preferredUpdateRateNanos = APerformanceHint_getPreferredUpdateRateNanos(manager);
+ EXPECT_EQ(123L, preferredUpdateRateNanos);
+}
+
+TEST_F(PerformanceHintTest, TestSession) {
+ APerformanceHintManager* manager = createManager();
+
+ std::vector<int32_t> tids;
+ tids.push_back(1);
+ tids.push_back(2);
+ int64_t targetDuration = 56789L;
+
+ StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
+ sp<IHintSession> session_sp(iSession);
+
+ EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
+
+ APerformanceHintSession* session =
+ APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ ASSERT_TRUE(session);
+
+ int64_t targetDurationNanos = 10;
+ EXPECT_CALL(*iSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
+ int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
+ EXPECT_EQ(0, result);
+
+ usleep(2); // Sleep for longer than preferredUpdateRateNanos.
+ int64_t actualDurationNanos = 20;
+ std::vector<int64_t> actualDurations;
+ actualDurations.push_back(20);
+ EXPECT_CALL(*iSession, reportActualWorkDuration(Eq(actualDurations), _)).Times(Exactly(1));
+ result = APerformanceHint_reportActualWorkDuration(session, actualDurationNanos);
+ EXPECT_EQ(0, result);
+
+ result = APerformanceHint_updateTargetWorkDuration(session, -1L);
+ EXPECT_EQ(EINVAL, result);
+ result = APerformanceHint_reportActualWorkDuration(session, -1L);
+ EXPECT_EQ(EINVAL, result);
+
+ EXPECT_CALL(*iSession, close()).Times(Exactly(1));
+ APerformanceHint_closeSession(session);
+}
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index f04b0e3..266fc78 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -267,26 +267,22 @@
private static void startLottieAnimationWith(LottieAnimationView illustrationView,
Uri imageUri) {
- try {
- final InputStream inputStream =
- getInputStreamFromUri(illustrationView.getContext(), imageUri);
- illustrationView.setAnimation(inputStream, /* cacheKey= */ null);
- illustrationView.setRepeatCount(LottieDrawable.INFINITE);
- illustrationView.playAnimation();
- } catch (IllegalStateException e) {
- Log.w(TAG, "Invalid illustration image uri: " + imageUri, e);
- }
+ final InputStream inputStream =
+ getInputStreamFromUri(illustrationView.getContext(), imageUri);
+ illustrationView.setFailureListener(
+ result -> Log.w(TAG, "Invalid illustration image uri: " + imageUri, result));
+ illustrationView.setAnimation(inputStream, /* cacheKey= */ null);
+ illustrationView.setRepeatCount(LottieDrawable.INFINITE);
+ illustrationView.playAnimation();
}
private static void startLottieAnimationWith(LottieAnimationView illustrationView,
@RawRes int rawRes) {
- try {
- illustrationView.setAnimation(rawRes);
- illustrationView.setRepeatCount(LottieDrawable.INFINITE);
- illustrationView.playAnimation();
- } catch (IllegalStateException e) {
- Log.w(TAG, "Invalid illustration resource id: " + rawRes, e);
- }
+ illustrationView.setFailureListener(
+ result -> Log.w(TAG, "Invalid illustration resource id: " + rawRes, result));
+ illustrationView.setAnimation(rawRes);
+ illustrationView.setRepeatCount(LottieDrawable.INFINITE);
+ illustrationView.playAnimation();
}
private static void resetAnimations(LottieAnimationView illustrationView) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
index ea9be04..9e3312a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
@@ -18,6 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -130,4 +132,27 @@
verify(drawable).start();
}
+
+ @Test
+ public void playLottieAnimationWithUri_verifyFailureListener() {
+ doReturn(null).when(mAnimationView).getDrawable();
+
+ mPreference.setImageUri(mImageUri);
+ mPreference.onBindViewHolder(mViewHolder);
+
+ verify(mAnimationView).setFailureListener(any());
+ }
+
+ @Test
+ public void playLottieAnimationWithResource_verifyFailureListener() {
+ // fake the valid lottie image
+ final int fakeValidResId = 111;
+ doNothing().when(mAnimationView).setImageResource(fakeValidResId);
+ doReturn(null).when(mAnimationView).getDrawable();
+
+ mPreference.setLottieAnimationResId(fakeValidResId);
+ mPreference.onBindViewHolder(mViewHolder);
+
+ verify(mAnimationView).setFailureListener(any());
+ }
}
diff --git a/packages/Shell/res/values-mr/strings.xml b/packages/Shell/res/values-mr/strings.xml
index 3842733..8297488 100644
--- a/packages/Shell/res/values-mr/strings.xml
+++ b/packages/Shell/res/values-mr/strings.xml
@@ -31,7 +31,7 @@
<string name="bugreport_confirm" msgid="5917407234515812495">"बग रीपोर्टांमध्ये तुम्ही संवेदनशील (अॅप-वापर आणि स्थान डेटा यासारखा) डेटा म्हणून विचार करता त्या डेटाच्या समावेशासह सिस्टीमच्या विविध लॉग फायलींमधील डेटा असतो. ज्या लोकांवर आणि अॅपवर तुमचा विश्वास आहे केवळ त्यांच्यासह हा बग रीपोर्ट शेअर करा."</string>
<string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"पुन्हा दर्शवू नका"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"बग रीपोर्ट"</string>
- <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग रिपोर्ट फाइल वाचणे शक्य झाले नाही"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग अहवाल फाइल वाचणे शक्य झाले नाही"</string>
<string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"झिप फाइल मध्ये बग रिपोर्ट तपशील जोडणे शक्य झाले नाही"</string>
<string name="bugreport_unnamed" msgid="2800582406842092709">"अनामित"</string>
<string name="bugreport_info_action" msgid="2158204228510576227">"तपशील"</string>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
index 2e9400e..5420779 100644
--- a/packages/SystemUI/res/values-af/strings_tv.xml
+++ b/packages/SystemUI/res/values-af/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Kennisgewings"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen kennisgewings nie"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
index 71d887d..ede0b78 100644
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"በ<xliff:g id="VPN_APP">%1$s</xliff:g> በኩል"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"ማሳወቂያዎች"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ምንም ማሳወቂያዎች የሉም"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
index 769999f..f6c4aef 100644
--- a/packages/SystemUI/res/values-ar/strings_tv.xml
+++ b/packages/SystemUI/res/values-ar/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"عبر <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"الإشعارات"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ما من إشعارات"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-as/strings_tv.xml b/packages/SystemUI/res/values-as/strings_tv.xml
index 859ea2c..6ceee80 100644
--- a/packages/SystemUI/res/values-as/strings_tv.xml
+++ b/packages/SystemUI/res/values-as/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>ৰ জৰিয়তে"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"জাননী"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনো জাননী নাই"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az/strings_tv.xml b/packages/SystemUI/res/values-az/strings_tv.xml
index 1f1b649..d141ad6 100644
--- a/packages/SystemUI/res/values-az/strings_tv.xml
+++ b/packages/SystemUI/res/values-az/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> vasitəsilə"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirişlər"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildiriş yoxdur"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
index 2eaa499..04a7e81 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Preko: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Obaveštenja"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obaveštenja"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-be/strings_tv.xml b/packages/SystemUI/res/values-be/strings_tv.xml
index 21a2e6e..5aa771f 100644
--- a/packages/SystemUI/res/values-be/strings_tv.xml
+++ b/packages/SystemUI/res/values-be/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Праз <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Апавяшчэнні"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Апавяшчэнняў няма"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
index b7af7cb..49bf014 100644
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Чрез <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Известия"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Няма известия"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings_tv.xml b/packages/SystemUI/res/values-bn/strings_tv.xml
index 38c24ac..5a9b456 100644
--- a/packages/SystemUI/res/values-bn/strings_tv.xml
+++ b/packages/SystemUI/res/values-bn/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"বিজ্ঞপ্তি"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনও বিজ্ঞপ্তি নেই"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings_tv.xml b/packages/SystemUI/res/values-bs/strings_tv.xml
index 01916a1..92c5e2a 100644
--- a/packages/SystemUI/res/values-bs/strings_tv.xml
+++ b/packages/SystemUI/res/values-bs/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavještenja"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavještenja"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
index a060785..dac4a1a 100644
--- a/packages/SystemUI/res/values-ca/strings_tv.xml
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Mitjançant <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacions"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Cap notificació"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
index eeab0d9..e9f4a10 100644
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Přes <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Oznámení"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žádná oznámení"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
index fb0bc2d..9534776 100644
--- a/packages/SystemUI/res/values-da/strings_tv.xml
+++ b/packages/SystemUI/res/values-da/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikationer"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen notifikationer"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
index 0345c80..ec162ef 100644
--- a/packages/SystemUI/res/values-de/strings_tv.xml
+++ b/packages/SystemUI/res/values-de/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Über <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Benachrichtigungen"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Keine Benachrichtigungen"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
index cd92772..175c402 100644
--- a/packages/SystemUI/res/values-el/strings_tv.xml
+++ b/packages/SystemUI/res/values-el/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Μέσω <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Ειδοποιήσεις"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Δεν υπάρχουν ειδοποιήσεις."</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
index 3b3e2d6..08fc8a6 100644
--- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
@@ -26,4 +26,10 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
+ <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
+ <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
+ <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and microphone are recording"</string>
+ <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
+ <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
+ <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and microphone stopped recording"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings_tv.xml b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
index 3b3e2d6..08fc8a6 100644
--- a/packages/SystemUI/res/values-en-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
@@ -26,4 +26,10 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
+ <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
+ <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
+ <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and microphone are recording"</string>
+ <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
+ <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
+ <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and microphone stopped recording"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
index 3b3e2d6..08fc8a6 100644
--- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
@@ -26,4 +26,10 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
+ <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
+ <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
+ <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and microphone are recording"</string>
+ <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
+ <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
+ <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and microphone stopped recording"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
index 3b3e2d6..08fc8a6 100644
--- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
@@ -26,4 +26,10 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string>
+ <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
+ <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
+ <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and microphone are recording"</string>
+ <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
+ <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
+ <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and microphone stopped recording"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings_tv.xml b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
index 34882b3..c030833 100644
--- a/packages/SystemUI/res/values-en-rXC/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
@@ -26,4 +26,10 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No Notifications"</string>
+ <string name="mic_recording_announcement" msgid="7587123608060316575">"Microphone is recording"</string>
+ <string name="camera_recording_announcement" msgid="7240177719403759112">"Camera is recording"</string>
+ <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Camera and Microphone are recording"</string>
+ <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Microphone stopped recording"</string>
+ <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Camera stopped recording"</string>
+ <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Camera and Microphone stopped recording"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
index a0a355b..680e7cc 100644
--- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No hay notificaciones"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
index 4607ad5..16154a4 100644
--- a/packages/SystemUI/res/values-es/strings_tv.xml
+++ b/packages/SystemUI/res/values-es/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sin notificaciones"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-et/strings_tv.xml b/packages/SystemUI/res/values-et/strings_tv.xml
index 593298e..3732020 100644
--- a/packages/SystemUI/res/values-et/strings_tv.xml
+++ b/packages/SystemUI/res/values-et/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Teenuse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Märguanded"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Märguandeid pole"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings_tv.xml b/packages/SystemUI/res/values-eu/strings_tv.xml
index e1c4fcc..524165e 100644
--- a/packages/SystemUI/res/values-eu/strings_tv.xml
+++ b/packages/SystemUI/res/values-eu/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> bidez"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Jakinarazpenak"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ez dago jakinarazpenik"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
index 5ad12df..8038755 100644
--- a/packages/SystemUI/res/values-fa/strings_tv.xml
+++ b/packages/SystemUI/res/values-fa/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"اعلانها"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"اعلانی ندارید"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
index 61cd5ab..17797d7 100644
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Palvelun <xliff:g id="VPN_APP">%1$s</xliff:g> kautta"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Ilmoitukset"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ei ilmoituksia"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
index a667d76..7f45411 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Par <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
index 25fab4e..99bab80 100644
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings_tv.xml b/packages/SystemUI/res/values-gl/strings_tv.xml
index cd12b94..0d35c4d 100644
--- a/packages/SystemUI/res/values-gl/strings_tv.xml
+++ b/packages/SystemUI/res/values-gl/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacións"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Non hai notificacións"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings_tv.xml b/packages/SystemUI/res/values-gu/strings_tv.xml
index a53e983..c2c8ad6 100644
--- a/packages/SystemUI/res/values-gu/strings_tv.xml
+++ b/packages/SystemUI/res/values-gu/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> મારફતે"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"નોટિફિકેશન"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"કોઈ નોટિફિકેશન નથી"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
index fedaae3..eb8f150 100644
--- a/packages/SystemUI/res/values-hi/strings_tv.xml
+++ b/packages/SystemUI/res/values-hi/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाएं"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कोई सूचना नहीं है"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
index 3bfdf70..241195b 100644
--- a/packages/SystemUI/res/values-hr/strings_tv.xml
+++ b/packages/SystemUI/res/values-hr/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem mreže <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavijesti"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavijesti"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
index 91183af..e825584 100644
--- a/packages/SystemUI/res/values-hu/strings_tv.xml
+++ b/packages/SystemUI/res/values-hu/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Ezzel: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Értesítések"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nincs értesítés"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings_tv.xml b/packages/SystemUI/res/values-hy/strings_tv.xml
index cf4eb90..0fab090 100644
--- a/packages/SystemUI/res/values-hy/strings_tv.xml
+++ b/packages/SystemUI/res/values-hy/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ի միջոցով"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Ծանուցումներ"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ծանուցումներ չկան"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index 3b446ad..c787ca2 100644
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikasi"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tidak Ada Notifikasi"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-is/strings_tv.xml b/packages/SystemUI/res/values-is/strings_tv.xml
index 7c23e62..6d7c91c 100644
--- a/packages/SystemUI/res/values-is/strings_tv.xml
+++ b/packages/SystemUI/res/values-is/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Tilkynningar"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Engar tilkynningar"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index 57931b0..c676029 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Tramite <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifiche"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nessuna notifica"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
index f01321e..46e61d0 100644
--- a/packages/SystemUI/res/values-iw/strings_tv.xml
+++ b/packages/SystemUI/res/values-iw/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"דרך <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"התראות"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"אין התראות"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
index 7f676b5..798caec 100644
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> 経由"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"通知はありません"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings_tv.xml b/packages/SystemUI/res/values-ka/strings_tv.xml
index 0819781..b158e5c 100644
--- a/packages/SystemUI/res/values-ka/strings_tv.xml
+++ b/packages/SystemUI/res/values-ka/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ის მიერ"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"შეტყობინებები"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"შეტყობინებები არ არის"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings_tv.xml b/packages/SystemUI/res/values-kk/strings_tv.xml
index 768e3ac..36440c9 100644
--- a/packages/SystemUI/res/values-kk/strings_tv.xml
+++ b/packages/SystemUI/res/values-kk/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> арқылы жалғанған"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Хабарландырулар"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Хабарландырулар жоқ"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km/strings_tv.xml b/packages/SystemUI/res/values-km/strings_tv.xml
index 0dec2d6..b04cc2b 100644
--- a/packages/SystemUI/res/values-km/strings_tv.xml
+++ b/packages/SystemUI/res/values-km/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"តាមរយៈ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"ការជូនដំណឹង"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"គ្មានការជូនដំណឹងទេ"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings_tv.xml b/packages/SystemUI/res/values-kn/strings_tv.xml
index ef10e3a..e4b3314 100644
--- a/packages/SystemUI/res/values-kn/strings_tv.xml
+++ b/packages/SystemUI/res/values-kn/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ಮೂಲಕ"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"ಅಧಿಸೂಚನೆಗಳು"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
index f9c723a..8849265 100644
--- a/packages/SystemUI/res/values-ko/strings_tv.xml
+++ b/packages/SystemUI/res/values-ko/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>에 연결됨"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"알림"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"알림 없음"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings_tv.xml b/packages/SystemUI/res/values-ky/strings_tv.xml
index 1dba865..128c7e0 100644
--- a/packages/SystemUI/res/values-ky/strings_tv.xml
+++ b/packages/SystemUI/res/values-ky/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Билдирмелер"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Билдирме жок"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings_tv.xml b/packages/SystemUI/res/values-lo/strings_tv.xml
index a45fb45..b852456 100644
--- a/packages/SystemUI/res/values-lo/strings_tv.xml
+++ b/packages/SystemUI/res/values-lo/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ຜ່ານ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"ການແຈ້ງເຕືອນ"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ບໍ່ມີການແຈ້ງເຕືອນ"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
index 8c329f9..7cd7507 100644
--- a/packages/SystemUI/res/values-lt/strings_tv.xml
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Per „<xliff:g id="VPN_APP">%1$s</xliff:g>“"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Pranešimai"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nėra jokių pranešimų"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
index 758d28c..4c64843 100644
--- a/packages/SystemUI/res/values-lv/strings_tv.xml
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Izmantojot: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Paziņojumi"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nav paziņojumu"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings_tv.xml b/packages/SystemUI/res/values-mk/strings_tv.xml
index 0dfbd79..55d9df7 100644
--- a/packages/SystemUI/res/values-mk/strings_tv.xml
+++ b/packages/SystemUI/res/values-mk/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преку <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Известувања"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема известувања"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings_tv.xml b/packages/SystemUI/res/values-ml/strings_tv.xml
index 70cced8..6ae342cf 100644
--- a/packages/SystemUI/res/values-ml/strings_tv.xml
+++ b/packages/SystemUI/res/values-ml/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> വഴി"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"അറിയിപ്പുകൾ"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings_tv.xml b/packages/SystemUI/res/values-mn/strings_tv.xml
index 221d8ae..bbb302f 100644
--- a/packages/SystemUI/res/values-mn/strings_tv.xml
+++ b/packages/SystemUI/res/values-mn/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-р"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Мэдэгдэл"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Мэдэгдэл байхгүй байна"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings_tv.xml b/packages/SystemUI/res/values-mr/strings_tv.xml
index ac0cad1..d596d95 100644
--- a/packages/SystemUI/res/values-mr/strings_tv.xml
+++ b/packages/SystemUI/res/values-mr/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> द्वारे"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचना"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"सूचना नाहीत"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings_tv.xml b/packages/SystemUI/res/values-ms/strings_tv.xml
index 46e345e..e28d032 100644
--- a/packages/SystemUI/res/values-ms/strings_tv.xml
+++ b/packages/SystemUI/res/values-ms/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Pemberitahuan"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tiada Pemberitahuan"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-my/strings_tv.xml b/packages/SystemUI/res/values-my/strings_tv.xml
index 268c554..848c403 100644
--- a/packages/SystemUI/res/values-my/strings_tv.xml
+++ b/packages/SystemUI/res/values-my/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> မှတစ်ဆင့်"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"အကြောင်းကြားချက်များ"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"အကြောင်းကြားချက်များ မရှိပါ"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
index c5767dd..11de50a 100644
--- a/packages/SystemUI/res/values-nb/strings_tv.xml
+++ b/packages/SystemUI/res/values-nb/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Varsler"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen varsler"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings_tv.xml b/packages/SystemUI/res/values-ne/strings_tv.xml
index 925f7b76..0bcc1cc 100644
--- a/packages/SystemUI/res/values-ne/strings_tv.xml
+++ b/packages/SystemUI/res/values-ne/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाहरू"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कुनै पनि सूचना छैन"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
index 22d3b88..02c00ec 100644
--- a/packages/SystemUI/res/values-nl/strings_tv.xml
+++ b/packages/SystemUI/res/values-nl/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Meldingen"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen meldingen"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-or/strings_tv.xml b/packages/SystemUI/res/values-or/strings_tv.xml
index 707c49e..8289068 100644
--- a/packages/SystemUI/res/values-or/strings_tv.xml
+++ b/packages/SystemUI/res/values-or/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings_tv.xml b/packages/SystemUI/res/values-pa/strings_tv.xml
index c076194..22fcce8 100644
--- a/packages/SystemUI/res/values-pa/strings_tv.xml
+++ b/packages/SystemUI/res/values-pa/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ਰਾਹੀਂ"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"ਸੂਚਨਾਵਾਂ"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ਕੋਈ ਸੂਚਨਾ ਨਹੀਂ"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
index e63aade..2371b5e 100644
--- a/packages/SystemUI/res/values-pl/strings_tv.xml
+++ b/packages/SystemUI/res/values-pl/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Przez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Powiadomienia"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Brak powiadomień"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
index 2ea8152..d29bc6a 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -26,4 +26,10 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string>
+ <string name="mic_recording_announcement" msgid="7587123608060316575">"O microfone está gravando"</string>
+ <string name="camera_recording_announcement" msgid="7240177719403759112">"A câmera está gravando"</string>
+ <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"A câmera e o microfone estão gravando"</string>
+ <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"O microfone parou de gravar"</string>
+ <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"A câmera parou de gravar"</string>
+ <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"A câmera e o microfone pararam de gravar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
index 8ce3e30..883fa3a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Através de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sem notificações"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
index 2ea8152..d29bc6a 100644
--- a/packages/SystemUI/res/values-pt/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -26,4 +26,10 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string>
+ <string name="mic_recording_announcement" msgid="7587123608060316575">"O microfone está gravando"</string>
+ <string name="camera_recording_announcement" msgid="7240177719403759112">"A câmera está gravando"</string>
+ <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"A câmera e o microfone estão gravando"</string>
+ <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"O microfone parou de gravar"</string>
+ <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"A câmera parou de gravar"</string>
+ <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"A câmera e o microfone pararam de gravar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
index c64a492..9f28693 100644
--- a/packages/SystemUI/res/values-ro/strings_tv.xml
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prin <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificări"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nicio notificare"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
index 8ce0dc2..e2162ea 100644
--- a/packages/SystemUI/res/values-ru/strings_tv.xml
+++ b/packages/SystemUI/res/values-ru/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Через приложение <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Уведомления"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Уведомлений нет."</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-si/strings_tv.xml b/packages/SystemUI/res/values-si/strings_tv.xml
index 3067be3..b750988 100644
--- a/packages/SystemUI/res/values-si/strings_tv.xml
+++ b/packages/SystemUI/res/values-si/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> හරහා"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"දැනුම්දීම්"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"දැනුම්දීම් නැත"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
index b37648d..2b74267 100644
--- a/packages/SystemUI/res/values-sk/strings_tv.xml
+++ b/packages/SystemUI/res/values-sk/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Cez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Upozornenia"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žiadne upozornenia"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
index 1f66138..2ef9705 100644
--- a/packages/SystemUI/res/values-sl/strings_tv.xml
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prek storitve <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Obvestila"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ni obvestil"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings_tv.xml b/packages/SystemUI/res/values-sq/strings_tv.xml
index fb74e38..ece5982 100644
--- a/packages/SystemUI/res/values-sq/strings_tv.xml
+++ b/packages/SystemUI/res/values-sq/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Njoftimet"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Asnjë njoftim"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
index 59151da..38b106b 100644
--- a/packages/SystemUI/res/values-sr/strings_tv.xml
+++ b/packages/SystemUI/res/values-sr/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преко: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Обавештења"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема обавештења"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
index fd8fa4b..22f6baa 100644
--- a/packages/SystemUI/res/values-sv/strings_tv.xml
+++ b/packages/SystemUI/res/values-sv/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Aviseringar"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Inga aviseringar"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
index 8f6880d..086a098 100644
--- a/packages/SystemUI/res/values-sw/strings_tv.xml
+++ b/packages/SystemUI/res/values-sw/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Kupitia <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Arifa"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Hakuna Arifa"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings_tv.xml b/packages/SystemUI/res/values-ta/strings_tv.xml
index 9c62d8cf..398ffe9 100644
--- a/packages/SystemUI/res/values-ta/strings_tv.xml
+++ b/packages/SystemUI/res/values-ta/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> வழியாக"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"அறிவிப்புகள்"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"அறிவிப்புகள் எதுவுமில்லை"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-te/strings_tv.xml b/packages/SystemUI/res/values-te/strings_tv.xml
index 1879edd..33c9ec9 100644
--- a/packages/SystemUI/res/values-te/strings_tv.xml
+++ b/packages/SystemUI/res/values-te/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ద్వారా"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"నోటిఫికేషన్లు"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"నోటిఫికేషన్లు లేవు"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
index 0724821..57cff1f 100644
--- a/packages/SystemUI/res/values-th/strings_tv.xml
+++ b/packages/SystemUI/res/values-th/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"การแจ้งเตือน"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ไม่มีการแจ้งเตือน"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
index 8dcc22f..8be6a86 100644
--- a/packages/SystemUI/res/values-tl/strings_tv.xml
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Sa pamamagitan ng <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Mga Notification"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Walang Notification"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
index 49e76af..28b2d77 100644
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> üzerinden"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirimler"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirim Yok"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
index 170b068..c86cf31 100644
--- a/packages/SystemUI/res/values-uk/strings_tv.xml
+++ b/packages/SystemUI/res/values-uk/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Через <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Сповіщення"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Немає сповіщень"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings_tv.xml b/packages/SystemUI/res/values-ur/strings_tv.xml
index fbaa3f6..5810482 100644
--- a/packages/SystemUI/res/values-ur/strings_tv.xml
+++ b/packages/SystemUI/res/values-ur/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"بذریعہ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"اطلاعات"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"کوئی اطلاع نہیں ہے"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings_tv.xml b/packages/SystemUI/res/values-uz/strings_tv.xml
index f4b4b08..afa82bc 100644
--- a/packages/SystemUI/res/values-uz/strings_tv.xml
+++ b/packages/SystemUI/res/values-uz/strings_tv.xml
@@ -26,4 +26,10 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> orqali"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirishnomalar"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirishnomalar yoʻq"</string>
+ <string name="mic_recording_announcement" msgid="7587123608060316575">"Mikrofon yozib olmoqda"</string>
+ <string name="camera_recording_announcement" msgid="7240177719403759112">"Kamera yozib olmoqda"</string>
+ <string name="mic_and_camera_recording_announcement" msgid="8599231390508812667">"Kamera va mikrofon yozib olmoqda"</string>
+ <string name="mic_stopped_recording_announcement" msgid="7301537004900721242">"Mikrofon yozib olishni toʻxtatdi"</string>
+ <string name="camera_stopped_recording_announcement" msgid="8540496432367032801">"Kamera yozib olishni toʻxtatdi"</string>
+ <string name="mic_camera_stopped_recording_announcement" msgid="8708524579599977412">"Kamera va mikrofon yozib olishni toʻxtatdi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
index 3dfc8c1..21f5471 100644
--- a/packages/SystemUI/res/values-vi/strings_tv.xml
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Thông báo"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Không có thông báo"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
index 1e599ca..ca814a3 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"没有通知"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
index 92b1762..f992b62 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過 <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
index db0781a..94135d2 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
index a9b7597..79a6575 100644
--- a/packages/SystemUI/res/values-zu/strings_tv.xml
+++ b/packages/SystemUI/res/values-zu/strings_tv.xml
@@ -26,4 +26,16 @@
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nge-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="tv_notification_panel_title" msgid="5311050946506276154">"Izaziso"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Azikho Izaziso"</string>
+ <!-- no translation found for mic_recording_announcement (7587123608060316575) -->
+ <skip />
+ <!-- no translation found for camera_recording_announcement (7240177719403759112) -->
+ <skip />
+ <!-- no translation found for mic_and_camera_recording_announcement (8599231390508812667) -->
+ <skip />
+ <!-- no translation found for mic_stopped_recording_announcement (7301537004900721242) -->
+ <skip />
+ <!-- no translation found for camera_stopped_recording_announcement (8540496432367032801) -->
+ <skip />
+ <!-- no translation found for mic_camera_stopped_recording_announcement (8708524579599977412) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 7485ef8..ae09f26 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -921,6 +921,7 @@
<dimen name="keyguard_lock_padding">20dp</dimen>
<dimen name="keyguard_indication_margin_bottom">32dp</dimen>
+ <dimen name="lock_icon_margin_bottom">98dp</dimen>
<!-- The text size for battery level -->
<dimen name="battery_level_text_size">12sp</dimen>
@@ -1266,6 +1267,8 @@
<!-- Three privacy items. This value must not be exceeded -->
<dimen name="ongoing_appops_chip_max_width">76dp</dimen>
<dimen name="ongoing_appops_dot_diameter">6dp</dimen>
+ <!-- Total minimum padding to enforce to ensure that the dot can always show -->
+ <dimen name="ongoing_appops_dot_min_padding">20dp</dimen>
<dimen name="ongoing_appops_dialog_side_margins">@dimen/notification_shade_content_margin_horizontal</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 8b974b4..9c8582fa 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -72,7 +72,10 @@
*/
@StatusBarComponent.StatusBarScope
public class LockIconViewController extends ViewController<LockIconView> implements Dumpable {
-
+ private static final float sDefaultDensity =
+ (float) DisplayMetrics.DENSITY_DEVICE_STABLE / (float) DisplayMetrics.DENSITY_DEFAULT;
+ private static final int sLockIconRadiusPx = (int) (sDefaultDensity * 36);
+ private static final float sDistAboveKgBottomAreaPx = sDefaultDensity * 12;
private static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -111,9 +114,7 @@
private boolean mHasUdfps;
private float mHeightPixels;
private float mWidthPixels;
- private float mDensity;
- private int mAmbientIndicationHeight; // in pixels
- private int mKgIndicationHeight; // in pixels
+ private int mBottomPadding; // in pixels
private boolean mShowUnlockIcon;
private boolean mShowLockIcon;
@@ -318,11 +319,8 @@
final DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics();
mWidthPixels = metrics.widthPixels;
mHeightPixels = metrics.heightPixels;
- mDensity = metrics.density;
- mKgIndicationHeight = mView.getContext().getResources().getDimensionPixelSize(
- R.dimen.keyguard_indication_margin_bottom)
- + mView.getContext().getResources().getDimensionPixelSize(
- R.dimen.keyguard_indication_bottom_padding);
+ mBottomPadding = mView.getContext().getResources().getDimensionPixelSize(
+ R.dimen.lock_icon_margin_bottom);
updateLockIconLocation();
}
@@ -332,26 +330,15 @@
mView.setCenterLocation(new PointF(props.sensorLocationX, props.sensorLocationY),
props.sensorRadius);
} else {
- final float distAboveKgBottomArea = 12 * mDensity;
- final float radius = 36 * mDensity;
- final int kgBottomAreaHeight = Math.max(mKgIndicationHeight, mAmbientIndicationHeight);
mView.setCenterLocation(
new PointF(mWidthPixels / 2,
- mHeightPixels - kgBottomAreaHeight - distAboveKgBottomArea
- - radius / 2), (int) radius);
+ mHeightPixels - mBottomPadding - sDistAboveKgBottomAreaPx
+ - sLockIconRadiusPx), sLockIconRadiusPx);
}
mView.getHitRect(mSensorTouchLocation);
}
- /**
- * Set the location of ambient indication if showing (ie: now playing)
- */
- public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
- mAmbientIndicationHeight = ambientIndicationBottomPadding;
- updateLockIconLocation();
- }
-
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("mUdfpsEnrolled: " + mUdfpsEnrolled);
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 9c87fc4..76f30a8 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -100,6 +100,7 @@
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.AccessibilityController;
@@ -362,6 +363,7 @@
@Inject Lazy<EdgeBackGestureHandler.Factory> mEdgeBackGestureHandlerFactoryLazy;
@Inject Lazy<UiEventLogger> mUiEventLogger;
@Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
+ @Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy;
@Inject
public Dependency() {
@@ -578,6 +580,7 @@
mEdgeBackGestureHandlerFactoryLazy::get);
mProviders.put(UiEventLogger.class, mUiEventLogger::get);
mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
+ mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get);
Dependency.setInstance(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index c241c08..4104e31 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -64,16 +64,12 @@
}
}
- override fun onStart() {
- super.onStart()
+ override fun onResume() {
+ super.onResume()
parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
parent.alpha = 0f
uiController.show(parent, { finish() }, this)
- }
-
- override fun onResume() {
- super.onResume()
ControlsAnimations.enterAnimation(parent).start()
}
@@ -82,8 +78,8 @@
finish()
}
- override fun onStop() {
- super.onStop()
+ override fun onPause() {
+ super.onPause()
uiController.hide()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 4d15a0a..120121c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -885,7 +885,10 @@
mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
- if (biometricSourceType == BiometricSourceType.FACE && shouldSuppressFaceMsg()) {
+ if (biometricSourceType == BiometricSourceType.FACE
+ && shouldSuppressFaceMsgAndShowTryFingerprintMsg()) {
+ // suggest trying fingerprint
+ showTransientIndication(R.string.keyguard_try_fingerprint);
return;
}
showTransientIndication(helpString, false /* isError */, showSwipeToUnlock);
@@ -903,9 +906,11 @@
return;
}
if (biometricSourceType == BiometricSourceType.FACE
- && shouldSuppressFaceMsg()
+ && shouldSuppressFaceMsgAndShowTryFingerprintMsg()
&& !mStatusBarKeyguardViewManager.isBouncerShowing()
&& mKeyguardUpdateMonitor.isScreenOn()) {
+ // suggest trying fingerprint
+ showTransientIndication(R.string.keyguard_try_fingerprint);
return;
}
if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
@@ -956,7 +961,7 @@
|| msgId == FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED);
}
- private boolean shouldSuppressFaceMsg() {
+ private boolean shouldSuppressFaceMsgAndShowTryFingerprintMsg() {
// For dual biometric, don't show face auth messages
return mKeyguardUpdateMonitor.isFingerprintDetectionRunning()
&& mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
index 5f10e55..29cfb07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
@@ -18,6 +18,8 @@
import android.animation.Animator
import android.annotation.UiThread
+import android.graphics.Point
+import android.graphics.Rect
import android.util.Log
import android.view.Gravity
import android.view.View
@@ -31,9 +33,16 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState.SHADE
import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
-import com.android.systemui.statusbar.phone.StatusBarLocationPublisher
-import com.android.systemui.statusbar.phone.StatusBarMarginUpdatedListener
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
+import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.leak.RotationUtils
+import com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE
+import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE
+import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE
+import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
+import com.android.systemui.util.leak.RotationUtils.Rotation
import java.lang.IllegalStateException
import java.util.concurrent.Executor
@@ -58,7 +67,8 @@
class PrivacyDotViewController @Inject constructor(
@Main private val mainExecutor: Executor,
private val stateController: StatusBarStateController,
- private val locationPublisher: StatusBarLocationPublisher,
+ private val configurationController: ConfigurationController,
+ private val contentInsetsProvider: StatusBarContentInsetsProvider,
private val animationScheduler: SystemStatusAnimationScheduler
) {
private var sbHeightPortrait = 0
@@ -84,18 +94,27 @@
// Privacy dots are created in ScreenDecoration's UiThread, which is not the main thread
private var uiExecutor: DelayableExecutor? = null
- private val marginListener: StatusBarMarginUpdatedListener =
- object : StatusBarMarginUpdatedListener {
- override fun onStatusBarMarginUpdated(marginLeft: Int, marginRight: Int) {
- setStatusBarMargins(marginLeft, marginRight)
- }
- }
-
private val views: Sequence<View>
get() = if (!this::tl.isInitialized) sequenceOf() else sequenceOf(tl, tr, br, bl)
init {
- locationPublisher.addCallback(marginListener)
+ contentInsetsProvider.addCallback(object : StatusBarContentInsetsChangedListener {
+ override fun onStatusBarContentInsetsChanged() {
+ dlog("onStatusBarContentInsetsChanged: ")
+ setNewLayoutRects()
+ }
+ })
+ configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
+ override fun onLayoutDirectionChanged(isRtl: Boolean) {
+ synchronized(this) {
+ val corner = selectDesignatedCorner(nextViewState.rotation, isRtl)
+ nextViewState = nextViewState.copy(
+ layoutRtl = isRtl,
+ designatedCorner = corner
+ )
+ }
+ }
+ })
stateController.addCallback(object : StatusBarStateController.StateListener {
override fun onExpandedChanged(isExpanded: Boolean) {
@@ -123,16 +142,19 @@
fun setNewRotation(rot: Int) {
dlog("updateRotation: $rot")
+ val isRtl: Boolean
synchronized(lock) {
if (rot == nextViewState.rotation) {
return
}
+
+ isRtl = nextViewState.layoutRtl
}
// If we rotated, hide all dotes until the next state resolves
setCornerVisibilities(View.INVISIBLE)
- val newCorner = selectDesignatedCorner(rot)
+ val newCorner = selectDesignatedCorner(rot, isRtl)
val index = newCorner.cornerIndex()
val h = when (rot) {
@@ -222,15 +244,77 @@
}
}
+ @UiThread
+ private fun setCornerSizes(state: ViewState) {
+ // StatusBarContentInsetsProvider can tell us the location of the privacy indicator dot
+ // in every rotation. The only thing we need to check is rtl
+ val rtl = state.layoutRtl
+ val size = Point()
+ tl.context.display.getRealSize(size)
+ val currentRotation = RotationUtils.getExactRotation(tl.context)
+
+ val displayWidth: Int
+ val displayHeight: Int
+ if (currentRotation == ROTATION_LANDSCAPE || currentRotation == ROTATION_SEASCAPE) {
+ displayWidth = size.y
+ displayHeight = size.x
+ } else {
+ displayWidth = size.x
+ displayHeight = size.y
+ }
+
+ var rot = activeRotationForCorner(tl, rtl)
+ var contentInsets = state.contentRectForRotation(rot)
+ (tl.layoutParams as FrameLayout.LayoutParams).apply {
+ height = contentInsets.height()
+ if (rtl) {
+ width = contentInsets.left
+ } else {
+ width = displayHeight - contentInsets.right
+ }
+ }
+
+ rot = activeRotationForCorner(tr, rtl)
+ contentInsets = state.contentRectForRotation(rot)
+ (tr.layoutParams as FrameLayout.LayoutParams).apply {
+ height = contentInsets.height()
+ if (rtl) {
+ width = contentInsets.left
+ } else {
+ width = displayWidth - contentInsets.right
+ }
+ }
+
+ rot = activeRotationForCorner(br, rtl)
+ contentInsets = state.contentRectForRotation(rot)
+ (br.layoutParams as FrameLayout.LayoutParams).apply {
+ height = contentInsets.height()
+ if (rtl) {
+ width = contentInsets.left
+ } else {
+ width = displayHeight - contentInsets.right
+ }
+ }
+
+ rot = activeRotationForCorner(bl, rtl)
+ contentInsets = state.contentRectForRotation(rot)
+ (bl.layoutParams as FrameLayout.LayoutParams).apply {
+ height = contentInsets.height()
+ if (rtl) {
+ width = contentInsets.left
+ } else {
+ width = displayWidth - contentInsets.right
+ }
+ }
+ }
+
// Designated view will be the one at statusbar's view.END
@UiThread
- private fun selectDesignatedCorner(r: Int): View? {
+ private fun selectDesignatedCorner(r: Int, isRtl: Boolean): View? {
if (!this::tl.isInitialized) {
return null
}
- val isRtl = tl.isLayoutRtl
-
return when (r) {
0 -> if (isRtl) tl else tr
1 -> if (isRtl) tr else br
@@ -282,6 +366,17 @@
return modded
}
+ @Rotation
+ private fun activeRotationForCorner(corner: View, rtl: Boolean): Int {
+ // Each corner will only be visible in a single rotation, based on rtl
+ return when (corner) {
+ tr -> if (rtl) ROTATION_LANDSCAPE else ROTATION_NONE
+ tl -> if (rtl) ROTATION_NONE else ROTATION_SEASCAPE
+ br -> if (rtl) ROTATION_UPSIDE_DOWN else ROTATION_LANDSCAPE
+ else /* bl */ -> if (rtl) ROTATION_SEASCAPE else ROTATION_UPSIDE_DOWN
+ }
+ }
+
private fun widthForCorner(corner: Int, left: Int, right: Int): Int {
return when (corner) {
TOP_LEFT, BOTTOM_LEFT -> left
@@ -303,15 +398,32 @@
bl = bottomLeft
br = bottomRight
- val dc = selectDesignatedCorner(0)
+ val rtl = configurationController.isLayoutRtl
+ val dc = selectDesignatedCorner(0, rtl)
+
val index = dc.cornerIndex()
mainExecutor.execute {
animationScheduler.addCallback(systemStatusAnimationCallback)
}
+ val left = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_SEASCAPE)
+ val top = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
+ val right = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_LANDSCAPE)
+ val bottom = contentInsetsProvider
+ .getStatusBarContentInsetsForRotation(ROTATION_UPSIDE_DOWN)
+
synchronized(lock) {
- nextViewState = nextViewState.copy(designatedCorner = dc, cornerIndex = index)
+ nextViewState = nextViewState.copy(
+ viewInitialized = true,
+ designatedCorner = dc,
+ cornerIndex = index,
+ seascapeRect = left,
+ portraitRect = top,
+ landscapeRect = right,
+ upsideDownRect = bottom,
+ layoutRtl = rtl
+ )
}
}
@@ -324,19 +436,6 @@
sbHeightLandscape = landscape
}
- /**
- * The dot view containers will fill the margin in order to position the dots correctly
- *
- * @param left the space between the status bar contents and the left side of the screen
- * @param right space between the status bar contents and the right side of the screen
- */
- private fun setStatusBarMargins(left: Int, right: Int) {
- dlog("setStatusBarMargins l=$left r=$right")
- synchronized(lock) {
- nextViewState = nextViewState.copy(marginLeft = left, marginRight = right)
- }
- }
-
private fun updateStatusBarState() {
synchronized(lock) {
nextViewState = nextViewState.copy(shadeExpanded = isShadeInQs())
@@ -377,6 +476,11 @@
@UiThread
private fun resolveState(state: ViewState) {
dlog("resolveState $state")
+ if (!state.viewInitialized) {
+ dlog("resolveState: view is not initialized. skipping.")
+ return
+ }
+
if (state == currentViewState) {
dlog("resolveState: skipping")
return
@@ -387,23 +491,15 @@
updateRotations(state.rotation)
}
- if (state.height != currentViewState.height) {
- updateHeights(state.rotation)
- }
-
- if (state.marginLeft != currentViewState.marginLeft ||
- state.marginRight != currentViewState.marginRight) {
- updateCornerSizes(state.marginLeft, state.marginRight, state.rotation)
+ if (state.needsLayout(currentViewState)) {
+ setCornerSizes(state)
+ views.forEach { it.requestLayout() }
}
if (state.designatedCorner != currentViewState.designatedCorner) {
updateDesignatedCorner(state.designatedCorner, state.shouldShowDot())
}
- if (state.needsLayout(currentViewState)) {
- views.forEach { it.requestLayout() }
- }
-
val shouldShow = state.shouldShowDot()
if (shouldShow != currentViewState.shouldShowDot()) {
if (shouldShow && state.designatedCorner != null) {
@@ -441,6 +537,30 @@
}
return -1
}
+
+ // Returns [left, top, right, bottom] aka [seascape, none, landscape, upside-down]
+ private fun getLayoutRects(): List<Rect> {
+ val left = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_SEASCAPE)
+ val top = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
+ val right = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_LANDSCAPE)
+ val bottom = contentInsetsProvider
+ .getStatusBarContentInsetsForRotation(ROTATION_UPSIDE_DOWN)
+
+ return listOf(left, top, right, bottom)
+ }
+
+ private fun setNewLayoutRects() {
+ val rects = getLayoutRects()
+
+ synchronized(lock) {
+ nextViewState = nextViewState.copy(
+ seascapeRect = rects[0],
+ portraitRect = rects[1],
+ landscapeRect = rects[2],
+ upsideDownRect = rects[3]
+ )
+ }
+ }
}
private fun dlog(s: String) {
@@ -461,7 +581,7 @@
const val BOTTOM_LEFT = 3
private const val DURATION = 160L
private const val TAG = "PrivacyDotViewController"
-private const val DEBUG = true
+private const val DEBUG = false
private const val DEBUG_VERBOSE = false
private fun Int.toGravity(): Int {
@@ -485,14 +605,20 @@
}
private data class ViewState(
+ val viewInitialized: Boolean = false,
+
val systemPrivacyEventIsActive: Boolean = false,
val shadeExpanded: Boolean = false,
val qsExpanded: Boolean = false,
+ val portraitRect: Rect? = null,
+ val landscapeRect: Rect? = null,
+ val upsideDownRect: Rect? = null,
+ val seascapeRect: Rect? = null,
+ val layoutRtl: Boolean = false,
+
val rotation: Int = 0,
val height: Int = 0,
- val marginLeft: Int = 0,
- val marginRight: Int = 0,
val cornerIndex: Int = -1,
val designatedCorner: View? = null
) {
@@ -502,7 +628,20 @@
fun needsLayout(other: ViewState): Boolean {
return rotation != other.rotation ||
- marginRight != other.marginRight ||
- height != other.height
+ layoutRtl != other.layoutRtl ||
+ portraitRect != other.portraitRect ||
+ landscapeRect != other.landscapeRect ||
+ upsideDownRect != other.upsideDownRect ||
+ seascapeRect != other.seascapeRect
+ }
+
+ fun contentRectForRotation(@Rotation rot: Int): Rect {
+ return when (rot) {
+ ROTATION_NONE -> portraitRect!!
+ ROTATION_LANDSCAPE -> landscapeRect!!
+ ROTATION_UPSIDE_DOWN -> upsideDownRect!!
+ ROTATION_SEASCAPE -> seascapeRect!!
+ else -> throw IllegalArgumentException("not a rotation ($rot)")
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 93166f3..73bb6cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -287,7 +287,7 @@
mGroupExpansionChanging = true;
final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
boolean nowExpanded = mGroupExpansionManager.toggleGroupExpansion(mEntry);
- mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+ mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded);
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
nowExpanded);
onExpansionChanged(true /* userAction */, wasExpanded);
@@ -310,7 +310,7 @@
setUserExpanded(nowExpanded);
}
notifyHeightChanged(true);
- mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
+ mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded);
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_EXPANDER,
nowExpanded);
}
@@ -3064,7 +3064,7 @@
}
public interface OnExpandClickListener {
- void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded);
+ void onExpandClicked(NotificationEntry clickedEntry, View clickedView, boolean nowExpanded);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 23e3742..d0507e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -394,7 +394,8 @@
ambientState.getExpansionFraction(), true /* notification */);
}
- if (view.mustStayOnScreen() && viewState.yTranslation >= 0) {
+ if (ambientState.isShadeExpanded() && view.mustStayOnScreen()
+ && viewState.yTranslation >= 0) {
// Even if we're not scrolled away we're in view and we're also not in the
// shelf. We can relax the constraints and let us scroll off the top!
float end = viewState.yTranslation + viewState.height + ambientState.getStackY();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 1361acb..596fce5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -37,7 +37,6 @@
import android.view.ViewStub;
import android.widget.LinearLayout;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -76,9 +75,9 @@
public static final int FADE_IN_DURATION = 320;
public static final int FADE_IN_DELAY = 50;
private PhoneStatusBarView mStatusBar;
- private StatusBarStateController mStatusBarStateController;
- private KeyguardStateController mKeyguardStateController;
- private NetworkController mNetworkController;
+ private final StatusBarStateController mStatusBarStateController;
+ private final KeyguardStateController mKeyguardStateController;
+ private final NetworkController mNetworkController;
private LinearLayout mSystemIconArea;
private View mClockView;
private View mOngoingCallChip;
@@ -86,15 +85,16 @@
private View mCenteredIconArea;
private int mDisabled1;
private int mDisabled2;
- private StatusBar mStatusBarComponent;
+ private final StatusBar mStatusBarComponent;
private DarkIconManager mDarkIconManager;
private View mOperatorNameFrame;
- private CommandQueue mCommandQueue;
- private OngoingCallController mOngoingCallController;
+ private final CommandQueue mCommandQueue;
+ private final OngoingCallController mOngoingCallController;
private final SystemStatusAnimationScheduler mAnimationScheduler;
private final StatusBarLocationPublisher mLocationPublisher;
- private NotificationIconAreaController mNotificationIconAreaController;
private final FeatureFlags mFeatureFlags;
+ private final NotificationIconAreaController mNotificationIconAreaController;
+ private final StatusBarIconController mStatusBarIconController;
private List<String> mBlockedIcons = new ArrayList<>();
@@ -118,23 +118,25 @@
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
NotificationIconAreaController notificationIconAreaController,
- FeatureFlags featureFlags
+ FeatureFlags featureFlags,
+ StatusBarIconController statusBarIconController,
+ KeyguardStateController keyguardStateController,
+ NetworkController networkController,
+ StatusBarStateController statusBarStateController,
+ StatusBar statusBarComponent,
+ CommandQueue commandQueue
) {
mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler;
mLocationPublisher = locationPublisher;
mNotificationIconAreaController = notificationIconAreaController;
mFeatureFlags = featureFlags;
- }
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mKeyguardStateController = Dependency.get(KeyguardStateController.class);
- mNetworkController = Dependency.get(NetworkController.class);
- mStatusBarStateController = Dependency.get(StatusBarStateController.class);
- mStatusBarComponent = Dependency.get(StatusBar.class);
- mCommandQueue = Dependency.get(CommandQueue.class);
+ mStatusBarIconController = statusBarIconController;
+ mKeyguardStateController = keyguardStateController;
+ mNetworkController = networkController;
+ mStatusBarStateController = statusBarStateController;
+ mStatusBarComponent = statusBarComponent;
+ mCommandQueue = commandQueue;
}
@Override
@@ -160,7 +162,7 @@
mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
mDarkIconManager.setBlockList(mBlockedIcons);
- Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
+ mStatusBarIconController.addIconGroup(mDarkIconManager);
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
mClockView = mStatusBar.findViewById(R.id.clock);
mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip);
@@ -199,7 +201,7 @@
@Override
public void onDestroyView() {
super.onDestroyView();
- Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
+ mStatusBarIconController.removeIconGroup(mDarkIconManager);
if (mNetworkController.hasEmergencyCryptKeeperText()) {
mNetworkController.removeCallback(mSignalCallback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index b148eeb..07618da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -18,6 +18,7 @@
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.os.LocaleList
+import android.view.View.LAYOUT_DIRECTION_RTL
import com.android.systemui.statusbar.policy.ConfigurationController
import java.util.ArrayList
@@ -33,6 +34,7 @@
private var uiMode: Int = 0
private var localeList: LocaleList? = null
private val context: Context
+ private var layoutDirection: Int
init {
val currentConfig = context.resources.configuration
@@ -44,6 +46,7 @@
Configuration.UI_MODE_TYPE_CAR
uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
localeList = currentConfig.locales
+ layoutDirection = currentConfig.layoutDirection
}
override fun notifyThemeChanged() {
@@ -101,6 +104,13 @@
}
}
+ if (layoutDirection != newConfig.layoutDirection) {
+ layoutDirection = newConfig.layoutDirection
+ listeners.filterForEach({ this.listeners.contains(it) }) {
+ it.onLayoutDirectionChanged(layoutDirection == LAYOUT_DIRECTION_RTL)
+ }
+ }
+
if (lastConfig.updateFrom(newConfig) and ActivityInfo.CONFIG_ASSETS_PATHS != 0) {
listeners.filterForEach({ this.listeners.contains(it) }) {
it.onOverlayChanged()
@@ -116,6 +126,10 @@
override fun removeCallback(listener: ConfigurationController.ConfigurationListener) {
listeners.remove(listener)
}
+
+ override fun isLayoutRtl(): Boolean {
+ return layoutDirection == LAYOUT_DIRECTION_RTL
+ }
}
// This could be done with a Collection.filter and Collection.forEach, but Collection.filter
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 3c1892d..7958301 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3635,8 +3635,6 @@
public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
if (mAmbientIndicationBottomPadding != ambientIndicationBottomPadding) {
mAmbientIndicationBottomPadding = ambientIndicationBottomPadding;
- mLockIconViewController.setAmbientIndicationBottomPadding(
- mAmbientIndicationBottomPadding);
updateMaxDisplayedNotifications(true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 31a432e..c300b11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.EventLog;
@@ -52,6 +53,7 @@
private static final boolean DEBUG = StatusBar.DEBUG;
private static final boolean DEBUG_GESTURES = false;
private final CommandQueue mCommandQueue;
+ private final StatusBarContentInsetsProvider mContentInsetsProvider;
StatusBar mBar;
@@ -85,11 +87,10 @@
private int mCutoutSideNudge = 0;
private boolean mHeadsUpVisible;
- private int mRoundedCornerPadding = 0;
-
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
mCommandQueue = Dependency.get(CommandQueue.class);
+ mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
}
public void setBar(StatusBar bar) {
@@ -305,8 +306,6 @@
public void updateResources() {
mCutoutSideNudge = getResources().getDimensionPixelSize(
R.dimen.display_cutout_margin_consumption);
- mRoundedCornerPadding = getResources().getDimensionPixelSize(
- R.dimen.rounded_corner_content_padding);
updateStatusBarHeight();
}
@@ -341,8 +340,7 @@
private void updateLayoutForCutout() {
updateStatusBarHeight();
updateCutoutLocation(StatusBarWindowView.cornerCutoutMargins(mDisplayCutout, getDisplay()));
- updateSafeInsets(StatusBarWindowView.statusBarCornerCutoutMargins(mDisplayCutout,
- getDisplay(), mRotationOrientation, mStatusBarHeight));
+ updateSafeInsets();
}
private void updateCutoutLocation(Pair<Integer, Integer> cornerCutoutMargins) {
@@ -370,15 +368,18 @@
lp.height = bounds.height();
}
- private void updateSafeInsets(Pair<Integer, Integer> cornerCutoutMargins) {
- // Depending on our rotation, we may have to work around a cutout in the middle of the view,
- // or letterboxing from the right or left sides.
+ private void updateSafeInsets() {
+ Rect contentRect = mContentInsetsProvider
+ .getStatusBarContentInsetsForRotation(RotationUtils.getExactRotation(getContext()));
- Pair<Integer, Integer> padding =
- StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
- mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding);
+ Point size = new Point();
+ getDisplay().getRealSize(size);
- setPadding(padding.first, getPaddingTop(), padding.second, getPaddingBottom());
+ setPadding(
+ contentRect.left,
+ getPaddingTop(),
+ size.x - contentRect.right,
+ getPaddingBottom());
}
public void setHeadsUpVisible(boolean headsUpVisible) {
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 63390f9..742eae3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -441,6 +441,7 @@
private final OngoingCallController mOngoingCallController;
private final SystemStatusAnimationScheduler mAnimationScheduler;
private final StatusBarLocationPublisher mStatusBarLocationPublisher;
+ private final StatusBarIconController mStatusBarIconController;
// expanded notifications
// the sliding/resizing panel within the notification window
@@ -803,6 +804,7 @@
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
+ StatusBarIconController statusBarIconController,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@@ -889,6 +891,7 @@
mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler;
mStatusBarLocationPublisher = locationPublisher;
+ mStatusBarIconController = statusBarIconController;
mFeatureFlags = featureFlags;
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
@@ -1190,7 +1193,14 @@
mAnimationScheduler,
mStatusBarLocationPublisher,
mNotificationIconAreaController,
- mFeatureFlags),
+ mFeatureFlags,
+ mStatusBarIconController,
+ mKeyguardStateController,
+ mNetworkController,
+ mStatusBarStateController,
+ this,
+ mCommandQueue
+ ),
CollapsedStatusBarFragment.TAG)
.commit();
@@ -2737,6 +2747,11 @@
mScrimController.dump(fd, pw, args);
}
+ if (mLightRevealScrim != null) {
+ pw.println(
+ "mLightRevealScrim.getRevealAmount(): " + mLightRevealScrim.getRevealAmount());
+ }
+
if (mStatusBarKeyguardViewManager != null) {
mStatusBarKeyguardViewManager.dump(pw);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
index edcf261..fe1f63a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.content.res.Resources
import android.graphics.Rect
+import android.util.Log
import android.util.Pair
import android.view.DisplayCutout
import android.view.View.LAYOUT_DIRECTION_RTL
@@ -155,13 +156,30 @@
val dc = context.display.cutout
val currentRotation = RotationUtils.getExactRotation(context)
+ val isRtl = rotatedResources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL
+ val roundedCornerPadding = rotatedResources
+ .getDimensionPixelSize(R.dimen.rounded_corner_content_padding)
+ val minDotWidth = rotatedResources
+ .getDimensionPixelSize(R.dimen.ongoing_appops_dot_min_padding)
+
+ val minLeft: Int
+ val minRight: Int
+ if (isRtl) {
+ minLeft = max(minDotWidth, roundedCornerPadding)
+ minRight = roundedCornerPadding
+ } else {
+ minLeft = roundedCornerPadding
+ minRight = max(minDotWidth, roundedCornerPadding)
+ }
+
return calculateInsetsForRotationWithRotatedResources(
currentRotation,
targetRotation,
dc,
windowManager.maximumWindowMetrics,
rotatedResources.getDimensionPixelSize(R.dimen.status_bar_height),
- rotatedResources.getDimensionPixelSize(R.dimen.rounded_corner_content_padding))
+ minLeft,
+ minRight)
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
@@ -212,9 +230,12 @@
* Calculates the exact left and right positions for the status bar contents for the given
* rotation
*
- * @param rot rotation for which to query the margins
- * @param context systemui context
- * @param rotatedResources resources constructed with the proper orientation set
+ * @param currentRotation current device rotation
+ * @param targetRotation rotation for which to calculate the status bar content rect
+ * @param displayCutout [DisplayCutout] for the curren display. possibly null
+ * @param windowMetrics [WindowMetrics] for the current window
+ * @param statusBarHeight height of the status bar for the target rotation
+ * @param roundedCornerPadding from rounded_corner_content_padding
*
* @see [RotationUtils#getResourcesForRotation]
*/
@@ -224,7 +245,8 @@
displayCutout: DisplayCutout?,
windowMetrics: WindowMetrics,
statusBarHeight: Int,
- roundedCornerPadding: Int
+ minLeft: Int,
+ minRight: Int
): Rect {
/*
TODO: Check if this is ever used for devices with no rounded corners
@@ -242,7 +264,8 @@
rotZeroBounds.bottom,
currentBounds.width(),
currentBounds.height(),
- roundedCornerPadding,
+ minLeft,
+ minRight,
targetRotation,
currentRotation)
@@ -256,7 +279,10 @@
* @param sbHeight appropriate status bar height for this rotation
* @param width display width calculated for ROTATION_NONE
* @param height display height calculated for ROTATION_NONE
- * @param roundedCornerPadding rounded_corner_content_padding dimension
+ * @param cWidth display width in our current rotation
+ * @param cHeight display height in our current rotation
+ * @param minLeft the minimum padding to enforce on the left
+ * @param minRight the minimum padding to enforce on the right
* @param targetRotation the rotation for which to calculate margins
* @param currentRotation the rotation from which the display cutout was generated
*
@@ -270,7 +296,8 @@
height: Int,
cWidth: Int,
cHeight: Int,
- roundedCornerPadding: Int,
+ minLeft: Int,
+ minRight: Int,
@Rotation targetRotation: Int,
@Rotation currentRotation: Int
): Rect {
@@ -279,9 +306,9 @@
val cutoutRects = dc?.boundingRects
if (cutoutRects == null || cutoutRects.isEmpty()) {
- return Rect(roundedCornerPadding,
+ return Rect(minLeft,
0,
- logicalDisplayWidth - roundedCornerPadding,
+ logicalDisplayWidth - minRight,
sbHeight)
}
@@ -294,8 +321,8 @@
// Size of the status bar window for the given rotation relative to our exact rotation
val sbRect = sbRect(relativeRotation, sbHeight, Pair(cWidth, cHeight))
- var leftMargin = roundedCornerPadding
- var rightMargin = roundedCornerPadding
+ var leftMargin = minLeft
+ var rightMargin = minRight
for (cutoutRect in cutoutRects) {
// There is at most one non-functional area per short edge of the device. So if the status
// bar doesn't share a short edge with the cutout, we can ignore its insets because there
@@ -306,11 +333,11 @@
if (cutoutRect.touchesLeftEdge(relativeRotation, cWidth, cHeight)) {
- val l = max(roundedCornerPadding, cutoutRect.logicalWidth(relativeRotation))
+ val l = max(minLeft, cutoutRect.logicalWidth(relativeRotation))
leftMargin = max(l, leftMargin)
} else if (cutoutRect.touchesRightEdge(relativeRotation, cWidth, cHeight)) {
val logicalWidth = cutoutRect.logicalWidth(relativeRotation)
- rightMargin = max(roundedCornerPadding, logicalWidth)
+ rightMargin = max(minRight, logicalWidth)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index aa58527..47deb1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -24,12 +24,14 @@
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.util.Log;
import android.util.Slog;
+import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
@@ -394,8 +396,10 @@
}
@Override
- public void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded) {
+ public void onExpandClicked(NotificationEntry clickedEntry, View clickedView,
+ boolean nowExpanded) {
mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
+ mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), clickedView, "NOTIFICATION_CLICK");
if (nowExpanded) {
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 716d1db..b6e8bd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -89,6 +89,7 @@
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
@@ -216,6 +217,7 @@
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
+ StatusBarIconController statusBarIconController,
LockscreenShadeTransitionController transitionController,
FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@@ -305,6 +307,7 @@
ongoingCallController,
animationScheduler,
locationPublisher,
+ statusBarIconController,
transitionController,
featureFlags,
keyguardUnlockAnimationController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
index c2bd87c..3a05ec7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -30,6 +30,9 @@
/** Alert controller of a change in between light and dark themes. */
void notifyThemeChanged();
+ /** Query the current configuration's layout direction */
+ boolean isLayoutRtl();
+
interface ConfigurationListener {
default void onConfigChanged(Configuration newConfig) {}
default void onDensityOrFontScaleChanged() {}
@@ -38,5 +41,6 @@
default void onUiModeChanged() {}
default void onThemeChanged() {}
default void onLocaleListChanged() {}
+ default void onLayoutDirectionChanged(boolean isLayoutRtl) {}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index 9640423..bc53074 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -39,10 +39,14 @@
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
@@ -54,10 +58,17 @@
private NotificationIconAreaController mMockNotificationAreaController;
private View mNotificationAreaInner;
- private StatusBarStateController mStatusBarStateController;
private OngoingCallController mOngoingCallController;
private SystemStatusAnimationScheduler mAnimationScheduler;
private StatusBarLocationPublisher mLocationPublisher;
+ // Set in instantiate()
+ private StatusBarIconController mStatusBarIconController;
+ private NetworkController mNetworkController;
+ private StatusBarStateController mStatusBarStateController;
+ private KeyguardStateController mKeyguardStateController;
+
+ private final StatusBar mStatusBar = mock(StatusBar.class);
+ private final CommandQueue mCommandQueue = mock(CommandQueue.class);
public CollapsedStatusBarFragmentTest() {
super(CollapsedStatusBarFragment.class);
@@ -65,12 +76,8 @@
@Before
public void setup() {
- StatusBar statusBar = mock(StatusBar.class);
- mDependency.injectTestDependency(StatusBar.class, statusBar);
- mStatusBarStateController = mDependency
- .injectMockDependency(StatusBarStateController.class);
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
- when(statusBar.getPanelController()).thenReturn(
+ when(mStatusBar.getPanelController()).thenReturn(
mock(NotificationPanelViewController.class));
}
@@ -202,6 +209,7 @@
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
}
+ @Ignore("b/192618546")
@Test
public void testOnDozingChanged() throws Exception {
mFragments.dispatchResume();
@@ -225,13 +233,23 @@
mOngoingCallController = mock(OngoingCallController.class);
mAnimationScheduler = mock(SystemStatusAnimationScheduler.class);
mLocationPublisher = mock(StatusBarLocationPublisher.class);
+ mStatusBarIconController = mock(StatusBarIconController.class);
+ mNetworkController = mock(NetworkController.class);
+ mStatusBarStateController = mock(StatusBarStateController.class);
+ mKeyguardStateController = mock(KeyguardStateController.class);
setUpNotificationIconAreaController();
return new CollapsedStatusBarFragment(
mOngoingCallController,
mAnimationScheduler,
mLocationPublisher,
mMockNotificationAreaController,
- mock(FeatureFlags.class));
+ mock(FeatureFlags.class),
+ mStatusBarIconController,
+ mKeyguardStateController,
+ mNetworkController,
+ mStatusBarStateController,
+ mStatusBar,
+ mCommandQueue);
}
private void setUpNotificationIconAreaController() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
index 4796cd7..10eb71f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
@@ -47,7 +47,8 @@
@Test
fun testGetBoundingRectForPrivacyChipForRotation_noCutout() {
val screenBounds = Rect(0, 0, 1080, 2160)
- val roundedCornerPadding = 20
+ val minLeftPadding = 20
+ val minRightPadding = 20
val sbHeightPortrait = 100
val sbHeightLandscape = 60
val currentRotation = ROTATION_NONE
@@ -64,7 +65,8 @@
null,
windowMetrics,
sbHeightPortrait,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
var chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl)
/* 1080 - 20 (rounded corner) - 30 (chip),
@@ -92,7 +94,8 @@
dc,
windowMetrics,
sbHeightLandscape,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl)
/* 2160 - 20 (rounded corner) - 30 (chip),
@@ -118,7 +121,8 @@
// GIVEN a device in portrait mode with width < height and a display cutout in the top-left
val screenBounds = Rect(0, 0, 1080, 2160)
val dcBounds = Rect(0, 0, 100, 100)
- val roundedCornerPadding = 20
+ val minLeftPadding = 20
+ val minRightPadding = 20
val sbHeightPortrait = 100
val sbHeightLandscape = 60
val currentRotation = ROTATION_NONE
@@ -131,7 +135,7 @@
var targetRotation = ROTATION_NONE
var expectedBounds = Rect(dcBounds.right,
0,
- screenBounds.right - roundedCornerPadding,
+ screenBounds.right - minRightPadding,
sbHeightPortrait)
var bounds = calculateInsetsForRotationWithRotatedResources(
@@ -140,14 +144,15 @@
dc,
windowMetrics,
sbHeightPortrait,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_LANDSCAPE
expectedBounds = Rect(dcBounds.height(),
0,
- screenBounds.height() - roundedCornerPadding,
+ screenBounds.height() - minRightPadding,
sbHeightLandscape)
bounds = calculateInsetsForRotationWithRotatedResources(
@@ -156,16 +161,17 @@
dc,
windowMetrics,
sbHeightLandscape,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
// THEN the side that does NOT share a short side with the display cutout ignores the
// display cutout bounds
targetRotation = ROTATION_UPSIDE_DOWN
- expectedBounds = Rect(roundedCornerPadding,
+ expectedBounds = Rect(minLeftPadding,
0,
- screenBounds.width() - roundedCornerPadding,
+ screenBounds.width() - minRightPadding,
sbHeightPortrait)
bounds = calculateInsetsForRotationWithRotatedResources(
@@ -174,13 +180,14 @@
dc,
windowMetrics,
sbHeightPortrait,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
// Phone in portrait, seascape (rot_270) bounds
targetRotation = ROTATION_SEASCAPE
- expectedBounds = Rect(roundedCornerPadding,
+ expectedBounds = Rect(minLeftPadding,
0,
screenBounds.height() - dcBounds.height(),
sbHeightLandscape)
@@ -191,7 +198,8 @@
dc,
windowMetrics,
sbHeightLandscape,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
}
@@ -205,7 +213,8 @@
val screenBounds = Rect(0, 0, 1080, 2160)
// cutout centered at the top
val dcBounds = Rect(490, 0, 590, 100)
- val roundedCornerPadding = 20
+ val minLeftPadding = 20
+ val minRightPadding = 20
val sbHeightPortrait = 100
val sbHeightLandscape = 60
val currentRotation = ROTATION_NONE
@@ -216,9 +225,9 @@
// THEN only the landscape/seascape rotations should avoid the cutout area because of the
// potential letterboxing
var targetRotation = ROTATION_NONE
- var expectedBounds = Rect(roundedCornerPadding,
+ var expectedBounds = Rect(minLeftPadding,
0,
- screenBounds.right - roundedCornerPadding,
+ screenBounds.right - minRightPadding,
sbHeightPortrait)
var bounds = calculateInsetsForRotationWithRotatedResources(
@@ -227,14 +236,15 @@
dc,
windowMetrics,
sbHeightPortrait,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_LANDSCAPE
expectedBounds = Rect(dcBounds.height(),
0,
- screenBounds.height() - roundedCornerPadding,
+ screenBounds.height() - minRightPadding,
sbHeightLandscape)
bounds = calculateInsetsForRotationWithRotatedResources(
@@ -243,14 +253,15 @@
dc,
windowMetrics,
sbHeightLandscape,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_UPSIDE_DOWN
- expectedBounds = Rect(roundedCornerPadding,
+ expectedBounds = Rect(minLeftPadding,
0,
- screenBounds.right - roundedCornerPadding,
+ screenBounds.right - minRightPadding,
sbHeightPortrait)
bounds = calculateInsetsForRotationWithRotatedResources(
@@ -259,12 +270,13 @@
dc,
windowMetrics,
sbHeightPortrait,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_SEASCAPE
- expectedBounds = Rect(roundedCornerPadding,
+ expectedBounds = Rect(minLeftPadding,
0,
screenBounds.height() - dcBounds.height(),
sbHeightLandscape)
@@ -275,7 +287,8 @@
dc,
windowMetrics,
sbHeightLandscape,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
}
@@ -285,7 +298,8 @@
// GIVEN device in portrait mode, where width < height and no cutout
val currentRotation = ROTATION_NONE
val screenBounds = Rect(0, 0, 1080, 2160)
- val roundedCornerPadding = 20
+ val minLeftPadding = 20
+ val minRightPadding = 20
val sbHeightPortrait = 100
val sbHeightLandscape = 60
@@ -293,9 +307,9 @@
// THEN content insets should only use rounded corner padding
var targetRotation = ROTATION_NONE
- var expectedBounds = Rect(roundedCornerPadding,
+ var expectedBounds = Rect(minLeftPadding,
0,
- screenBounds.right - roundedCornerPadding,
+ screenBounds.right - minRightPadding,
sbHeightPortrait)
var bounds = calculateInsetsForRotationWithRotatedResources(
@@ -304,13 +318,14 @@
null, /* no cutout */
windowMetrics,
sbHeightPortrait,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_LANDSCAPE
- expectedBounds = Rect(roundedCornerPadding,
+ expectedBounds = Rect(minLeftPadding,
0,
- screenBounds.height() - roundedCornerPadding,
+ screenBounds.height() - minRightPadding,
sbHeightLandscape)
bounds = calculateInsetsForRotationWithRotatedResources(
@@ -319,13 +334,14 @@
null, /* no cutout */
windowMetrics,
sbHeightLandscape,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_UPSIDE_DOWN
- expectedBounds = Rect(roundedCornerPadding,
+ expectedBounds = Rect(minLeftPadding,
0,
- screenBounds.width() - roundedCornerPadding,
+ screenBounds.width() - minRightPadding,
sbHeightPortrait)
bounds = calculateInsetsForRotationWithRotatedResources(
@@ -334,13 +350,14 @@
null, /* no cutout */
windowMetrics,
sbHeightPortrait,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
targetRotation = ROTATION_LANDSCAPE
- expectedBounds = Rect(roundedCornerPadding,
+ expectedBounds = Rect(minLeftPadding,
0,
- screenBounds.height() - roundedCornerPadding,
+ screenBounds.height() - minRightPadding,
sbHeightLandscape)
bounds = calculateInsetsForRotationWithRotatedResources(
@@ -349,7 +366,41 @@
null, /* no cutout */
windowMetrics,
sbHeightLandscape,
- roundedCornerPadding)
+ minLeftPadding,
+ minRightPadding)
+ assertRects(expectedBounds, bounds, currentRotation, targetRotation)
+ }
+
+ @Test
+ fun testMinLeftRight_accountsForDisplayCutout() {
+ // GIVEN a device in portrait mode with width < height and a display cutout in the top-left
+ val screenBounds = Rect(0, 0, 1080, 2160)
+ val dcBounds = Rect(0, 0, 100, 100)
+ val minLeftPadding = 80
+ val minRightPadding = 150
+ val sbHeightPortrait = 100
+ val sbHeightLandscape = 60
+ val currentRotation = ROTATION_NONE
+
+ `when`(windowMetrics.bounds).thenReturn(screenBounds)
+ `when`(dc.boundingRects).thenReturn(listOf(dcBounds))
+
+ // THEN left should be set to the display cutout width, and right should use the minRight
+ var targetRotation = ROTATION_NONE
+ var expectedBounds = Rect(dcBounds.right,
+ 0,
+ screenBounds.right - minRightPadding,
+ sbHeightPortrait)
+
+ var bounds = calculateInsetsForRotationWithRotatedResources(
+ currentRotation,
+ targetRotation,
+ dc,
+ windowMetrics,
+ sbHeightPortrait,
+ minLeftPadding,
+ minRightPadding)
+
assertRects(expectedBounds, bounds, currentRotation, targetRotation)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index f126ed0..2c2833a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -269,6 +269,7 @@
@Mock private OngoingCallController mOngoingCallController;
@Mock private SystemStatusAnimationScheduler mAnimationScheduler;
@Mock private StatusBarLocationPublisher mLocationPublisher;
+ @Mock private StatusBarIconController mIconController;
@Mock private LockscreenShadeTransitionController mLockscreenTransitionController;
@Mock private FeatureFlags mFeatureFlags;
@Mock private IWallpaperManager mWallpaperManager;
@@ -442,6 +443,7 @@
mOngoingCallController,
mAnimationScheduler,
mLocationPublisher,
+ mIconController,
mLockscreenTransitionController,
mFeatureFlags,
mKeyguardUnlockAnimationController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
index f5ccac3..516eb6e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
@@ -33,4 +33,9 @@
@Override
public void notifyThemeChanged() {
}
+
+ @Override
+ public boolean isLayoutRtl() {
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index abb8243..979a9ee 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -430,7 +430,13 @@
final ApplicationExitInfo info = new ApplicationExitInfo(raw);
final String[] packages = raw.getPackageList();
- final int uid = raw.getPackageUid();
+ int uid = raw.getRealUid();
+ if (UserHandle.isIsolated(uid)) {
+ Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
+ if (k != null) {
+ uid = k;
+ }
+ }
for (int i = 0; i < packages.length; i++) {
addExitInfoInnerLocked(packages[i], uid, info);
}
@@ -833,14 +839,14 @@
pw.println(prefix + "package: " + packageName);
int size = array.size();
for (int i = 0; i < size; i++) {
- pw.println(prefix + " Historical Process Exit for userId=" + array.keyAt(i));
+ pw.println(prefix + " Historical Process Exit for uid=" + array.keyAt(i));
array.valueAt(i).dumpLocked(pw, prefix + " ", sdf);
}
}
@GuardedBy("mLock")
- private void addExitInfoInnerLocked(String packageName, int userId, ApplicationExitInfo info) {
- AppExitInfoContainer container = mData.get(packageName, userId);
+ private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info) {
+ AppExitInfoContainer container = mData.get(packageName, uid);
if (container == null) {
container = new AppExitInfoContainer(mAppExitInfoHistoryListSize);
if (UserHandle.isIsolated(info.getRealUid())) {
@@ -851,7 +857,7 @@
} else {
container.mUid = info.getRealUid();
}
- mData.put(packageName, userId, container);
+ mData.put(packageName, uid, container);
}
container.addExitInfoLocked(info);
}
@@ -997,7 +1003,7 @@
info.setPackageList(app.getPackageList());
info.setReason(ApplicationExitInfo.REASON_UNKNOWN);
info.setStatus(0);
- info.setImportance(procStateToImportance(app.mState.getSetProcState()));
+ info.setImportance(procStateToImportance(app.mState.getReportedProcState()));
info.setPss(app.mProfile.getLastPss());
info.setRss(app.mProfile.getLastRss());
info.setTimestamp(timestamp);
diff --git a/services/core/java/com/android/server/am/PhantomProcessList.java b/services/core/java/com/android/server/am/PhantomProcessList.java
index 4f3438fe..ca31681 100644
--- a/services/core/java/com/android/server/am/PhantomProcessList.java
+++ b/services/core/java/com/android/server/am/PhantomProcessList.java
@@ -305,7 +305,7 @@
}
// Somehow our record doesn't match, remove it anyway
Slog.w(TAG, "Stale " + proc + ", removing");
- mPhantomProcesses.removeAt(index);
+ onPhantomProcessKilledLocked(proc);
} else {
// Is this one of the zombie processes we've known?
final int idx = mZombiePhantomProcesses.indexOfKey(pid);
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index 7520d88..dc6bcd8 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -1086,7 +1086,7 @@
mCurRawAdj = mSetRawAdj = mCurAdj = mSetAdj = mVerifiedAdj = ProcessList.INVALID_ADJ;
mCurCapability = mSetCapability = PROCESS_CAPABILITY_NONE;
mCurSchedGroup = mSetSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
- mCurProcState = mRepProcState = mCurRawProcState = mSetProcState = mAllowStartFgsState =
+ mCurProcState = mCurRawProcState = mSetProcState = mAllowStartFgsState =
PROCESS_STATE_NONEXISTENT;
}
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 f97cb8a..f732a14 100644
--- a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
@@ -268,11 +268,18 @@
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();
+ if (isUdfpsActivelyAuthing(udfps)) {
+ // 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 {
+ // UDFPS is not actively authenticating (finger not touching, already
+ // rejected, etc).
+ callback.sendHapticFeedback();
+ callback.handleLifecycleAfterAuth();
+ }
} else if (isCurrentUdfps(client)) {
// Face should either be running, or have already finished
SuccessfulAuth auth = popSuccessfulFaceAuthIfExists(currentTimeMillis);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1edede5..1108937 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -778,7 +778,7 @@
setUpAutoBrightness(mContext.getResources(), mHandler);
reloadReduceBrightColours();
mHbmController.resetHbmData(info.width, info.height, token,
- mDisplayDeviceConfig.getHighBrightnessModeData(), mBrightnessSetting);
+ mDisplayDeviceConfig.getHighBrightnessModeData());
}
private void sendUpdatePowerState() {
@@ -968,7 +968,6 @@
final boolean mustNotify;
final int previousPolicy;
boolean mustInitialize = false;
- boolean shouldSaveBrightnessInfo = true;
int brightnessAdjustmentFlags = 0;
mBrightnessReasonTemp.set(null);
synchronized (mLock) {
@@ -1099,7 +1098,6 @@
if (state == Display.STATE_OFF) {
brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
- shouldSaveBrightnessInfo = false;
}
// Always use the VR brightness when in the VR state.
@@ -1217,6 +1215,10 @@
brightnessAdjustmentFlags = 0;
}
} else {
+ // Any non-auto-brightness values such as override or temporary should still be subject
+ // to clamping so that they don't go beyond the current max as specified by HBM
+ // Controller.
+ brightnessState = clampScreenBrightness(brightnessState);
mAppliedAutoBrightness = false;
brightnessAdjustmentFlags = 0;
}
@@ -1224,9 +1226,8 @@
// Use default brightness when dozing unless overridden.
if ((Float.isNaN(brightnessState))
&& Display.isDozeState(state)) {
- brightnessState = mScreenBrightnessDozeConfig;
+ brightnessState = clampScreenBrightness(mScreenBrightnessDozeConfig);
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
- shouldSaveBrightnessInfo = false;
}
// Apply manual brightness.
@@ -1241,12 +1242,13 @@
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
}
- // Save out the brightness info now that the brightness state for this iteration has been
- // finalized and before we send out notifications about the brightness changing.
- if (shouldSaveBrightnessInfo) {
- saveBrightnessInfo(brightnessState);
-
- }
+ // The current brightness to use has been calculated at this point (minus the adjustments
+ // like low-power and dim), and HbmController should be notified so that it can accurately
+ // calculate HDR or HBM levels. We specifically do it here instead of having HbmController
+ // listen to the brightness setting because certain brightness sources (just as an app
+ // override) are not saved to the setting, but should be reflected in HBM
+ // calculations.
+ mHbmController.onBrightnessChanged(brightnessState);
if (updateScreenBrightnessSetting) {
// Tell the rest of the system about the new brightness in case we had to change it
@@ -1257,6 +1259,10 @@
putScreenBrightnessSetting(brightnessState, /* updateCurrent */ true);
}
+ // We save the brightness info *after* the brightness setting has been changed so that
+ // the brightness info reflects the latest value.
+ saveBrightnessInfo(getScreenBrightnessSetting());
+
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
@@ -1533,7 +1539,7 @@
mHandler.post(mOnBrightnessChangeRunnable);
// TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
mAutomaticBrightnessController.update();
- }, mContext, mBrightnessSetting);
+ }, mContext);
}
private void blockScreenOn() {
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index 645131c..2791f6a 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -37,7 +37,6 @@
import android.view.SurfaceControlHdrLayerInfoListener;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.display.BrightnessSetting.BrightnessSettingListener;
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
import com.android.server.display.DisplayManagerService.Clock;
@@ -70,7 +69,6 @@
private final Context mContext;
private final SettingsObserver mSettingsObserver;
private final Injector mInjector;
- private final BrightnessSettingListener mBrightnessSettingListener = this::onBrightnessChanged;
private HdrListener mHdrListener;
private HighBrightnessModeData mHbmData;
@@ -86,7 +84,6 @@
private boolean mIsBlockedByLowPowerMode = false;
private int mWidth;
private int mHeight;
- private BrightnessSetting mBrightnessSetting;
private float mAmbientLux;
/**
@@ -103,30 +100,30 @@
HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken,
float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData,
- Runnable hbmChangeCallback, Context context, BrightnessSetting brightnessSetting) {
+ Runnable hbmChangeCallback, Context context) {
this(new Injector(), handler, width, height, displayToken, brightnessMin, brightnessMax,
- hbmData, hbmChangeCallback, context, brightnessSetting);
+ hbmData, hbmChangeCallback, context);
}
@VisibleForTesting
HighBrightnessModeController(Injector injector, Handler handler, int width, int height,
IBinder displayToken, float brightnessMin, float brightnessMax,
HighBrightnessModeData hbmData, Runnable hbmChangeCallback,
- Context context, BrightnessSetting brightnessSetting) {
+ Context context) {
mInjector = injector;
mContext = context;
mClock = injector.getClock();
mHandler = handler;
+ mBrightness = brightnessMin;
mBrightnessMin = brightnessMin;
mBrightnessMax = brightnessMax;
- mBrightness = brightnessSetting.getBrightness();
mHbmChangeCallback = hbmChangeCallback;
mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mRecalcRunnable = this::recalculateTimeAllowance;
mHdrListener = new HdrListener();
- resetHbmData(width, height, displayToken, hbmData, brightnessSetting);
+ resetHbmData(width, height, displayToken, hbmData);
}
void setAutoBrightnessEnabled(boolean isEnabled) {
@@ -185,7 +182,6 @@
}
}
- @VisibleForTesting
void onBrightnessChanged(float brightness) {
if (!deviceSupportsHbm()) {
return;
@@ -224,12 +220,11 @@
mSettingsObserver.stopObserving();
}
- void resetHbmData(int width, int height, IBinder displayToken, HighBrightnessModeData hbmData,
- BrightnessSetting brightnessSetting) {
+ void resetHbmData(int width, int height, IBinder displayToken, HighBrightnessModeData hbmData) {
mWidth = width;
mHeight = height;
mHbmData = hbmData;
- resetBrightnessSetting(brightnessSetting);
+
unregisterHdrListener();
mSkinThermalStatusObserver.stopObserving();
mSettingsObserver.stopObserving();
@@ -261,9 +256,12 @@
pw.println(" mBrightness=" + mBrightness);
pw.println(" mCurrentMin=" + getCurrentBrightnessMin());
pw.println(" mCurrentMax=" + getCurrentBrightnessMax());
- pw.println(" mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode));
+ pw.println(" mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode)
+ + (mHbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
+ ? "(" + getHdrBrightnessValue() + ")" : ""));
pw.println(" mHbmData=" + mHbmData);
- pw.println(" mAmbientLux=" + mAmbientLux);
+ pw.println(" mAmbientLux=" + mAmbientLux
+ + (mIsAutoBrightnessEnabled ? "" : " (old/invalid)"));
pw.println(" mIsInAllowedAmbientRange=" + mIsInAllowedAmbientRange);
pw.println(" mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled);
pw.println(" mIsHdrLayerPresent=" + mIsHdrLayerPresent);
@@ -301,16 +299,6 @@
return event.startTimeMillis;
}
- private void resetBrightnessSetting(BrightnessSetting brightnessSetting) {
- if (mBrightnessSetting != null) {
- mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
- }
- mBrightnessSetting = brightnessSetting;
- if (mBrightnessSetting != null) {
- mBrightnessSetting.registerListener(mBrightnessSettingListener);
- }
- }
-
private boolean isCurrentlyAllowed() {
// Returns true if HBM is allowed (above the ambient lux threshold) and there's still
// time within the current window for additional HBM usage. We return false if there is an
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 00ef97d..5429484 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2252,12 +2252,29 @@
(params.installFlags & PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK)
== 0;
synchronized (mLock) {
- if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName)) {
+ if (checkApexUpdateAllowed && !isApexUpdateAllowed(mPackageName,
+ mInstallSource.installerPackageName)) {
onSessionValidationFailure(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
- "Update of APEX package " + mPackageName + " is not allowed");
+ "Update of APEX package " + mPackageName + " is not allowed for "
+ + mInstallSource.installerPackageName);
return;
}
}
+
+ if (!params.isStaged) {
+ // For non-staged APEX installs also check if there is a staged session that
+ // contains the same APEX. If that's the case, we should fail this session.
+ synchronized (mLock) {
+ int sessionId = mStagingManager.getSessionIdByPackageName(mPackageName);
+ if (sessionId != -1) {
+ onSessionValidationFailure(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
+ "Staged session " + sessionId + " already contains "
+ + mPackageName);
+ return;
+ }
+ }
+ }
}
if (params.isStaged) {
@@ -2798,9 +2815,23 @@
return sessionContains((s) -> !s.isApexSession());
}
- private boolean isApexUpdateAllowed(String apexPackageName) {
- return mPm.getModuleInfo(apexPackageName, 0) != null
- || SystemConfig.getInstance().getAllowedVendorApexes().contains(apexPackageName);
+ private boolean isApexUpdateAllowed(String apexPackageName, String installerPackageName) {
+ if (mPm.getModuleInfo(apexPackageName, 0) != null) {
+ final String modulesInstaller =
+ SystemConfig.getInstance().getModulesInstallerPackageName();
+ if (modulesInstaller == null) {
+ Slog.w(TAG, "No modules installer defined");
+ return false;
+ }
+ return modulesInstaller.equals(installerPackageName);
+ }
+ final String vendorApexInstaller =
+ SystemConfig.getInstance().getAllowedVendorApexes().get(apexPackageName);
+ if (vendorApexInstaller == null) {
+ Slog.w(TAG, apexPackageName + " is not allowed to be updated");
+ return false;
+ }
+ return vendorApexInstaller.equals(installerPackageName);
}
/**
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 4ac5be2..bdbcb27 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -777,6 +777,26 @@
}
}
+ /**
+ * Returns id of a committed and non-finalized stated session that contains same
+ * {@code packageName}, or {@code -1} if no sessions have this {@code packageName} staged.
+ */
+ int getSessionIdByPackageName(@NonNull String packageName) {
+ synchronized (mStagedSessions) {
+ for (int i = 0; i < mStagedSessions.size(); i++) {
+ StagedSession stagedSession = mStagedSessions.valueAt(i);
+ if (!stagedSession.isCommitted() || stagedSession.isDestroyed()
+ || stagedSession.isInTerminalState()) {
+ continue;
+ }
+ if (stagedSession.getPackageName().equals(packageName)) {
+ return stagedSession.sessionId();
+ }
+ }
+ }
+ return -1;
+ }
+
@VisibleForTesting
void createSession(@NonNull StagedSession sessionInfo) {
synchronized (mStagedSessions) {
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 0f6a718..494f496 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -933,9 +933,11 @@
// This will avoid any races with other operations that modify the ActivityRecord.
final TransitionInfoSnapshot infoSnapshot = new TransitionInfoSnapshot(info);
if (info.isInterestingToLoggerAndObserver()) {
+ final long timestamp = info.mTransitionStartTimeNs;
+ final long uptime = info.mTransitionDeviceUptimeMs;
+ final int transitionDelay = info.mCurrentTransitionDelayMs;
mLoggerHandler.post(() -> logAppTransition(
- info.mTransitionDeviceUptimeMs, info.mCurrentTransitionDelayMs,
- infoSnapshot, isHibernating));
+ timestamp, uptime, transitionDelay, infoSnapshot, isHibernating));
}
mLoggerHandler.post(() -> logAppDisplayed(infoSnapshot));
if (info.mPendingFullyDrawn != null) {
@@ -946,8 +948,8 @@
}
// This gets called on another thread without holding the activity manager lock.
- private void logAppTransition(long transitionDeviceUptimeMs, int currentTransitionDelayMs,
- TransitionInfoSnapshot info, boolean isHibernating) {
+ private void logAppTransition(long transitionStartTimeNs, long transitionDeviceUptimeMs,
+ int currentTransitionDelayMs, TransitionInfoSnapshot info, boolean isHibernating) {
final LogMaker builder = new LogMaker(APP_TRANSITION);
builder.setPackageName(info.packageName);
builder.setType(info.type);
@@ -998,7 +1000,7 @@
info.launchedActivityName,
info.launchedActivityLaunchedFromPackage,
isInstantApp,
- transitionDeviceUptimeMs,
+ 0 /* deprecated transitionDeviceUptimeMs */,
info.reason,
currentTransitionDelayMs,
info.startingWindowDelayMs,
@@ -1012,7 +1014,8 @@
isHibernating,
isIncremental,
isLoading,
- info.launchedActivityName.hashCode());
+ info.launchedActivityName.hashCode(),
+ TimeUnit.NANOSECONDS.toMillis(transitionStartTimeNs));
if (DEBUG_METRICS) {
Slog.i(TAG, String.format("APP_START_OCCURRED(%s, %s, %s, %s, %s)",
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b6e0d8d..a843c80 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2206,16 +2206,17 @@
ensureActivitiesVisible(null, 0, false /* preserveWindows */);
resumeFocusedTasksTopActivities();
- notifyActivityPipModeChanged(r);
+ notifyActivityPipModeChanged(r.getTask(), r);
}
/**
* Notifies when an activity enters or leaves PIP mode.
*
+ * @param task the task of {@param r}
* @param r indicates the activity currently in PIP, can be null to indicate no activity is
* currently in PIP mode.
*/
- void notifyActivityPipModeChanged(@Nullable ActivityRecord r) {
+ void notifyActivityPipModeChanged(@NonNull Task task, @Nullable ActivityRecord r) {
final boolean inPip = r != null;
if (inPip) {
mService.getTaskChangeNotificationController().notifyActivityPinned(r);
@@ -2223,6 +2224,9 @@
mService.getTaskChangeNotificationController().notifyActivityUnpinned();
}
mWindowManager.mPolicy.setPipVisibilityLw(inPip);
+ mWmService.mTransactionFactory.get()
+ .setTrustedOverlay(task.getSurfaceControl(), inPip)
+ .apply();
}
void executeAppTransitionForAllDisplay() {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 382a2b1..1f0d70a 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1437,7 +1437,7 @@
&& (newParent == null || !newParent.inPinnedWindowingMode())) {
// Notify if a task from the root pinned task is being removed
// (or moved depending on the mode).
- mRootWindowContainer.notifyActivityPipModeChanged(null);
+ mRootWindowContainer.notifyActivityPipModeChanged(this, null);
}
}
@@ -4167,7 +4167,9 @@
StartingWindowInfo getStartingWindowInfo(ActivityRecord activity) {
final StartingWindowInfo info = new StartingWindowInfo();
info.taskInfo = getTaskInfo();
-
+ info.targetActivityInfo = info.taskInfo.topActivityInfo != null
+ && activity.info != info.taskInfo.topActivityInfo
+ ? activity.info : null;
info.isKeyguardOccluded =
mAtmService.mKeyguardController.isDisplayOccluded(DEFAULT_DISPLAY);
@@ -5394,7 +5396,7 @@
: WINDOWING_MODE_FULLSCREEN;
}
if (currentMode == WINDOWING_MODE_PINNED) {
- mRootWindowContainer.notifyActivityPipModeChanged(null);
+ mRootWindowContainer.notifyActivityPipModeChanged(this, null);
}
if (likelyResolvedMode == WINDOWING_MODE_PINNED) {
// In the case that we've disabled affecting the SysUI flags as a part of seamlessly
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index e3e2708..fdf23d3 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -59,9 +59,7 @@
private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
- private static final long BG_PROCESS_PERIOD = DEBUG
- ? TimeUnit.MINUTES.toMillis(1)
- : TimeUnit.DAYS.toMillis(1);
+ private static final long BG_PROCESS_PERIOD = TimeUnit.DAYS.toMillis(1); // every 1 day.
private IProfCollectd mIProfcollect;
private static ProfcollectForwardingService sSelfService;
@@ -286,6 +284,11 @@
updateEngine.bind(new UpdateEngineCallback() {
@Override
public void onStatusUpdate(int status, float percent) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Received OTA status update, status: " + status + ", percent: "
+ + percent);
+ }
+
if (status == UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT) {
packProfileReport();
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index a254f68..16afef5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -3002,7 +3002,8 @@
final PendingIntent pi = getNewMockPendingIntent();
setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i, pi);
- verify(() -> MetricsHelper.pushAlarmScheduled(argThat(a -> a.matches(pi, null))));
+ verify(() -> MetricsHelper.pushAlarmScheduled(argThat(a -> a.matches(pi, null)),
+ anyInt()));
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index 803a0c1..26b5218 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -1003,7 +1003,7 @@
dummyPackageName, dummyClassName), "", definingUid));
}
app.mServices.setConnectionGroup(connectionGroup);
- app.mState.setSetProcState(procState);
+ app.mState.setReportedProcState(procState);
app.mProfile.setLastMemInfo(spy(new Debug.MemoryInfo()));
app.mProfile.setLastPss(pss);
app.mProfile.setLastRss(rss);
diff --git a/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java b/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
index 8336663..9926953 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java
@@ -50,6 +50,14 @@
AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo(
+ AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
assertThat(appSearchConfig.getCachedLimitConfigMaxDocumentSizeBytes()).isEqualTo(
AppSearchConfig.DEFAULT_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES);
assertThat(appSearchConfig.getCachedLimitConfigMaxDocumentCount()).isEqualTo(
@@ -100,6 +108,11 @@
final int samplingIntervalDefault = -1;
final int samplingIntervalPutDocumentStats = -2;
final int samplingIntervalBatchCallStats = -3;
+ final int samplingIntervalInitializeStats = -4;
+ final int samplingIntervalSearchStats = -5;
+ final int samplingIntervalGlobalSearchStats = -6;
+ final int samplingIntervalOptimizeStats = -7;
+
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
Integer.toString(samplingIntervalDefault),
@@ -112,6 +125,22 @@
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
Integer.toString(samplingIntervalBatchCallStats),
false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+ Integer.toString(samplingIntervalInitializeStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+ Integer.toString(samplingIntervalSearchStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+ Integer.toString(samplingIntervalGlobalSearchStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
+ Integer.toString(samplingIntervalOptimizeStats),
+ false);
AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
@@ -121,6 +150,14 @@
samplingIntervalPutDocumentStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
samplingIntervalBatchCallStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo(
+ samplingIntervalInitializeStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo(
+ samplingIntervalSearchStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo(
+ samplingIntervalGlobalSearchStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo(
+ samplingIntervalOptimizeStats);
}
@Test
@@ -128,6 +165,10 @@
int samplingIntervalDefault = -1;
int samplingIntervalPutDocumentStats = -2;
int samplingIntervalBatchCallStats = -3;
+ int samplingIntervalInitializeStats = -4;
+ int samplingIntervalSearchStats = -5;
+ int samplingIntervalGlobalSearchStats = -6;
+ int samplingIntervalOptimizeStats = -7;
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
Integer.toString(samplingIntervalDefault),
@@ -140,12 +181,32 @@
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
Integer.toString(samplingIntervalBatchCallStats),
false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+ Integer.toString(samplingIntervalInitializeStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+ Integer.toString(samplingIntervalSearchStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+ Integer.toString(samplingIntervalGlobalSearchStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
+ Integer.toString(samplingIntervalOptimizeStats),
+ false);
AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
// Overrides
samplingIntervalDefault = -4;
samplingIntervalPutDocumentStats = -5;
samplingIntervalBatchCallStats = -6;
+ samplingIntervalInitializeStats = -7;
+ samplingIntervalSearchStats = -8;
+ samplingIntervalGlobalSearchStats = -9;
+ samplingIntervalOptimizeStats = -10;
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
Integer.toString(samplingIntervalDefault),
@@ -158,6 +219,22 @@
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
Integer.toString(samplingIntervalBatchCallStats),
false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
+ Integer.toString(samplingIntervalInitializeStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
+ Integer.toString(samplingIntervalSearchStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
+ Integer.toString(samplingIntervalGlobalSearchStats),
+ false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
+ AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
+ Integer.toString(samplingIntervalOptimizeStats),
+ false);
assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo(
samplingIntervalDefault);
@@ -165,6 +242,14 @@
samplingIntervalPutDocumentStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
samplingIntervalBatchCallStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo(
+ samplingIntervalInitializeStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo(
+ samplingIntervalSearchStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo(
+ samplingIntervalGlobalSearchStats);
+ assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo(
+ samplingIntervalOptimizeStats);
}
/**
@@ -366,6 +451,18 @@
() -> appSearchConfig.getCachedSamplingIntervalForPutDocumentStats());
Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalForInitializeStats());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalForSearchStats());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
+ () -> appSearchConfig.getCachedSamplingIntervalForOptimizeStats());
+ Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
+ IllegalStateException.class,
() -> appSearchConfig.getCachedBytesOptimizeThreshold());
Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
IllegalStateException.class,
diff --git a/services/tests/mockingservicestests/src/com/android/server/appsearch/OWNERS b/services/tests/mockingservicestests/src/com/android/server/appsearch/OWNERS
new file mode 100644
index 0000000..24f6b0b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/appsearch/OWNERS
@@ -0,0 +1 @@
+include /apex/appsearch/OWNERS
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
index f91cb28..521be70 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -459,6 +459,66 @@
assertThat(apkSession.getErrorMessage()).isEqualTo("Another apex session failed");
}
+ @Test
+ public void getSessionIdByPackageName() throws Exception {
+ FakeStagedSession session = new FakeStagedSession(239);
+ session.setCommitted(true);
+ session.setSessionReady();
+ session.setPackageName("com.foo");
+
+ mStagingManager.createSession(session);
+ assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(239);
+ }
+
+ @Test
+ public void getSessionIdByPackageName_appliedSession_ignores() throws Exception {
+ FakeStagedSession session = new FakeStagedSession(37);
+ session.setCommitted(true);
+ session.setSessionApplied();
+ session.setPackageName("com.foo");
+
+ mStagingManager.createSession(session);
+ assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
+ }
+
+ @Test
+ public void getSessionIdByPackageName_failedSession_ignores() throws Exception {
+ FakeStagedSession session = new FakeStagedSession(73);
+ session.setCommitted(true);
+ session.setSessionFailed(1, "whatevs");
+ session.setPackageName("com.foo");
+
+ mStagingManager.createSession(session);
+ assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
+ }
+
+ @Test
+ public void getSessionIdByPackageName_destroyedSession_ignores() throws Exception {
+ FakeStagedSession session = new FakeStagedSession(23);
+ session.setCommitted(true);
+ session.setDestroyed(true);
+ session.setPackageName("com.foo");
+
+ mStagingManager.createSession(session);
+ assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
+ }
+
+ @Test
+ public void getSessionIdByPackageName_noSessions() throws Exception {
+ assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
+ }
+
+ @Test
+ public void getSessionIdByPackageName_noSessionHasThisPackage() throws Exception {
+ FakeStagedSession session = new FakeStagedSession(37);
+ session.setCommitted(true);
+ session.setSessionApplied();
+ session.setPackageName("com.foo");
+
+ mStagingManager.createSession(session);
+ assertThat(mStagingManager.getSessionIdByPackageName("com.bar")).isEqualTo(-1);
+ }
+
private StagingManager.StagedSession createSession(int sessionId, String packageName,
long committedMillis) {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index 5b067bc..f40a5ad 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -42,6 +42,7 @@
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
import com.android.server.appsearch.icing.proto.DocumentProto;
import com.android.server.appsearch.icing.proto.GetOptimizeInfoResultProto;
@@ -451,19 +452,26 @@
assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1);
// Increase mutation counter and stop before reach the threshold
- mAppSearchImpl.checkForOptimize(AppSearchImpl.CHECK_OPTIMIZE_INTERVAL - 1);
+ mAppSearchImpl.checkForOptimize(
+ AppSearchImpl.CHECK_OPTIMIZE_INTERVAL - 1, /*builder=*/ null);
// Verify the optimize() isn't triggered.
optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked();
assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1);
// Increase the counter and reach the threshold, optimize() should be triggered.
- mAppSearchImpl.checkForOptimize(/*mutateBatchSize=*/ 1);
+ OptimizeStats.Builder builder = new OptimizeStats.Builder();
+ mAppSearchImpl.checkForOptimize(/*mutateBatchSize=*/ 1, builder);
// Verify optimize() is triggered.
optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked();
assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(0);
assertThat(optimizeInfo.getEstimatedOptimizableBytes()).isEqualTo(0);
+
+ // Verify the stats have been set.
+ OptimizeStats oStats = builder.build();
+ assertThat(oStats.getOriginalDocumentCount()).isEqualTo(1);
+ assertThat(oStats.getDeletedDocumentCount()).isEqualTo(1);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
index 7bacbb6..7c97687 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
@@ -29,12 +29,14 @@
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
+import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
import com.android.server.appsearch.icing.proto.DeleteStatsProto;
import com.android.server.appsearch.icing.proto.DocumentProto;
import com.android.server.appsearch.icing.proto.InitializeStatsProto;
+import com.android.server.appsearch.icing.proto.OptimizeStatsProto;
import com.android.server.appsearch.icing.proto.PutDocumentStatsProto;
import com.android.server.appsearch.icing.proto.PutResultProto;
import com.android.server.appsearch.icing.proto.QueryStatsProto;
@@ -81,6 +83,7 @@
@Nullable InitializeStats mInitializeStats;
@Nullable SearchStats mSearchStats;
@Nullable RemoveStats mRemoveStats;
+ @Nullable OptimizeStats mOptimizeStats;
@Override
public void logStats(@NonNull CallStats stats) {
@@ -106,6 +109,11 @@
public void logStats(@NonNull RemoveStats stats) {
mRemoveStats = stats;
}
+
+ @Override
+ public void logStats(@NonNull OptimizeStats stats) {
+ mOptimizeStats = stats;
+ }
}
@Test
@@ -286,6 +294,48 @@
assertThat(rStats.getDeletedDocumentCount()).isEqualTo(nativeNumDocumentDeleted);
}
+ @Test
+ public void testAppSearchLoggerHelper_testCopyNativeStats_optimize() {
+ int nativeLatencyMillis = 1;
+ int nativeDocumentStoreOptimizeLatencyMillis = 2;
+ int nativeIndexRestorationLatencyMillis = 3;
+ int nativeNumOriginalDocuments = 4;
+ int nativeNumDeletedDocuments = 5;
+ int nativeNumExpiredDocuments = 6;
+ long nativeStorageSizeBeforeBytes = Integer.MAX_VALUE + 1;
+ long nativeStorageSizeAfterBytes = Integer.MAX_VALUE + 2;
+ long nativeTimeSinceLastOptimizeMillis = Integer.MAX_VALUE + 3;
+ OptimizeStatsProto optimizeStatsProto =
+ OptimizeStatsProto.newBuilder()
+ .setLatencyMs(nativeLatencyMillis)
+ .setDocumentStoreOptimizeLatencyMs(nativeDocumentStoreOptimizeLatencyMillis)
+ .setIndexRestorationLatencyMs(nativeIndexRestorationLatencyMillis)
+ .setNumOriginalDocuments(nativeNumOriginalDocuments)
+ .setNumDeletedDocuments(nativeNumDeletedDocuments)
+ .setNumExpiredDocuments(nativeNumExpiredDocuments)
+ .setStorageSizeBefore(nativeStorageSizeBeforeBytes)
+ .setStorageSizeAfter(nativeStorageSizeAfterBytes)
+ .setTimeSinceLastOptimizeMs(nativeTimeSinceLastOptimizeMillis)
+ .build();
+ OptimizeStats.Builder oBuilder = new OptimizeStats.Builder();
+
+ AppSearchLoggerHelper.copyNativeStats(optimizeStatsProto, oBuilder);
+
+ OptimizeStats oStats = oBuilder.build();
+ assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+ assertThat(oStats.getDocumentStoreOptimizeLatencyMillis())
+ .isEqualTo(nativeDocumentStoreOptimizeLatencyMillis);
+ assertThat(oStats.getIndexRestorationLatencyMillis())
+ .isEqualTo(nativeIndexRestorationLatencyMillis);
+ assertThat(oStats.getOriginalDocumentCount()).isEqualTo(nativeNumOriginalDocuments);
+ assertThat(oStats.getDeletedDocumentCount()).isEqualTo(nativeNumDeletedDocuments);
+ assertThat(oStats.getExpiredDocumentCount()).isEqualTo(nativeNumExpiredDocuments);
+ assertThat(oStats.getStorageSizeBeforeBytes()).isEqualTo(nativeStorageSizeBeforeBytes);
+ assertThat(oStats.getStorageSizeAfterBytes()).isEqualTo(nativeStorageSizeAfterBytes);
+ assertThat(oStats.getTimeSinceLastOptimizeMillis())
+ .isEqualTo(nativeTimeSinceLastOptimizeMillis);
+ }
+
//
// Testing actual logging
//
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
index 57d9941..c1dc0e4 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java
@@ -348,4 +348,49 @@
assertThat(rStats.getDeleteType()).isEqualTo(deleteType);
assertThat(rStats.getDeletedDocumentCount()).isEqualTo(documentDeletedCount);
}
+
+ @Test
+ public void testAppSearchStats_OptimizeStats() {
+ int nativeLatencyMillis = 1;
+ int nativeDocumentStoreOptimizeLatencyMillis = 2;
+ int nativeIndexRestorationLatencyMillis = 3;
+ int nativeNumOriginalDocuments = 4;
+ int nativeNumDeletedDocuments = 5;
+ int nativeNumExpiredDocuments = 6;
+ long nativeStorageSizeBeforeBytes = Integer.MAX_VALUE + 1;
+ long nativeStorageSizeAfterBytes = Integer.MAX_VALUE + 2;
+ long nativeTimeSinceLastOptimizeMillis = Integer.MAX_VALUE + 3;
+
+ final OptimizeStats oStats =
+ new OptimizeStats.Builder()
+ .setStatusCode(TEST_STATUS_CODE)
+ .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
+ .setNativeLatencyMillis(nativeLatencyMillis)
+ .setDocumentStoreOptimizeLatencyMillis(
+ nativeDocumentStoreOptimizeLatencyMillis)
+ .setIndexRestorationLatencyMillis(nativeIndexRestorationLatencyMillis)
+ .setOriginalDocumentCount(nativeNumOriginalDocuments)
+ .setDeletedDocumentCount(nativeNumDeletedDocuments)
+ .setExpiredDocumentCount(nativeNumExpiredDocuments)
+ .setStorageSizeBeforeBytes(nativeStorageSizeBeforeBytes)
+ .setStorageSizeAfterBytes(nativeStorageSizeAfterBytes)
+ .setTimeSinceLastOptimizeMillis(nativeTimeSinceLastOptimizeMillis)
+ .build();
+
+ assertThat(oStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE);
+ assertThat(oStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
+ assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+ assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+ assertThat(oStats.getDocumentStoreOptimizeLatencyMillis())
+ .isEqualTo(nativeDocumentStoreOptimizeLatencyMillis);
+ assertThat(oStats.getIndexRestorationLatencyMillis())
+ .isEqualTo(nativeIndexRestorationLatencyMillis);
+ assertThat(oStats.getOriginalDocumentCount()).isEqualTo(nativeNumOriginalDocuments);
+ assertThat(oStats.getDeletedDocumentCount()).isEqualTo(nativeNumDeletedDocuments);
+ assertThat(oStats.getExpiredDocumentCount()).isEqualTo(nativeNumExpiredDocuments);
+ assertThat(oStats.getStorageSizeBeforeBytes()).isEqualTo(nativeStorageSizeBeforeBytes);
+ assertThat(oStats.getStorageSizeAfterBytes()).isEqualTo(nativeStorageSizeAfterBytes);
+ assertThat(oStats.getTimeSinceLastOptimizeMillis())
+ .isEqualTo(nativeTimeSinceLastOptimizeMillis);
+ }
}
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 fb05825..a169ebd 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
@@ -259,6 +259,74 @@
}
@Test
+ public void testKeyguard_faceRejectedWhenUdfpsTouching_thenUdfpsRejected() {
+ 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.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+ when(udfpsClient.isKeyguard()).thenReturn(true);
+ when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+ mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, faceClient,
+ LockoutTracker.LOCKOUT_NONE, mCallback);
+ verify(mCallback, never()).sendHapticFeedback();
+ verify(mCallback).handleLifecycleAfterAuth();
+
+ // BiometricScheduler removes the face authentication client after rejection
+ mCoexCoordinator.removeAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+
+ // Then UDFPS rejected
+ CoexCoordinator.Callback udfpsCallback = mock(CoexCoordinator.Callback.class);
+ mCoexCoordinator.onAuthenticationRejected(1 /* currentTimeMillis */, udfpsClient,
+ LockoutTracker.LOCKOUT_NONE, udfpsCallback);
+ verify(udfpsCallback).sendHapticFeedback();
+ verify(udfpsCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+ verify(mCallback, never()).sendHapticFeedback();
+ }
+
+ @Test
+ public void testKeyguard_udfpsRejected_thenFaceRejected() {
+ 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.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
+ when(udfpsClient.isKeyguard()).thenReturn(true);
+ when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+ mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, udfpsClient,
+ LockoutTracker.LOCKOUT_NONE, mCallback);
+ // Client becomes paused, but finger does not necessarily lift, since we suppress the haptic
+ when(udfpsClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED_PAUSED);
+ verify(mCallback, never()).sendHapticFeedback();
+ verify(mCallback).handleLifecycleAfterAuth();
+
+ // Then face rejected. Note that scheduler leaves UDFPS in the CoexCoordinator since
+ // unlike face, its lifecycle becomes "paused" instead of "finished".
+ CoexCoordinator.Callback faceCallback = mock(CoexCoordinator.Callback.class);
+ mCoexCoordinator.onAuthenticationRejected(1 /* currentTimeMillis */, faceClient,
+ LockoutTracker.LOCKOUT_NONE, faceCallback);
+ verify(faceCallback).sendHapticFeedback();
+ verify(faceCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
+ verify(mCallback, never()).sendHapticFeedback();
+ }
+
+ @Test
public void testNonKeyguard_rejectAndNotLockedOut() {
mCoexCoordinator.reset();
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
index 1ad8850..cc3591c8 100644
--- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -92,7 +92,6 @@
@Mock IThermalService mThermalServiceMock;
@Mock Injector mInjectorMock;
- @Mock BrightnessSetting mBrightnessSetting;
@Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
@@ -123,7 +122,7 @@
initHandler(null);
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN,
- DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting);
+ DEFAULT_MAX, null, () -> {}, mContextSpy);
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
}
@@ -132,7 +131,7 @@
initHandler(null);
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN,
- DEFAULT_MAX, null, () -> {}, mContextSpy, mBrightnessSetting);
+ DEFAULT_MAX, null, () -> {}, mContextSpy);
hbmc.setAutoBrightnessEnabled(true);
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
@@ -464,7 +463,7 @@
initHandler(clock);
return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH,
DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {},
- mContextSpy, mBrightnessSetting);
+ mContextSpy);
}
private void initHandler(OffsettableClock clock) {
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index 9044b27..5eb21a5 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.testng.Assert.expectThrows;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
@@ -200,6 +201,46 @@
assertThat(mSysConfig.getWhitelistedStagedInstallers())
.containsExactly("com.android.package1");
+ assertThat(mSysConfig.getModulesInstallerPackageName()).isNull();
+ }
+
+ @Test
+ public void readPermissions_parsesStagedInstallerWhitelist_modulesInstaller()
+ throws IOException {
+ final String contents =
+ "<config>\n"
+ + " <whitelisted-staged-installer package=\"com.android.package1\" "
+ + " isModulesInstaller=\"true\" />\n"
+ + "</config>";
+ final File folder = createTempSubfolder("folder");
+ createTempFile(folder, "staged-installer-whitelist.xml", contents);
+
+ mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+
+ assertThat(mSysConfig.getWhitelistedStagedInstallers())
+ .containsExactly("com.android.package1");
+ assertThat(mSysConfig.getModulesInstallerPackageName())
+ .isEqualTo("com.android.package1");
+ }
+
+ @Test
+ public void readPermissions_parsesStagedInstallerWhitelist_multipleModulesInstallers()
+ throws IOException {
+ final String contents =
+ "<config>\n"
+ + " <whitelisted-staged-installer package=\"com.android.package1\" "
+ + " isModulesInstaller=\"true\" />\n"
+ + " <whitelisted-staged-installer package=\"com.android.package2\" "
+ + " isModulesInstaller=\"true\" />\n"
+ + "</config>";
+ final File folder = createTempSubfolder("folder");
+ createTempFile(folder, "staged-installer-whitelist.xml", contents);
+
+ IllegalStateException e = expectThrows(
+ IllegalStateException.class,
+ () -> mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0));
+
+ assertThat(e).hasMessageThat().contains("Multiple modules installers");
}
/**
@@ -230,14 +271,16 @@
throws IOException {
final String contents =
"<config>\n"
- + " <allowed-vendor-apex package=\"com.android.apex1\" />\n"
+ + " <allowed-vendor-apex package=\"com.android.apex1\" "
+ + "installerPackage=\"com.installer\" />\n"
+ "</config>";
final File folder = createTempSubfolder("folder");
createTempFile(folder, "vendor-apex-allowlist.xml", contents);
mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
- assertThat(mSysConfig.getAllowedVendorApexes()).containsExactly("com.android.apex1");
+ assertThat(mSysConfig.getAllowedVendorApexes())
+ .containsExactly("com.android.apex1", "com.installer");
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index b89539c..3a2190d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -265,4 +265,10 @@
public SurfaceControl.Transaction setColorSpace(SurfaceControl sc, ColorSpace colorSpace) {
return this;
}
+
+ @Override
+ public SurfaceControl.Transaction setTrustedOverlay(SurfaceControl sc,
+ boolean isTrustedOverlay) {
+ return this;
+ }
}
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 1aa0499..cac14a7 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -32,6 +32,7 @@
test_suites: ["general-tests"],
java_resources: [
":com.android.apex.apkrollback.test_v2",
+ ":StagedInstallTestApexV2",
":StagedInstallTestApexV2_WrongSha",
":test.rebootless_apex_v1",
":test.rebootless_apex_v2",
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 738e68e..4684f01 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -55,8 +55,11 @@
private static final TestApp TEST_APEX_WITH_APK_V2 = new TestApp("TestApexWithApkV2",
APK_IN_APEX_TESTAPEX_NAME, 2, /*isApex*/true, APK_IN_APEX_TESTAPEX_NAME + "_v2.apex");
private static final TestApp APEX_WRONG_SHA_V2 = new TestApp(
- "ApexWrongSha2", SHIM_APEX_PACKAGE_NAME, 2, /*isApex*/true,
+ "ApexWrongSha2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
"com.android.apex.cts.shim.v2_wrong_sha.apex");
+ private static final TestApp APEX_V2 = new TestApp(
+ "ApexV2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
+ "com.android.apex.cts.shim.v2.apex");
private File mTestStateFile = new File(
InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
@@ -237,6 +240,96 @@
}
@Test
+ public void testApexInstallerNotInAllowListCanNotInstall_staged() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+ // We don't really care which APEX we are trying to install here, since the session creation
+ // should fail immediately.
+ InstallUtils.commitExpectingFailure(
+ SecurityException.class,
+ "Installer not allowed to commit staged install",
+ Install.single(APEX_WRONG_SHA_V2).setBypassStangedInstallerCheck(false)
+ .setStaged());
+ }
+
+ @Test
+ public void testApexInstallerNotInAllowListCanNotInstall_nonStaged() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+ // We don't really care which APEX we are trying to install here, since the session creation
+ // should fail immediately.
+ InstallUtils.commitExpectingFailure(
+ SecurityException.class,
+ "Installer not allowed to commit non-staged APEX install",
+ Install.single(APEX_WRONG_SHA_V2).setBypassStangedInstallerCheck(false));
+ }
+
+ @Test
+ public void testApexNotInAllowListCanNotInstall_staged() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+ TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+ /* isApex= */ true, "test.rebootless_apex_v2.apex");
+ InstallUtils.commitExpectingFailure(
+ AssertionError.class,
+ "Update of APEX package test.apex.rebootless is not allowed "
+ + "for com.android.tests.stagedinstallinternal",
+ Install.single(apex).setBypassAllowedApexUpdateCheck(false).setStaged());
+ }
+
+ @Test
+ public void testApexNotInAllowListCanNotInstall_nonStaged() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+ TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+ /* isApex= */ true, "test.rebootless_apex_v2.apex");
+ InstallUtils.commitExpectingFailure(
+ AssertionError.class,
+ "Update of APEX package test.apex.rebootless is not allowed "
+ + "for com.android.tests.stagedinstallinternal",
+ Install.single(apex).setBypassAllowedApexUpdateCheck(false));
+ }
+
+ @Test
+ public void testVendorApexWrongInstaller_staged() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+ TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+ /* isApex= */ true, "test.rebootless_apex_v2.apex");
+ InstallUtils.commitExpectingFailure(
+ AssertionError.class,
+ "Update of APEX package test.apex.rebootless is not allowed "
+ + "for com.android.tests.stagedinstallinternal",
+ Install.single(apex).setBypassAllowedApexUpdateCheck(false).setStaged());
+ }
+
+ @Test
+ public void testVendorApexWrongInstaller_nonStaged() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+ TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+ /* isApex= */ true, "test.rebootless_apex_v2.apex");
+ InstallUtils.commitExpectingFailure(
+ AssertionError.class,
+ "Update of APEX package test.apex.rebootless is not allowed "
+ + "for com.android.tests.stagedinstallinternal",
+ Install.single(apex).setBypassAllowedApexUpdateCheck(false));
+ }
+
+ @Test
+ public void testVendorApexCorrectInstaller_staged() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+ TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+ /* isApex= */ true, "test.rebootless_apex_v2.apex");
+ int sessionId =
+ Install.single(apex).setBypassAllowedApexUpdateCheck(false).setStaged().commit();
+ InstallUtils.getPackageInstaller().abandonSession(sessionId);
+ }
+
+ @Test
+ public void testVendorApexCorrectInstaller_nonStaged() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(1);
+ TestApp apex = new TestApp("apex", "test.apex.rebootless", 2,
+ /* isApex= */ true, "test.rebootless_apex_v2.apex");
+ Install.single(apex).setBypassAllowedApexUpdateCheck(false).commit();
+ assertThat(InstallUtils.getInstalledVersion("test.apex.rebootless")).isEqualTo(2);
+ }
+
+ @Test
public void testRebootlessUpdates() throws Exception {
InstallUtils.dropShellPermissionIdentity();
InstallUtils.adoptShellPermissionIdentity(Manifest.permission.INSTALL_PACKAGE_UPDATES);
@@ -298,6 +391,19 @@
}
}
+ @Test
+ public void testRebootlessUpdate_hasStagedSessionWithSameApex_fails() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+
+ int sessionId = Install.single(APEX_V2).setStaged().commit();
+ assertSessionReady(sessionId);
+ InstallUtils.commitExpectingFailure(
+ AssertionError.class,
+ "Staged session " + sessionId + " already contains " + SHIM_APEX_PACKAGE_NAME,
+ Install.single(APEX_V2));
+
+ }
+
private static void assertSessionApplied(int sessionId) {
assertSessionState(sessionId, (session) -> {
assertThat(session.isStagedSessionApplied()).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 3bd3767..5021009 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -43,7 +43,9 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileWriter;
import java.util.List;
import java.util.stream.Collectors;
@@ -60,6 +62,9 @@
private static final String APK_A = "TestAppAv1.apk";
private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
+ private static final String TEST_VENDOR_APEX_ALLOW_LIST =
+ "/vendor/etc/sysconfig/test-vendor-apex-allow-list.xml";
+
private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
/**
@@ -87,7 +92,8 @@
"/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
"/data/apex/active/" + SHIM_APEX_PACKAGE_NAME + "*.apex",
"/system/apex/test.rebootless_apex_v1.apex",
- "/data/apex/active/test.apex.rebootless*.apex");
+ "/data/apex/active/test.apex.rebootless*.apex",
+ TEST_VENDOR_APEX_ALLOW_LIST);
}
@Before
@@ -134,7 +140,23 @@
}
getDevice().remountSystemWritable();
assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName));
- getDevice().reboot();
+ }
+
+ private void pushTestVendorApexAllowList(String installerPackageName) throws Exception {
+ if (!getDevice().isAdbRoot()) {
+ getDevice().enableAdbRoot();
+ }
+ getDevice().remountSystemWritable();
+ File file = File.createTempFile("test-vendor-apex-allow-list", ".xml");
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
+ final String fmt =
+ "<config>\n"
+ + " <allowed-vendor-apex package=\"test.apex.rebootless\" "
+ + " installerPackage=\"%s\" />\n"
+ + "</config>";
+ writer.write(String.format(fmt, installerPackageName));
+ }
+ getDevice().pushFile(file, TEST_VENDOR_APEX_ALLOW_LIST);
}
/**
@@ -144,6 +166,8 @@
@LargeTest
public void testDuplicateApkInApexShouldFail() throws Exception {
pushTestApex(APK_IN_APEX_TESTAPEX_NAME + "_v1.apex");
+ getDevice().reboot();
+
runPhase("testDuplicateApkInApexShouldFail_Commit");
getDevice().reboot();
runPhase("testDuplicateApkInApexShouldFail_Verify");
@@ -389,11 +413,71 @@
}
@Test
+ public void testApexInstallerNotInAllowListCanNotInstall() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+
+ runPhase("testApexInstallerNotInAllowListCanNotInstall_staged");
+ runPhase("testApexInstallerNotInAllowListCanNotInstall_nonStaged");
+ }
+
+ @Test
+ @LargeTest
+ public void testApexNotInAllowListCanNotInstall() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+
+ pushTestApex("test.rebootless_apex_v1.apex");
+ getDevice().reboot();
+
+ runPhase("testApexNotInAllowListCanNotInstall_staged");
+ runPhase("testApexNotInAllowListCanNotInstall_nonStaged");
+ }
+
+ @Test
+ @LargeTest
+ public void testVendorApexWrongInstaller() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+
+ pushTestVendorApexAllowList("com.wrong.installer");
+ pushTestApex("test.rebootless_apex_v1.apex");
+ getDevice().reboot();
+
+ runPhase("testVendorApexWrongInstaller_staged");
+ runPhase("testVendorApexWrongInstaller_nonStaged");
+ }
+
+ @Test
+ @LargeTest
+ public void testVendorApexCorrectInstaller() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+
+ pushTestVendorApexAllowList("com.android.tests.stagedinstallinternal");
+ pushTestApex("test.rebootless_apex_v1.apex");
+ getDevice().reboot();
+
+ runPhase("testVendorApexCorrectInstaller_staged");
+ runPhase("testVendorApexCorrectInstaller_nonStaged");
+ }
+
+ @Test
public void testRebootlessUpdates() throws Exception {
pushTestApex("test.rebootless_apex_v1.apex");
+ getDevice().reboot();
+
runPhase("testRebootlessUpdates");
}
+ @Test
+ public void testRebootlessUpdate_hasStagedSessionWithSameApex_fails() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+
+ runPhase("testRebootlessUpdate_hasStagedSessionWithSameApex_fails");
+ }
+
private List<String> getStagingDirectories() throws DeviceNotAvailableException {
String baseDir = "/data/app-staging";
try {