Merge "Import translations. DO NOT MERGE ANYWHERE" into sc-dev
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 77aa14c..2806974 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -37,6 +37,7 @@
import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -58,6 +59,7 @@
private static final String TAG = "AppSearchManagerService";
private PackageManagerInternal mPackageManagerInternal;
private ImplInstanceManager mImplInstanceManager;
+ private UserManager mUserManager;
// Cache of unlocked user ids so we don't have to query UserManager service each time. The
// "locked" suffix refers to the fact that access to the field should be locked; unrelated to
@@ -74,10 +76,11 @@
publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mImplInstanceManager = ImplInstanceManager.getInstance(getContext());
+ mUserManager = getContext().getSystemService(UserManager.class);
}
@Override
- public void onUserUnlocked(@NonNull TargetUser user) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
synchronized (mUnlockedUserIdsLocked) {
mUnlockedUserIdsLocked.add(user.getUserIdentifier());
}
@@ -509,7 +512,13 @@
private void verifyUserUnlocked(int callingUserId) {
synchronized (mUnlockedUserIdsLocked) {
- if (!mUnlockedUserIdsLocked.contains(callingUserId)) {
+ // First, check the local copy.
+ if (mUnlockedUserIdsLocked.contains(callingUserId)) {
+ return;
+ }
+ // If the local copy says the user is locked, check with UM for the actual state,
+ // since the user might just have been unlocked.
+ if (!mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(callingUserId))) {
throw new IllegalStateException(
"User " + callingUserId + " is locked or not running.");
}
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index 2ce85ee..8c06338 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -136,6 +136,23 @@
void restrictApp(@NonNull String packageName, int userId,
@SystemForcedReasons int restrictReason);
+ /**
+ * Put the specified app in the
+ * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED}
+ * bucket. If it has been used by the user recently, the restriction will delayed
+ * until an appropriate time. This should only be used in cases where
+ * {@link #restrictApp(String, int, int)} is not sufficient.
+ *
+ * @param mainReason The main reason for restricting the app. Must be either {@link
+ * android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_SYSTEM} or
+ * {@link android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_USER}.
+ * Calls providing any other value will be ignored.
+ * @param restrictReason The restrictReason for restricting the app. Should be one of the
+ * UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_* reasons.
+ */
+ void restrictApp(@NonNull String packageName, int userId, int mainReason,
+ @SystemForcedReasons int restrictReason);
+
void addActiveDeviceAdmin(String adminPkg, int userId);
void setActiveAdminApps(Set<String> adminPkgs, int userId);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 82f2f69..2b08ba5 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -793,6 +793,13 @@
mDebuggableApps.remove(pkgName);
}
}
+ } else if (Intent.ACTION_USER_ADDED.equals(action)) {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ synchronized (mLock) {
+ for (int c = 0; c < mControllers.size(); ++c) {
+ mControllers.get(c).onUserAddedLocked(userId);
+ }
+ }
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
if (DEBUG) {
@@ -1454,6 +1461,7 @@
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, filter, null, null);
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+ userFilter.addAction(Intent.ACTION_USER_ADDED);
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
try {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 784c63a..2b79969 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -28,6 +28,7 @@
import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -42,7 +43,9 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManagerInternal;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.Handler;
@@ -118,6 +121,10 @@
private static final String ALARM_TAG_CLEANUP = "*job.cleanup*";
private static final String ALARM_TAG_QUOTA_CHECK = "*job.quota_check*";
+ private static final int SYSTEM_APP_CHECK_FLAGS =
+ PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.GET_PERMISSIONS | PackageManager.MATCH_KNOWN_PACKAGES;
+
/**
* Standardize the output of userId-packageName combo.
*/
@@ -526,7 +533,9 @@
QcConstants.DEFAULT_EJ_LIMIT_RESTRICTED_MS
};
- private long mEjLimitSpecialAdditionMs = QcConstants.DEFAULT_EJ_LIMIT_SPECIAL_ADDITION_MS;
+ private long mEjLimitAdditionInstallerMs = QcConstants.DEFAULT_EJ_LIMIT_ADDITION_INSTALLER_MS;
+
+ private long mEjLimitAdditionSpecialMs = QcConstants.DEFAULT_EJ_LIMIT_ADDITION_SPECIAL_MS;
/**
* The period of time used to calculate expedited job sessions. Apps can only have expedited job
@@ -560,9 +569,11 @@
private long mEJGracePeriodTopAppMs = QcConstants.DEFAULT_EJ_GRACE_PERIOD_TOP_APP_MS;
- /** The package verifier app. */
- @Nullable
- private String mPackageVerifier;
+ /**
+ * List of system apps with the {@link android.Manifest.permission#INSTALL_PACKAGES} permission
+ * granted for each user.
+ */
+ private final SparseSetArray<String> mSystemInstallers = new SparseSetArray<>();
/** An app has reached its quota. The message should contain a {@link Package} object. */
@VisibleForTesting
@@ -627,11 +638,8 @@
@Override
public void onSystemServicesReady() {
- String[] pkgNames = LocalServices.getService(PackageManagerInternal.class)
- .getKnownPackageNames(
- PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM);
synchronized (mLock) {
- mPackageVerifier = ArrayUtils.firstOrNull(pkgNames);
+ cacheInstallerPackagesLocked(UserHandle.USER_SYSTEM);
}
}
@@ -731,6 +739,11 @@
}
@Override
+ public void onUserAddedLocked(int userId) {
+ cacheInstallerPackagesLocked(userId);
+ }
+
+ @Override
public void onUserRemovedLocked(int userId) {
mTrackedJobs.delete(userId);
mPkgTimers.delete(userId);
@@ -741,6 +754,7 @@
mExecutionStatsCache.delete(userId);
mEJStats.delete(userId);
mUidToPackageCache.clear();
+ mSystemInstallers.remove(userId);
}
/** Drop all historical stats and stop tracking any active sessions for the specified app. */
@@ -767,6 +781,22 @@
mEJStats.delete(userId, packageName);
}
+ private void cacheInstallerPackagesLocked(int userId) {
+ final List<PackageInfo> packages = mContext.getPackageManager()
+ .getInstalledPackagesAsUser(SYSTEM_APP_CHECK_FLAGS, userId);
+ for (int i = packages.size() - 1; i >= 0; --i) {
+ final PackageInfo pi = packages.get(i);
+ final ApplicationInfo ai = pi.applicationInfo;
+ final int idx = ArrayUtils.indexOf(
+ pi.requestedPermissions, Manifest.permission.INSTALL_PACKAGES);
+
+ if (idx >= 0 && ai != null && PackageManager.PERMISSION_GRANTED
+ == mContext.checkPermission(Manifest.permission.INSTALL_PACKAGES, -1, ai.uid)) {
+ mSystemInstallers.add(UserHandle.getUserId(ai.uid), pi.packageName);
+ }
+ }
+ }
+
private boolean isUidInForeground(int uid) {
if (UserHandle.isCore(uid)) {
return true;
@@ -962,7 +992,8 @@
if (quota.getStandbyBucketLocked() == NEVER_INDEX) {
return 0;
}
- final long limitMs = getEJLimitMsLocked(packageName, quota.getStandbyBucketLocked());
+ final long limitMs =
+ getEJLimitMsLocked(userId, packageName, quota.getStandbyBucketLocked());
long remainingMs = limitMs - quota.getTallyLocked();
// Stale sessions may still be factored into tally. Make sure they're removed.
@@ -1000,10 +1031,11 @@
return remainingMs - timer.getCurrentDuration(sElapsedRealtimeClock.millis());
}
- private long getEJLimitMsLocked(@NonNull final String packageName, final int standbyBucket) {
+ private long getEJLimitMsLocked(final int userId, @NonNull final String packageName,
+ final int standbyBucket) {
final long baseLimitMs = mEJLimitsMs[standbyBucket];
- if (packageName.equals(mPackageVerifier)) {
- return baseLimitMs + mEjLimitSpecialAdditionMs;
+ if (mSystemInstallers.contains(userId, packageName)) {
+ return baseLimitMs + mEjLimitAdditionInstallerMs;
}
return baseLimitMs;
}
@@ -1116,7 +1148,8 @@
final long nowElapsed = sElapsedRealtimeClock.millis();
ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
- final long limitMs = getEJLimitMsLocked(packageName, quota.getStandbyBucketLocked());
+ final long limitMs =
+ getEJLimitMsLocked(userId, packageName, quota.getStandbyBucketLocked());
final long startWindowElapsed = Math.max(0, nowElapsed - mEJLimitWindowSizeMs);
long remainingDeadSpaceMs = remainingExecutionTimeMs;
// Total time looked at where a session wouldn't be phasing out.
@@ -1743,7 +1776,8 @@
inRegularQuotaTimeElapsed = inQuotaTimeElapsed;
}
if (remainingEJQuota <= 0) {
- final long limitMs = getEJLimitMsLocked(packageName, standbyBucket) - mQuotaBufferMs;
+ final long limitMs =
+ getEJLimitMsLocked(userId, packageName, standbyBucket) - mQuotaBufferMs;
long sumMs = 0;
final Timer ejTimer = mEJPkgTimers.get(userId, packageName);
if (ejTimer != null && ejTimer.isActive()) {
@@ -3029,8 +3063,11 @@
static final String KEY_EJ_LIMIT_RESTRICTED_MS =
QC_CONSTANT_PREFIX + "ej_limit_restricted_ms";
@VisibleForTesting
- static final String KEY_EJ_LIMIT_SPECIAL_ADDITION_MS =
- QC_CONSTANT_PREFIX + "ej_limit_special_addition_ms";
+ static final String KEY_EJ_LIMIT_ADDITION_SPECIAL_MS =
+ QC_CONSTANT_PREFIX + "ej_limit_addition_special_ms";
+ @VisibleForTesting
+ static final String KEY_EJ_LIMIT_ADDITION_INSTALLER_MS =
+ QC_CONSTANT_PREFIX + "ej_limit_addition_installer_ms";
@VisibleForTesting
static final String KEY_EJ_WINDOW_SIZE_MS =
QC_CONSTANT_PREFIX + "ej_window_size_ms";
@@ -3098,7 +3135,8 @@
private static final long DEFAULT_EJ_LIMIT_FREQUENT_MS = 10 * MINUTE_IN_MILLIS;
private static final long DEFAULT_EJ_LIMIT_RARE_MS = DEFAULT_EJ_LIMIT_FREQUENT_MS;
private static final long DEFAULT_EJ_LIMIT_RESTRICTED_MS = 5 * MINUTE_IN_MILLIS;
- private static final long DEFAULT_EJ_LIMIT_SPECIAL_ADDITION_MS = 30 * MINUTE_IN_MILLIS;
+ private static final long DEFAULT_EJ_LIMIT_ADDITION_SPECIAL_MS = 15 * MINUTE_IN_MILLIS;
+ private static final long DEFAULT_EJ_LIMIT_ADDITION_INSTALLER_MS = 30 * MINUTE_IN_MILLIS;
private static final long DEFAULT_EJ_WINDOW_SIZE_MS = 24 * HOUR_IN_MILLIS;
private static final long DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS = 30 * SECOND_IN_MILLIS;
private static final long DEFAULT_EJ_REWARD_TOP_APP_MS = 10 * SECOND_IN_MILLIS;
@@ -3303,7 +3341,13 @@
/**
* How much additional EJ quota special, critical apps should get.
*/
- public long EJ_LIMIT_SPECIAL_ADDITION_MS = DEFAULT_EJ_LIMIT_SPECIAL_ADDITION_MS;
+ public long EJ_LIMIT_ADDITION_SPECIAL_MS = DEFAULT_EJ_LIMIT_ADDITION_SPECIAL_MS;
+
+ /**
+ * How much additional EJ quota system installers (with the INSTALL_PACKAGES permission)
+ * should get.
+ */
+ public long EJ_LIMIT_ADDITION_INSTALLER_MS = DEFAULT_EJ_LIMIT_ADDITION_INSTALLER_MS;
/**
* The period of time used to calculate expedited job sessions. Apps can only have expedited
@@ -3369,7 +3413,8 @@
case KEY_EJ_LIMIT_FREQUENT_MS:
case KEY_EJ_LIMIT_RARE_MS:
case KEY_EJ_LIMIT_RESTRICTED_MS:
- case KEY_EJ_LIMIT_SPECIAL_ADDITION_MS:
+ case KEY_EJ_LIMIT_ADDITION_SPECIAL_MS:
+ case KEY_EJ_LIMIT_ADDITION_INSTALLER_MS:
case KEY_EJ_WINDOW_SIZE_MS:
updateEJLimitConstantsLocked();
break;
@@ -3704,7 +3749,8 @@
DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_EJ_LIMIT_ACTIVE_MS, KEY_EJ_LIMIT_WORKING_MS,
KEY_EJ_LIMIT_FREQUENT_MS, KEY_EJ_LIMIT_RARE_MS,
- KEY_EJ_LIMIT_RESTRICTED_MS, KEY_EJ_LIMIT_SPECIAL_ADDITION_MS,
+ KEY_EJ_LIMIT_RESTRICTED_MS, KEY_EJ_LIMIT_ADDITION_SPECIAL_MS,
+ KEY_EJ_LIMIT_ADDITION_INSTALLER_MS,
KEY_EJ_WINDOW_SIZE_MS);
EJ_LIMIT_ACTIVE_MS = properties.getLong(
KEY_EJ_LIMIT_ACTIVE_MS, DEFAULT_EJ_LIMIT_ACTIVE_MS);
@@ -3716,8 +3762,10 @@
KEY_EJ_LIMIT_RARE_MS, DEFAULT_EJ_LIMIT_RARE_MS);
EJ_LIMIT_RESTRICTED_MS = properties.getLong(
KEY_EJ_LIMIT_RESTRICTED_MS, DEFAULT_EJ_LIMIT_RESTRICTED_MS);
- EJ_LIMIT_SPECIAL_ADDITION_MS = properties.getLong(
- KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, DEFAULT_EJ_LIMIT_SPECIAL_ADDITION_MS);
+ EJ_LIMIT_ADDITION_INSTALLER_MS = properties.getLong(
+ KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, DEFAULT_EJ_LIMIT_ADDITION_INSTALLER_MS);
+ EJ_LIMIT_ADDITION_SPECIAL_MS = properties.getLong(
+ KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, DEFAULT_EJ_LIMIT_ADDITION_SPECIAL_MS);
EJ_WINDOW_SIZE_MS = properties.getLong(
KEY_EJ_WINDOW_SIZE_MS, DEFAULT_EJ_WINDOW_SIZE_MS);
@@ -3763,11 +3811,17 @@
mEJLimitsMs[RESTRICTED_INDEX] = newRestrictedLimitMs;
mShouldReevaluateConstraints = true;
}
- // The addition must be in the range [0 minutes, window size - active limit].
- long newSpecialAdditionMs = Math.max(0,
- Math.min(newWindowSizeMs - newActiveLimitMs, EJ_LIMIT_SPECIAL_ADDITION_MS));
- if (mEjLimitSpecialAdditionMs != newSpecialAdditionMs) {
- mEjLimitSpecialAdditionMs = newSpecialAdditionMs;
+ // The additions must be in the range [0 minutes, window size - active limit].
+ long newAdditionInstallerMs = Math.max(0,
+ Math.min(newWindowSizeMs - newActiveLimitMs, EJ_LIMIT_ADDITION_INSTALLER_MS));
+ if (mEjLimitAdditionInstallerMs != newAdditionInstallerMs) {
+ mEjLimitAdditionInstallerMs = newAdditionInstallerMs;
+ mShouldReevaluateConstraints = true;
+ }
+ long newAdditionSpecialMs = Math.max(0,
+ Math.min(newWindowSizeMs - newActiveLimitMs, EJ_LIMIT_ADDITION_SPECIAL_MS));
+ if (mEjLimitAdditionSpecialMs != newAdditionSpecialMs) {
+ mEjLimitAdditionSpecialMs = newAdditionSpecialMs;
mShouldReevaluateConstraints = true;
}
}
@@ -3808,7 +3862,8 @@
pw.print(KEY_EJ_LIMIT_FREQUENT_MS, EJ_LIMIT_FREQUENT_MS).println();
pw.print(KEY_EJ_LIMIT_RARE_MS, EJ_LIMIT_RARE_MS).println();
pw.print(KEY_EJ_LIMIT_RESTRICTED_MS, EJ_LIMIT_RESTRICTED_MS).println();
- pw.print(KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, EJ_LIMIT_SPECIAL_ADDITION_MS).println();
+ pw.print(KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, EJ_LIMIT_ADDITION_INSTALLER_MS).println();
+ pw.print(KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, EJ_LIMIT_ADDITION_SPECIAL_MS).println();
pw.print(KEY_EJ_WINDOW_SIZE_MS, EJ_WINDOW_SIZE_MS).println();
pw.print(KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, EJ_TOP_APP_TIME_CHUNK_SIZE_MS).println();
pw.print(KEY_EJ_REWARD_TOP_APP_MS, EJ_REWARD_TOP_APP_MS).println();
@@ -3945,8 +4000,13 @@
}
@VisibleForTesting
- long getEjLimitSpecialAdditionMs() {
- return mEjLimitSpecialAdditionMs;
+ long getEjLimitAdditionInstallerMs() {
+ return mEjLimitAdditionInstallerMs;
+ }
+
+ @VisibleForTesting
+ long getEjLimitAdditionSpecialMs() {
+ return mEjLimitAdditionSpecialMs;
}
@VisibleForTesting
@@ -4067,6 +4127,12 @@
pw.decreaseIndent();
pw.println();
+ pw.println("Special apps:");
+ pw.increaseIndent();
+ pw.print("System installers", mSystemInstallers.toString());
+ pw.decreaseIndent();
+
+ pw.println();
mTrackedJobs.forEach((jobs) -> {
for (int j = 0; j < jobs.size(); j++) {
final JobStatus js = jobs.valueAt(j);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
index 56b3090..a33ba5b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
@@ -103,6 +103,10 @@
public void onAppRemovedLocked(String packageName, int uid) {
}
+ /** Called when a user is added to the device. */
+ public void onUserAddedLocked(int userId) {
+ }
+
/** Called when a user is removed from the device. */
public void onUserRemovedLocked(int userId) {
}
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 1a808c9..24f7b37 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -1343,13 +1343,24 @@
@Override
public void restrictApp(@NonNull String packageName, int userId,
@SystemForcedReasons int restrictReason) {
+ restrictApp(packageName, userId, REASON_MAIN_FORCED_BY_SYSTEM, restrictReason);
+ }
+
+ @Override
+ public void restrictApp(@NonNull String packageName, int userId, int mainReason,
+ @SystemForcedReasons int restrictReason) {
+ if (mainReason != REASON_MAIN_FORCED_BY_SYSTEM
+ && mainReason != REASON_MAIN_FORCED_BY_USER) {
+ Slog.e(TAG, "Tried to restrict app " + packageName + " for an unsupported reason");
+ return;
+ }
// If the package is not installed, don't allow the bucket to be set.
if (!mInjector.isPackageInstalled(packageName, 0, userId)) {
Slog.e(TAG, "Tried to restrict uninstalled app: " + packageName);
return;
}
- final int reason = REASON_MAIN_FORCED_BY_SYSTEM | (REASON_SUB_MASK & restrictReason);
+ final int reason = (REASON_MAIN_MASK & mainReason) | (REASON_SUB_MASK & restrictReason);
final long nowElapsed = mInjector.elapsedRealtime();
final int bucket = mAllowRestrictedBucket ? STANDBY_BUCKET_RESTRICTED : STANDBY_BUCKET_RARE;
setAppStandbyBucket(packageName, userId, bucket, reason, nowElapsed, false);
diff --git a/apex/media/framework/api/system-current.txt b/apex/media/framework/api/system-current.txt
index 1d912eb..ad68169 100644
--- a/apex/media/framework/api/system-current.txt
+++ b/apex/media/framework/api/system-current.txt
@@ -18,11 +18,9 @@
method @NonNull public android.net.Uri getSourceUri();
}
- public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver {
- ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver();
+ public static class MediaTranscodeManager.TranscodingRequest.VideoFormatResolver {
+ ctor public MediaTranscodeManager.TranscodingRequest.VideoFormatResolver(@NonNull android.media.ApplicationMediaCapabilities, @NonNull android.media.MediaFormat);
method @Nullable public android.media.MediaFormat resolveVideoFormat();
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setClientCapabilities(@NonNull android.media.ApplicationMediaCapabilities);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat);
method public boolean shouldTranscode();
}
@@ -34,7 +32,6 @@
method public int getSessionId();
method public int getStatus();
method public void setOnProgressUpdateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener);
- method public void setOnProgressUpdateListener(int, @NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener);
field public static final int ERROR_DROPPED_BY_SERVICE = 1; // 0x1
field public static final int ERROR_NONE = 0; // 0x0
field public static final int ERROR_SERVICE_DIED = 2; // 0x2
diff --git a/apex/media/framework/java/android/media/MediaTranscodeManager.java b/apex/media/framework/java/android/media/MediaTranscodeManager.java
index 79e0d58..7f4685e 100644
--- a/apex/media/framework/java/android/media/MediaTranscodeManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java
@@ -822,83 +822,102 @@
}
/**
- * Helper class for deciding if transcoding is needed, and if so, the track
+ * Abstract base class for all the format resolvers.
+ */
+ abstract static class MediaFormatResolver {
+ private @NonNull ApplicationMediaCapabilities mClientCaps;
+
+ /**
+ * Prevents public constructor access.
+ */
+ /* package private */ MediaFormatResolver() {
+ }
+
+ /**
+ * Constructs MediaFormatResolver object.
+ *
+ * @param clientCaps An ApplicationMediaCapabilities object containing the client's
+ * capabilities.
+ */
+ MediaFormatResolver(@NonNull ApplicationMediaCapabilities clientCaps) {
+ if (clientCaps == null) {
+ throw new IllegalArgumentException("Client capabilities must not be null");
+ }
+ mClientCaps = clientCaps;
+ }
+
+ /**
+ * Returns the client capabilities.
+ */
+ @NonNull
+ /* package */ ApplicationMediaCapabilities getClientCapabilities() {
+ return mClientCaps;
+ }
+
+ abstract boolean shouldTranscode();
+ }
+
+ /**
+ * VideoFormatResolver for deciding if video transcoding is needed, and if so, the track
* formats to use.
*/
- public static class MediaFormatResolver {
+ public static class VideoFormatResolver extends MediaFormatResolver {
private static final int BIT_RATE = 20000000; // 20Mbps
private MediaFormat mSrcVideoFormatHint;
private MediaFormat mSrcAudioFormatHint;
- private ApplicationMediaCapabilities mClientCaps;
/**
- * Sets the abilities of the client consuming the media. Must be called
- * before {@link #shouldTranscode()} or {@link #resolveVideoFormat()}.
+ * Constructs a new VideoFormatResolver object.
*
* @param clientCaps An ApplicationMediaCapabilities object containing the client's
* capabilities.
- * @return the same VideoFormatResolver instance.
+ * @param srcVideoFormatHint A MediaFormat object containing information about the
+ * source's video track format that could affect the
+ * transcoding decision. Such information could include video
+ * codec types, color spaces, whether special format info (eg.
+ * slow-motion markers) are present, etc.. If a particular
+ * information is not present, it will not be used to make the
+ * decision.
*/
- @NonNull
- public MediaFormatResolver setClientCapabilities(
- @NonNull ApplicationMediaCapabilities clientCaps) {
- mClientCaps = clientCaps;
- return this;
+ public VideoFormatResolver(@NonNull ApplicationMediaCapabilities clientCaps,
+ @NonNull MediaFormat srcVideoFormatHint) {
+ super(clientCaps);
+ mSrcVideoFormatHint = srcVideoFormatHint;
}
/**
- * Sets the video format hint about the source. Must be called before
- * {@link #shouldTranscode()} or {@link #resolveVideoFormat()}.
+ * Constructs a new VideoFormatResolver object.
*
- * @param format A MediaFormat object containing information about the source's
- * video track format that could affect the transcoding decision.
- * Such information could include video codec types, color spaces,
- * whether special format info (eg. slow-motion markers) are present,
- * etc.. If a particular information is not present, it will not be
- * used to make the decision.
- * @return the same MediaFormatResolver instance.
- */
- @NonNull
- public MediaFormatResolver setSourceVideoFormatHint(@NonNull MediaFormat format) {
- mSrcVideoFormatHint = format;
- return this;
- }
-
- /**
- * Sets the audio format hint about the source.
- *
- * @param format A MediaFormat object containing information about the source's
- * audio track format that could affect the transcoding decision.
- * @return the same MediaFormatResolver instance.
+ * @param clientCaps An ApplicationMediaCapabilities object containing the client's
+ * capabilities.
+ * @param srcVideoFormatHint A MediaFormat object containing information about the
+ * source's video track format that could affect the
+ * transcoding decision. Such information could include video
+ * codec types, color spaces, whether special format info (eg.
+ * slow-motion markers) are present, etc.. If a particular
+ * information is not present, it will not be used to make the
+ * decision.
+ * @param srcAudioFormatHint A MediaFormat object containing information about the
+ * source's audio track format that could affect the
+ * transcoding decision.
* @hide
*/
- @NonNull
- public MediaFormatResolver setSourceAudioFormatHint(@NonNull MediaFormat format) {
- mSrcAudioFormatHint = format;
- return this;
+ VideoFormatResolver(@NonNull ApplicationMediaCapabilities clientCaps,
+ @NonNull MediaFormat srcVideoFormatHint,
+ @NonNull MediaFormat srcAudioFormatHint) {
+ super(clientCaps);
+ mSrcVideoFormatHint = srcVideoFormatHint;
+ mSrcAudioFormatHint = srcAudioFormatHint;
}
/**
* Returns whether the source content should be transcoded.
*
* @return true if the source should be transcoded.
- * @throws UnsupportedOperationException
- * if {@link #setClientCapabilities(ApplicationMediaCapabilities)}
- * or {@link #setSourceVideoFormatHint(MediaFormat)} was not called.
*/
public boolean shouldTranscode() {
- if (mClientCaps == null) {
- throw new UnsupportedOperationException(
- "Client caps must be set!");
- }
- // Video src hint must be provided, audio src hint is not used right now.
- if (mSrcVideoFormatHint == null) {
- throw new UnsupportedOperationException(
- "Source video format hint must be set!");
- }
-
- boolean supportHevc = mClientCaps.isVideoMimeTypeSupported(
+ boolean supportHevc = getClientCapabilities().isVideoMimeTypeSupported(
MediaFormat.MIMETYPE_VIDEO_HEVC);
if (!supportHevc && MediaFormat.MIMETYPE_VIDEO_HEVC.equals(
mSrcVideoFormatHint.getString(MediaFormat.KEY_MIME))) {
@@ -910,13 +929,11 @@
/**
* Retrieves the video track format to be used on
- * {@link Builder#setVideoTrackFormat(MediaFormat)} for this configuration.
+ * {@link VideoTranscodingRequest.Builder#setVideoTrackFormat(MediaFormat)} for this
+ * configuration.
*
* @return the video track format to be used if transcoding should be performed,
* and null otherwise.
- * @throws UnsupportedOperationException
- * if {@link #setClientCapabilities(ApplicationMediaCapabilities)}
- * or {@link #setSourceVideoFormatHint(MediaFormat)} was not called.
*/
@Nullable
public MediaFormat resolveVideoFormat() {
@@ -1015,9 +1032,6 @@
*
* @return the audio track format to be used if transcoding should be performed, and
* null otherwise.
- * @throws UnsupportedOperationException
- * if {@link #setClientCapabilities(ApplicationMediaCapabilities)}
- * or {@link #setSourceVideoFormatHint(MediaFormat)} was not called.
* @hide
*/
@Nullable
@@ -1366,21 +1380,6 @@
public void setOnProgressUpdateListener(
@NonNull @CallbackExecutor Executor executor,
@Nullable OnProgressUpdateListener listener) {
- setOnProgressUpdateListener(
- 0 /* minProgressUpdateInterval */,
- executor, listener);
- }
-
- /**
- * Set a progress listener with specified progress update interval.
- * @param minProgressUpdateInterval The minimum interval between each progress update.
- * @param executor The executor on which listener will be invoked.
- * @param listener The progress listener.
- */
- public void setOnProgressUpdateListener(
- int minProgressUpdateInterval,
- @NonNull @CallbackExecutor Executor executor,
- @Nullable OnProgressUpdateListener listener) {
synchronized (mLock) {
Objects.requireNonNull(executor, "listenerExecutor must not be null");
Objects.requireNonNull(listener, "listener must not be null");
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index f5bee6c..260c8a4 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -258,7 +258,7 @@
public void runDisableAppDataIsolation() throws RemoteException {
if (!SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true)) {
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false)) {
throw new IllegalStateException("Storage app data isolation is not enabled.");
}
final String pkgName = nextArg();
diff --git a/core/api/current.txt b/core/api/current.txt
index 471f610..9775e08 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -330,7 +330,7 @@
field public static final int apiKey = 16843281; // 0x1010211
field public static final int appCategory = 16844101; // 0x1010545
field public static final int appComponentFactory = 16844154; // 0x101057a
- field public static final int attributionTags = 16844353; // 0x1010641
+ field public static final int attributionTags = 16844354; // 0x1010642
field public static final int author = 16843444; // 0x10102b4
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -508,7 +508,7 @@
field public static final int dashGap = 16843175; // 0x10101a7
field public static final int dashWidth = 16843174; // 0x10101a6
field public static final int data = 16842798; // 0x101002e
- field public static final int dataExtractionRules = 16844349; // 0x101063d
+ field public static final int dataExtractionRules = 16844350; // 0x101063e
field public static final int datePickerDialogTheme = 16843948; // 0x10104ac
field public static final int datePickerMode = 16843955; // 0x10104b3
field public static final int datePickerStyle = 16843612; // 0x101035c
@@ -530,8 +530,8 @@
field public static final int detailSocialSummary = 16843428; // 0x10102a4
field public static final int detailsElementBackground = 16843598; // 0x101034e
field public static final int dial = 16843010; // 0x1010102
- field public static final int dialTint = 16844341; // 0x1010635
- field public static final int dialTintMode = 16844342; // 0x1010636
+ field public static final int dialTint = 16844342; // 0x1010636
+ field public static final int dialTintMode = 16844343; // 0x1010637
field public static final int dialogCornerRadius = 16844145; // 0x1010571
field public static final int dialogIcon = 16843252; // 0x10101f4
field public static final int dialogLayout = 16843255; // 0x10101f7
@@ -729,14 +729,14 @@
field public static final int groupIndicator = 16843019; // 0x101010b
field public static final int gwpAsanMode = 16844310; // 0x1010616
field public static final int hand_hour = 16843011; // 0x1010103
- field public static final int hand_hourTint = 16844343; // 0x1010637
- field public static final int hand_hourTintMode = 16844344; // 0x1010638
+ field public static final int hand_hourTint = 16844344; // 0x1010638
+ field public static final int hand_hourTintMode = 16844345; // 0x1010639
field public static final int hand_minute = 16843012; // 0x1010104
- field public static final int hand_minuteTint = 16844345; // 0x1010639
- field public static final int hand_minuteTintMode = 16844346; // 0x101063a
+ field public static final int hand_minuteTint = 16844346; // 0x101063a
+ field public static final int hand_minuteTintMode = 16844347; // 0x101063b
field public static final int hand_second = 16844323; // 0x1010623
- field public static final int hand_secondTint = 16844347; // 0x101063b
- field public static final int hand_secondTintMode = 16844348; // 0x101063c
+ field public static final int hand_secondTint = 16844348; // 0x101063c
+ field public static final int hand_secondTintMode = 16844349; // 0x101063d
field public static final int handle = 16843354; // 0x101025a
field public static final int handleProfiling = 16842786; // 0x1010022
field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
@@ -820,7 +820,7 @@
field public static final int installLocation = 16843447; // 0x10102b7
field public static final int interactiveUiTimeout = 16844181; // 0x1010595
field public static final int interpolator = 16843073; // 0x1010141
- field public static final int isAccessibilityTool = 16844352; // 0x1010640
+ field public static final int isAccessibilityTool = 16844353; // 0x1010641
field public static final int isAlwaysSyncable = 16843571; // 0x1010333
field public static final int isAsciiCapable = 16843753; // 0x10103e9
field public static final int isAuxiliary = 16843647; // 0x101037f
@@ -972,8 +972,8 @@
field public static final int maxLines = 16843091; // 0x1010153
field public static final int maxLongVersionCode = 16844163; // 0x1010583
field public static final int maxRecents = 16843846; // 0x1010446
- field public static final int maxResizeHeight = 16844338; // 0x1010632
- field public static final int maxResizeWidth = 16844337; // 0x1010631
+ field public static final int maxResizeHeight = 16844339; // 0x1010633
+ field public static final int maxResizeWidth = 16844338; // 0x1010632
field public static final int maxRows = 16843059; // 0x1010133
field public static final int maxSdkVersion = 16843377; // 0x1010271
field public static final int maxWidth = 16843039; // 0x101011f
@@ -1076,7 +1076,7 @@
field public static final int panelTextAppearance = 16842850; // 0x1010062
field public static final int parentActivityName = 16843687; // 0x10103a7
field @Deprecated public static final int password = 16843100; // 0x101015c
- field public static final int passwordsActivity = 16844350; // 0x101063e
+ field public static final int passwordsActivity = 16844351; // 0x101063f
field public static final int path = 16842794; // 0x101002a
field public static final int pathAdvancedPattern = 16844320; // 0x1010620
field public static final int pathData = 16843781; // 0x1010405
@@ -1262,7 +1262,7 @@
field public static final int segmentedButtonStyle = 16843568; // 0x1010330
field public static final int selectAllOnFocus = 16843102; // 0x101015e
field public static final int selectable = 16843238; // 0x10101e6
- field public static final int selectableAsDefault = 16844351; // 0x101063f
+ field public static final int selectableAsDefault = 16844352; // 0x1010640
field public static final int selectableItemBackground = 16843534; // 0x101030e
field public static final int selectableItemBackgroundBorderless = 16843868; // 0x101045c
field @Deprecated public static final int selectedDateVerticalBar = 16843591; // 0x1010347
@@ -1312,7 +1312,7 @@
field public static final int spinnerMode = 16843505; // 0x10102f1
field public static final int spinnerStyle = 16842881; // 0x1010081
field public static final int spinnersShown = 16843595; // 0x101034b
- field public static final int splashScreenTheme = 16844336; // 0x1010630
+ field public static final int splashScreenTheme = 16844337; // 0x1010631
field public static final int splitMotionEvents = 16843503; // 0x10102ef
field public static final int splitName = 16844105; // 0x1010549
field public static final int splitTrack = 16843852; // 0x101044c
@@ -1395,7 +1395,7 @@
field public static final int supportsRtl = 16843695; // 0x10103af
field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
field public static final int supportsUploading = 16843419; // 0x101029b
- field public static final int suppressesSpellChecker = 16844354; // 0x1010642
+ field public static final int suppressesSpellChecker = 16844355; // 0x1010643
field public static final int switchMinWidth = 16843632; // 0x1010370
field public static final int switchPadding = 16843633; // 0x1010371
field public static final int switchPreferenceStyle = 16843629; // 0x101036d
@@ -1410,8 +1410,8 @@
field public static final int tabWidgetStyle = 16842883; // 0x1010083
field public static final int tag = 16842961; // 0x10100d1
field public static final int targetActivity = 16843266; // 0x1010202
- field public static final int targetCellHeight = 16844340; // 0x1010634
- field public static final int targetCellWidth = 16844339; // 0x1010633
+ field public static final int targetCellHeight = 16844341; // 0x1010635
+ field public static final int targetCellWidth = 16844340; // 0x1010634
field public static final int targetClass = 16842799; // 0x101002f
field @Deprecated public static final int targetDescriptions = 16843680; // 0x10103a0
field public static final int targetId = 16843740; // 0x10103dc
@@ -1581,6 +1581,7 @@
field public static final int useLevel = 16843167; // 0x101019f
field public static final int userVisible = 16843409; // 0x1010291
field public static final int usesCleartextTraffic = 16844012; // 0x10104ec
+ field public static final int usesPermissionFlags = 16844356; // 0x1010644
field public static final int value = 16842788; // 0x1010024
field public static final int valueFrom = 16843486; // 0x10102de
field public static final int valueTo = 16843487; // 0x10102df
@@ -1680,6 +1681,7 @@
field public static final int windowSplashScreenAnimationDuration = 16844334; // 0x101062e
field public static final int windowSplashScreenBackground = 16844332; // 0x101062c
field public static final int windowSplashScreenBrandingImage = 16844335; // 0x101062f
+ field public static final int windowSplashScreenIconBackgroundColor = 16844336; // 0x1010630
field @Deprecated public static final int windowSplashscreenContent = 16844132; // 0x1010564
field @Deprecated public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
@@ -6942,6 +6944,7 @@
method @Nullable public String onChoosePrivateKeyAlias(@NonNull android.content.Context, @NonNull android.content.Intent, int, @Nullable android.net.Uri, @Nullable String);
method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int);
method public final void onReceive(@NonNull android.content.Context, @NonNull android.content.Intent);
+ method public void onSecurityLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent);
}
public final class DeviceAdminInfo implements android.os.Parcelable {
@@ -7019,6 +7022,7 @@
field public static final String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
field public static final String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
field public static final String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE";
+ field public static final String ACTION_SECURITY_LOGS_AVAILABLE = "android.app.action.SECURITY_LOGS_AVAILABLE";
field public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0; // 0x0
field public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1; // 0x1
field public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
@@ -7314,6 +7318,7 @@
field public static final String DELEGATION_NETWORK_LOGGING = "delegation-network-logging";
field public static final String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
field public static final String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
+ field public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4
@@ -8005,13 +8010,14 @@
method public long getStartTimeMillis();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int ACTIVITY_ANNIVERSARY = 2; // 0x2
+ field public static final int ACTIVITY_AUDIO = 4; // 0x4
field public static final int ACTIVITY_BIRTHDAY = 1; // 0x1
- field public static final int ACTIVITY_GAME = 5; // 0x5
- field public static final int ACTIVITY_LOCATION = 6; // 0x6
- field public static final int ACTIVITY_MEDIA = 4; // 0x4
+ field public static final int ACTIVITY_GAME = 6; // 0x6
+ field public static final int ACTIVITY_LOCATION = 7; // 0x7
field public static final int ACTIVITY_NEW_STORY = 3; // 0x3
field public static final int ACTIVITY_OTHER = 0; // 0x0
- field public static final int ACTIVITY_UPCOMING_BIRTHDAY = 7; // 0x7
+ field public static final int ACTIVITY_UPCOMING_BIRTHDAY = 8; // 0x8
+ field public static final int ACTIVITY_VIDEO = 5; // 0x5
field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
field public static final int AVAILABILITY_BUSY = 1; // 0x1
field public static final int AVAILABILITY_OFFLINE = 2; // 0x2
@@ -12166,6 +12172,7 @@
field public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1; // 0x1
field public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2; // 0x2
field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2
+ field public static final int REQUESTED_PERMISSION_NEVER_FOR_LOCATION = 65536; // 0x10000
field public android.content.pm.ActivityInfo[] activities;
field public android.content.pm.ApplicationInfo applicationInfo;
field @Nullable public android.content.pm.Attribution[] attributions;
@@ -20678,6 +20685,7 @@
method public android.media.AudioDeviceInfo getPreferredDevice();
method public android.media.AudioDeviceInfo getRoutedDevice();
method public int getSampleRate();
+ method @IntRange(from=1) public int getStartThresholdInFrames();
method public int getState();
method public int getStreamType();
method public boolean getTimestamp(android.media.AudioTimestamp);
@@ -20708,6 +20716,7 @@
method public int setPositionNotificationPeriod(int);
method public boolean setPreferredDevice(android.media.AudioDeviceInfo);
method public int setPresentation(@NonNull android.media.AudioPresentation);
+ method @IntRange(from=1) public int setStartThresholdInFrames(@IntRange(from=1) int);
method @Deprecated protected void setState(int);
method @Deprecated public int setStereoVolume(float, float);
method public int setVolume(float);
@@ -41799,7 +41808,7 @@
method @NonNull public android.os.Bundle getCarrierConfigValues();
method @Deprecated public static android.telephony.SmsManager getDefault();
method public static int getDefaultSmsSubscriptionId();
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSmsCapacityOnIcc();
+ method @IntRange(from=0) @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public int getSmsCapacityOnIcc();
method @Deprecated public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback);
method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e49ef2c..8237f12 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -126,6 +126,7 @@
field public static final String MANAGE_ACCESSIBILITY = "android.permission.MANAGE_ACCESSIBILITY";
field @Deprecated public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
field public static final String MANAGE_ACTIVITY_TASKS = "android.permission.MANAGE_ACTIVITY_TASKS";
+ field public static final String MANAGE_APP_HIBERNATION = "android.permission.MANAGE_APP_HIBERNATION";
field public static final String MANAGE_APP_OPS_RESTRICTIONS = "android.permission.MANAGE_APP_OPS_RESTRICTIONS";
field public static final String MANAGE_APP_PREDICTIONS = "android.permission.MANAGE_APP_PREDICTIONS";
field public static final String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
@@ -1831,10 +1832,10 @@
package android.apphibernation {
public final class AppHibernationManager {
- method public boolean isHibernatingForUser(@NonNull String);
- method public boolean isHibernatingGlobally(@NonNull String);
- method public void setHibernatingForUser(@NonNull String, boolean);
- method public void setHibernatingGlobally(@NonNull String, boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public boolean isHibernatingForUser(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public boolean isHibernatingGlobally(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public void setHibernatingForUser(@NonNull String, boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public void setHibernatingGlobally(@NonNull String, boolean);
}
}
@@ -10341,6 +10342,32 @@
method public int getStart();
}
+ public final class HotwordDetectedResult implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getByteOffset();
+ method public int getConfidenceLevel();
+ method @NonNull public android.os.Bundle getExtras();
+ method @Nullable public String getHotwordPhrase();
+ method public static int getMaxBundleSize();
+ method public static int getMaxScore();
+ method public int getPersonalizedScore();
+ method public int getScore();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int BYTE_OFFSET_UNSET = -1; // 0xffffffff
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.HotwordDetectedResult> CREATOR;
+ }
+
+ public static final class HotwordDetectedResult.Builder {
+ ctor public HotwordDetectedResult.Builder();
+ method @NonNull public android.service.voice.HotwordDetectedResult build();
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setByteOffset(int);
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setConfidenceLevel(int);
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setExtras(@NonNull android.os.Bundle);
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordPhrase(@NonNull String);
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setPersonalizedScore(int);
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setScore(int);
+ }
+
public abstract class HotwordDetectionService extends android.app.Service {
ctor public HotwordDetectionService();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
@@ -10354,6 +10381,20 @@
method public void onRejected();
}
+ public interface HotwordDetector {
+ field public static final int CONFIDENCE_LEVEL_HIGH = 3; // 0x3
+ field public static final int CONFIDENCE_LEVEL_LOW = 1; // 0x1
+ field public static final int CONFIDENCE_LEVEL_MEDIUM = 2; // 0x2
+ field public static final int CONFIDENCE_LEVEL_NONE = 0; // 0x0
+ }
+
+ public final class HotwordRejectedResult implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getConfidenceLevel();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.HotwordRejectedResult> CREATOR;
+ }
+
public class VoiceInteractionService extends android.app.Service {
method @NonNull public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(String, java.util.Locale, @Nullable android.os.Bundle, @Nullable android.os.SharedMemory, android.service.voice.AlwaysOnHotwordDetector.Callback);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index a97c3ae..4be6206 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1035,9 +1035,11 @@
public class BiometricPrompt {
method @NonNull public java.util.List<java.lang.Integer> getAllowedSensorIds();
+ method public boolean isAllowBackgroundAuthentication();
}
public static class BiometricPrompt.Builder {
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.TEST_BIOMETRIC, "android.permission.USE_BIOMETRIC_INTERNAL"}) public android.hardware.biometrics.BiometricPrompt.Builder setAllowBackgroundAuthentication(boolean);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.TEST_BIOMETRIC, "android.permission.USE_BIOMETRIC_INTERNAL"}) public android.hardware.biometrics.BiometricPrompt.Builder setAllowedSensorIds(@NonNull java.util.List<java.lang.Integer>);
}
@@ -2929,6 +2931,7 @@
public final class SplashScreenView extends android.widget.FrameLayout {
method @Nullable public android.view.View getBrandingView();
+ method @ColorInt public int getIconBackgroundColor();
}
public final class StartingWindowInfo implements android.os.Parcelable {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c812e8e..f7a3514 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -450,6 +450,21 @@
public abstract boolean hasRunningForegroundService(int uid, int foregroundServiceType);
/**
+ * Returns {@code true} if the given notification channel currently has a
+ * notification associated with a foreground service. This is an AMS check
+ * because that is the source of truth for the FGS state.
+ */
+ public abstract boolean hasForegroundServiceNotification(String pkg, @UserIdInt int userId,
+ String channelId);
+
+ /**
+ * If the given app has any FGSs whose notifications are in the given channel,
+ * stop them.
+ */
+ public abstract void stopForegroundServicesForChannel(String pkg, @UserIdInt int userId,
+ String channelId);
+
+ /**
* Registers the specified {@code processObserver} to be notified of future changes to
* process state.
*/
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 60506b5..f4e214c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -12423,10 +12423,6 @@
*/
public static final int DECORATION_FULL_CONSTRAINED = 4;
- private static final boolean DEFAULT_BACKPORT_S_NOTIF_RULES = false;
- private static final int DEFAULT_FULLY_CUSTOM_DECORATION = DECORATION_MINIMAL;
- private static final int DEFAULT_DECORATED_DECORATION = DECORATION_PARTIAL;
-
/**
* Used by unit tests to force that this class returns its default values, which is required
* in cases where the ContentResolver instance is a mock.
@@ -12439,11 +12435,7 @@
* @hide
*/
public static boolean shouldBackportSNotifRules(@NonNull ContentResolver contentResolver) {
- if (sForceDefaults) {
- return DEFAULT_BACKPORT_S_NOTIF_RULES;
- }
- return Settings.Global.getInt(contentResolver, Settings.Global.BACKPORT_S_NOTIF_RULES,
- DEFAULT_BACKPORT_S_NOTIF_RULES ? 1 : 0) == 1;
+ return false;
}
/**
@@ -12452,14 +12444,7 @@
*/
public static int getFullyCustomViewNotifDecoration(
@NonNull ContentResolver contentResolver) {
- if (sForceDefaults) {
- return DEFAULT_FULLY_CUSTOM_DECORATION;
- }
- final int decoration = Settings.Global.getInt(contentResolver,
- Settings.Global.FULLY_CUSTOM_VIEW_NOTIF_DECORATION,
- DEFAULT_FULLY_CUSTOM_DECORATION);
- // clamp to a valid decoration value
- return Math.max(DECORATION_NONE, Math.min(decoration, DECORATION_FULL_CONSTRAINED));
+ return DECORATION_MINIMAL;
}
/**
@@ -12468,14 +12453,7 @@
*/
public static int getDecoratedCustomViewNotifDecoration(
@NonNull ContentResolver contentResolver) {
- if (sForceDefaults) {
- return DEFAULT_DECORATED_DECORATION;
- }
- final int decoration = Settings.Global.getInt(contentResolver,
- Settings.Global.DECORATED_CUSTOM_VIEW_NOTIF_DECORATION,
- DEFAULT_DECORATED_DECORATION);
- // clamp to a valid decoration value (and don't allow decoration to be NONE or MINIMAL)
- return Math.max(DECORATION_PARTIAL, Math.min(decoration, DECORATION_FULL_CONSTRAINED));
+ return DECORATION_PARTIAL;
}
}
}
diff --git a/core/java/android/app/admin/DelegatedAdminReceiver.java b/core/java/android/app/admin/DelegatedAdminReceiver.java
index 25b8eab..36097c9 100644
--- a/core/java/android/app/admin/DelegatedAdminReceiver.java
+++ b/core/java/android/app/admin/DelegatedAdminReceiver.java
@@ -18,6 +18,7 @@
import static android.app.admin.DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS;
import static android.app.admin.DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE;
+import static android.app.admin.DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_ALIAS;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_URI;
@@ -115,6 +116,29 @@
}
/**
+ * Called each time a new batch of security logs can be retrieved. This callback method will
+ * only ever be called when security logging is enabled. The logs can only be retrieved while
+ * security logging is enabled.
+ *
+ * <p>If a secondary user or profile is created, this callback won't be received until all users
+ * become affiliated again (even if security logging is enabled). It will also no longer be
+ * possible to retrieve the security logs. See {@link DevicePolicyManager#setAffiliationIds}.
+ *
+ * <p> This callback is only applicable if the delegated app has
+ * {@link DevicePolicyManager#DELEGATION_SECURITY_LOGGING} capability. Additionally, it must
+ * declare an intent filter for {@link DeviceAdminReceiver#ACTION_SECURITY_LOGS_AVAILABLE} in
+ * the receiver's manifest in order to receive this callback. The default implementation
+ * simply throws {@link UnsupportedOperationException}.
+ *
+ * @param context The running context as per {@link #onReceive}.
+ * @param intent The received intent as per {@link #onReceive}.
+ * @see DevicePolicyManager#retrieveSecurityLogs
+ */
+ public void onSecurityLogsAvailable(@NonNull Context context, @NonNull Intent intent) {
+ throw new UnsupportedOperationException("onSecurityLogsAvailable should be implemented");
+ }
+
+ /**
* Intercept delegated device administrator broadcasts. Implementations should not override
* this method; implement the convenience callbacks for each action instead.
*/
@@ -132,6 +156,8 @@
long batchToken = intent.getLongExtra(EXTRA_NETWORK_LOGS_TOKEN, -1);
int networkLogsCount = intent.getIntExtra(EXTRA_NETWORK_LOGS_COUNT, 0);
onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
+ } else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
+ onSecurityLogsAvailable(context, intent);
} else {
Log.w(TAG, "Unhandled broadcast: " + action);
}
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index cccc929..747a2de 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -290,7 +290,6 @@
/**
* Broadcast action: notify that a new batch of security logs is ready to be collected.
- * @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@BroadcastBehavior(explicitOnly = true)
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 594b005..426159f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1905,6 +1905,20 @@
public static final String DELEGATION_CERT_SELECTION = "delegation-cert-selection";
/**
+ * Grants access to {@link #setSecurityLoggingEnabled}, {@link #isSecurityLoggingEnabled},
+ * {@link #retrieveSecurityLogs}, and {@link #retrievePreRebootSecurityLogs}. Once granted the
+ * delegated app will start receiving {@link DelegatedAdminReceiver#onSecurityLogsAvailable}
+ * callback, and Device owner or Profile Owner will no longer receive the
+ * {@link DeviceAdminReceiver#onSecurityLogsAvailable} callback. There can be at most one app
+ * that has this delegation. If another app already had delegated security logging access, it
+ * will lose the delegation when a new app is delegated.
+ *
+ * <p> Can only be granted by Device Owner or Profile Owner of an organnization owned and
+ * managed profile.
+ */
+ public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
+
+ /**
* No management for current user in-effect. This is the default.
* @hide
*/
@@ -11241,7 +11255,7 @@
public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
throwIfParentInstance("setSecurityLoggingEnabled");
try {
- mService.setSecurityLoggingEnabled(admin, enabled);
+ mService.setSecurityLoggingEnabled(admin, mContext.getPackageName(), enabled);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -11260,7 +11274,7 @@
public boolean isSecurityLoggingEnabled(@Nullable ComponentName admin) {
throwIfParentInstance("isSecurityLoggingEnabled");
try {
- return mService.isSecurityLoggingEnabled(admin);
+ return mService.isSecurityLoggingEnabled(admin, mContext.getPackageName());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -11285,10 +11299,12 @@
* @see #isAffiliatedUser
* @see DeviceAdminReceiver#onSecurityLogsAvailable
*/
+ @SuppressLint("NullableCollection")
public @Nullable List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
throwIfParentInstance("retrieveSecurityLogs");
try {
- ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
+ ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(
+ admin, mContext.getPackageName());
if (list != null) {
return list.getList();
} else {
@@ -11438,11 +11454,13 @@
* @see #isAffiliatedUser
* @see #retrieveSecurityLogs
*/
+ @SuppressLint("NullableCollection")
public @Nullable List<SecurityEvent> retrievePreRebootSecurityLogs(
@NonNull ComponentName admin) {
throwIfParentInstance("retrievePreRebootSecurityLogs");
try {
- ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
+ ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(
+ admin, mContext.getPackageName());
if (list != null) {
return list.getList();
} else {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index e98720c..7901791 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -386,10 +386,10 @@
List<String> getAffiliationIds(in ComponentName admin);
boolean isAffiliatedUser();
- void setSecurityLoggingEnabled(in ComponentName admin, boolean enabled);
- boolean isSecurityLoggingEnabled(in ComponentName admin);
- ParceledListSlice retrieveSecurityLogs(in ComponentName admin);
- ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin);
+ void setSecurityLoggingEnabled(in ComponentName admin, String packageName, boolean enabled);
+ boolean isSecurityLoggingEnabled(in ComponentName admin, String packageName);
+ ParceledListSlice retrieveSecurityLogs(in ComponentName admin, String packageName);
+ ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin, String packageName);
long forceNetworkLogs();
long forceSecurityLogs();
diff --git a/core/java/android/app/people/ConversationStatus.java b/core/java/android/app/people/ConversationStatus.java
index d2a0255..d351683 100644
--- a/core/java/android/app/people/ConversationStatus.java
+++ b/core/java/android/app/people/ConversationStatus.java
@@ -36,7 +36,8 @@
ACTIVITY_BIRTHDAY,
ACTIVITY_ANNIVERSARY,
ACTIVITY_NEW_STORY,
- ACTIVITY_MEDIA,
+ ACTIVITY_AUDIO,
+ ACTIVITY_VIDEO,
ACTIVITY_GAME,
ACTIVITY_LOCATION,
ACTIVITY_UPCOMING_BIRTHDAY
@@ -44,14 +45,47 @@
@Retention(RetentionPolicy.SOURCE)
public @interface ActivityType {}
+ /**
+ * Constant representing that the conversation user is engaged in an activity that cannot be
+ * more specifically represented by another type.
+ */
public static final int ACTIVITY_OTHER = 0;
+ /**
+ * Constant representing that today is the conversation user's birthday.
+ */
public static final int ACTIVITY_BIRTHDAY = 1;
+ /**
+ * Constant representing that the conversation user and the device user are celebrating
+ * and anniversary today.
+ */
public static final int ACTIVITY_ANNIVERSARY = 2;
+ /**
+ * Constant representing that the conversation user has posted a new story.
+ */
public static final int ACTIVITY_NEW_STORY = 3;
- public static final int ACTIVITY_MEDIA = 4;
- public static final int ACTIVITY_GAME = 5;
- public static final int ACTIVITY_LOCATION = 6;
- public static final int ACTIVITY_UPCOMING_BIRTHDAY = 7;
+ /**
+ * Constant representing that the conversation user is listening to music or other audio
+ * like a podcast.
+ */
+ public static final int ACTIVITY_AUDIO = 4;
+ /**
+ * Constant representing that the conversation user is watching video content.
+ */
+ public static final int ACTIVITY_VIDEO = 5;
+ /**
+ * Constant representing that the conversation user is playing a game.
+ */
+ public static final int ACTIVITY_GAME = 6;
+ /**
+ * Constant representing that the conversation user is sharing status with the device user.
+ * Use this to represent a general 'this person is sharing their location with you' status or
+ * a more specific 'this is the current location of this person' status.
+ */
+ public static final int ACTIVITY_LOCATION = 7;
+ /**
+ * Constant representing that the conversation user's birthday is approaching soon.
+ */
+ public static final int ACTIVITY_UPCOMING_BIRTHDAY = 8;
/** @hide */
@IntDef(prefix = { "AVAILABILITY_" }, value = {
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 31781ec..1db7e9d 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -1104,6 +1104,14 @@
break;
case REASON_MAIN_FORCED_BY_USER:
sb.append("f");
+ if (subReason > 0) {
+ // Although not expected and shouldn't happen, this could potentially have a
+ // sub-reason if the system tries to give a reason when applying the
+ // FORCED_BY_USER reason. The sub-reason is undefined (though most likely a
+ // REASON_SUB_FORCED_SYSTEM_FLAG_ sub-reason), but it's better to note it in the
+ // log than to exclude it altogether.
+ sb.append("-").append(Integer.toBinaryString(subReason));
+ }
break;
case REASON_MAIN_PREDICTED:
sb.append("p");
diff --git a/core/java/android/apphibernation/AppHibernationManager.java b/core/java/android/apphibernation/AppHibernationManager.java
index 7281d50..132cc40 100644
--- a/core/java/android/apphibernation/AppHibernationManager.java
+++ b/core/java/android/apphibernation/AppHibernationManager.java
@@ -17,6 +17,7 @@
package android.apphibernation;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
@@ -54,6 +55,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(value = android.Manifest.permission.MANAGE_APP_HIBERNATION)
public boolean isHibernatingForUser(@NonNull String packageName) {
try {
return mIAppHibernationService.isHibernatingForUser(packageName, mContext.getUserId());
@@ -68,6 +70,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(value = android.Manifest.permission.MANAGE_APP_HIBERNATION)
public void setHibernatingForUser(@NonNull String packageName, boolean isHibernating) {
try {
mIAppHibernationService.setHibernatingForUser(packageName, mContext.getUserId(),
@@ -83,6 +86,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(value = android.Manifest.permission.MANAGE_APP_HIBERNATION)
public boolean isHibernatingGlobally(@NonNull String packageName) {
try {
return mIAppHibernationService.isHibernatingGlobally(packageName);
@@ -99,6 +103,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(value = android.Manifest.permission.MANAGE_APP_HIBERNATION)
public void setHibernatingGlobally(@NonNull String packageName, boolean isHibernating) {
try {
mIAppHibernationService.setHibernatingGlobally(packageName, isHibernating);
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 8fd0de7..a6b4b47 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -520,9 +520,7 @@
return;
}
int layoutId = rvToApply.getLayoutId();
- // If our stale view has been prepared to match active, and the new
- // layout matches, try recycling it
- if (content == null && layoutId == mLayoutId) {
+ if (rvToApply.canRecycleView(mView)) {
try {
rvToApply.reapply(mContext, mView, mInteractionHandler, mCurrentSize,
mColorResources);
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index e8ef077..0462a4b 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -232,13 +232,23 @@
*
* @removed We do not support required permissions.
*/
- public static final int REQUESTED_PERMISSION_REQUIRED = 1<<0;
+ public static final int REQUESTED_PERMISSION_REQUIRED = 0x00000001;
/**
* Flag for {@link #requestedPermissionsFlags}: the requested permission
* is currently granted to the application.
*/
- public static final int REQUESTED_PERMISSION_GRANTED = 1<<1;
+ public static final int REQUESTED_PERMISSION_GRANTED = 0x00000002;
+
+ /**
+ * Flag for {@link #requestedPermissionsFlags}: the requested permission has
+ * declared {@code neverForLocation} in their manifest as a strong assertion
+ * by a developer that they will never use this permission to derive the
+ * physical location of the device, regardless of
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and/or
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} being granted.
+ */
+ public static final int REQUESTED_PERMISSION_NEVER_FOR_LOCATION = 0x00010000;
/**
* Array of all signatures read from the package file. This is only filled
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index fdd2c2a..e0052da 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -52,6 +52,7 @@
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.parsing.component.ParsedProvider;
import android.content.pm.parsing.component.ParsedService;
+import android.content.pm.parsing.component.ParsedUsesPermission;
import android.os.Environment;
import android.os.UserHandle;
@@ -61,6 +62,7 @@
import java.io.File;
import java.util.Collections;
+import java.util.List;
import java.util.Set;
/** @hide **/
@@ -264,17 +266,26 @@
flags);
}
}
- size = pkg.getRequestedPermissions().size();
+ final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions();
+ size = usesPermissions.size();
if (size > 0) {
pi.requestedPermissions = new String[size];
pi.requestedPermissionsFlags = new int[size];
for (int i = 0; i < size; i++) {
- final String perm = pkg.getRequestedPermissions().get(i);
- pi.requestedPermissions[i] = perm;
+ final ParsedUsesPermission usesPermission = usesPermissions.get(i);
+ pi.requestedPermissions[i] = usesPermission.name;
// The notion of required permissions is deprecated but for compatibility.
- pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
- if (grantedPermissions != null && grantedPermissions.contains(perm)) {
- pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
+ pi.requestedPermissionsFlags[i] |=
+ PackageInfo.REQUESTED_PERMISSION_REQUIRED;
+ if (grantedPermissions != null
+ && grantedPermissions.contains(usesPermission.name)) {
+ pi.requestedPermissionsFlags[i] |=
+ PackageInfo.REQUESTED_PERMISSION_GRANTED;
+ }
+ if ((usesPermission.usesPermissionFlags
+ & ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0) {
+ pi.requestedPermissionsFlags[i] |=
+ PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
}
}
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedUsesPermission.java b/core/java/android/content/pm/parsing/component/ParsedUsesPermission.java
index b9c2e36..adf8da0 100644
--- a/core/java/android/content/pm/parsing/component/ParsedUsesPermission.java
+++ b/core/java/android/content/pm/parsing/component/ParsedUsesPermission.java
@@ -20,6 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.content.pm.PackageInfo;
import android.os.Parcel;
import android.os.Parcelable;
@@ -44,7 +45,8 @@
* to derive the physical location of the device, regardless of
* ACCESS_FINE_LOCATION and/or ACCESS_COARSE_LOCATION being granted.
*/
- public static final int FLAG_NEVER_FOR_LOCATION = 0x1;
+ public static final int FLAG_NEVER_FOR_LOCATION =
+ PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 1258247..2e51dc4 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -368,6 +368,20 @@
}
/**
+ * @param allow If true, allows authentication when the calling package is not in the
+ * foreground. This is set to false by default.
+ * @return This builder
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ @RequiresPermission(anyOf = {TEST_BIOMETRIC, USE_BIOMETRIC_INTERNAL})
+ public Builder setAllowBackgroundAuthentication(boolean allow) {
+ mPromptInfo.setAllowBackgroundAuthentication(allow);
+ return this;
+ }
+
+ /**
* If set check the Device Policy Manager for disabled biometrics.
*
* @param checkDevicePolicyManager
@@ -620,6 +634,15 @@
}
/**
+ * @return The value set by {@link Builder#setAllowBackgroundAuthentication(boolean)}
+ * @hide
+ */
+ @TestApi
+ public boolean isAllowBackgroundAuthentication() {
+ return mPromptInfo.isAllowBackgroundAuthentication();
+ }
+
+ /**
* A wrapper class for the cryptographic operations supported by BiometricPrompt.
*
* <p>Currently the framework supports {@link Signature}, {@link Cipher}, {@link Mac}, and
diff --git a/core/java/android/hardware/biometrics/ComponentInfoInternal.java b/core/java/android/hardware/biometrics/ComponentInfoInternal.java
index fa34e0b..3b61a56 100644
--- a/core/java/android/hardware/biometrics/ComponentInfoInternal.java
+++ b/core/java/android/hardware/biometrics/ComponentInfoInternal.java
@@ -27,11 +27,11 @@
*/
public class ComponentInfoInternal implements Parcelable {
- public final String componentId;
- public final String hardwareVersion;
- public final String firmwareVersion;
- public final String serialNumber;
- public final String softwareVersion;
+ @NonNull public final String componentId;
+ @NonNull public final String hardwareVersion;
+ @NonNull public final String firmwareVersion;
+ @NonNull public final String serialNumber;
+ @NonNull public final String softwareVersion;
/**
* Constructs a {@link ComponentInfoInternal} from another instance.
@@ -45,8 +45,9 @@
/**
* @hide
*/
- public ComponentInfoInternal(String componentId, String hardwareVersion,
- String firmwareVersion, String serialNumber, String softwareVersion) {
+ public ComponentInfoInternal(@NonNull String componentId, @NonNull String hardwareVersion,
+ @NonNull String firmwareVersion, @NonNull String serialNumber,
+ @NonNull String softwareVersion) {
this.componentId = componentId;
this.hardwareVersion = hardwareVersion;
this.firmwareVersion = firmwareVersion;
diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
index 059bf26..876513f 100644
--- a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
@@ -48,7 +48,7 @@
// startPreparedClient().
void prepareForAuthentication(boolean requireConfirmation, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- int cookie);
+ int cookie, boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
void startPreparedClient(int cookie);
diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java
index 20c25fb..339c654 100644
--- a/core/java/android/hardware/biometrics/PromptInfo.java
+++ b/core/java/android/hardware/biometrics/PromptInfo.java
@@ -44,6 +44,7 @@
private boolean mDisallowBiometricsIfPolicyExists;
private boolean mReceiveSystemEvents;
@NonNull private List<Integer> mAllowedSensorIds = new ArrayList<>();
+ private boolean mAllowBackgroundAuthentication;
public PromptInfo() {
@@ -64,6 +65,7 @@
mDisallowBiometricsIfPolicyExists = in.readBoolean();
mReceiveSystemEvents = in.readBoolean();
mAllowedSensorIds = in.readArrayList(Integer.class.getClassLoader());
+ mAllowBackgroundAuthentication = in.readBoolean();
}
public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() {
@@ -99,11 +101,14 @@
dest.writeBoolean(mDisallowBiometricsIfPolicyExists);
dest.writeBoolean(mReceiveSystemEvents);
dest.writeList(mAllowedSensorIds);
+ dest.writeBoolean(mAllowBackgroundAuthentication);
}
public boolean containsTestConfigurations() {
if (!mAllowedSensorIds.isEmpty()) {
return true;
+ } else if (mAllowBackgroundAuthentication) {
+ return true;
}
return false;
}
@@ -183,6 +188,10 @@
mAllowedSensorIds = sensorIds;
}
+ public void setAllowBackgroundAuthentication(boolean allow) {
+ mAllowBackgroundAuthentication = allow;
+ }
+
// Getters
public CharSequence getTitle() {
@@ -248,4 +257,8 @@
public List<Integer> getAllowedSensorIds() {
return mAllowedSensorIds;
}
+
+ public boolean isAllowBackgroundAuthentication() {
+ return mAllowBackgroundAuthentication;
+ }
}
diff --git a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
index eda0ded..17b2abf 100644
--- a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
+++ b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
@@ -34,7 +34,7 @@
public final int sensorId;
@SensorProperties.Strength public final int sensorStrength;
public final int maxEnrollmentsPerUser;
- public final List<ComponentInfoInternal> componentInfo;
+ @NonNull public final List<ComponentInfoInternal> componentInfo;
public final boolean resetLockoutRequiresHardwareAuthToken;
public final boolean resetLockoutRequiresChallenge;
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index a3c6f2f..b7b1a14 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -2030,7 +2030,9 @@
// Tell listeners that the cameras and torch modes are unavailable and schedule a
// reconnection to camera service. When camera service is reconnected, the camera
// and torch statuses will be updated.
- for (int i = 0; i < mDeviceStatus.size(); i++) {
+ // Iterate from the end to the beginning befcause onStatusChangedLocked removes
+ // entries from the ArrayMap.
+ for (int i = mDeviceStatus.size() - 1; i >= 0; i--) {
String cameraId = mDeviceStatus.keyAt(i);
onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId);
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 2c3e7f1..6dd6744 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -20,6 +20,7 @@
import android.Manifest;
import android.annotation.IntDef;
+import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -376,6 +377,43 @@
@TestApi
public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2;
+ /**
+ * @hide
+ */
+ @LongDef(flag = true, prefix = {"EVENT_FLAG_"}, value = {
+ EVENT_FLAG_DISPLAY_ADDED,
+ EVENT_FLAG_DISPLAY_CHANGED,
+ EVENT_FLAG_DISPLAY_REMOVED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EventsMask {}
+
+ /**
+ * Event type for when a new display is added.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
+ *
+ * @hide
+ */
+ public static final long EVENT_FLAG_DISPLAY_ADDED = 1L << 0;
+
+ /**
+ * Event type for when a display is removed.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
+ *
+ * @hide
+ */
+ public static final long EVENT_FLAG_DISPLAY_REMOVED = 1L << 1;
+
+ /**
+ * Event type for when a display is changed.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
+ *
+ * @hide
+ */
+ public static final long EVENT_FLAG_DISPLAY_CHANGED = 1L << 2;
/** @hide */
public DisplayManager(Context context) {
@@ -486,7 +524,7 @@
}
/**
- * Registers an display listener to receive notifications about when
+ * Registers a display listener to receive notifications about when
* displays are added, removed or changed.
*
* @param listener The listener to register.
@@ -496,7 +534,29 @@
* @see #unregisterDisplayListener
*/
public void registerDisplayListener(DisplayListener listener, Handler handler) {
- mGlobal.registerDisplayListener(listener, handler);
+ registerDisplayListener(listener, handler, EVENT_FLAG_DISPLAY_ADDED
+ | EVENT_FLAG_DISPLAY_CHANGED | EVENT_FLAG_DISPLAY_REMOVED);
+ }
+
+ /**
+ * Registers a display listener to receive notifications about given display event types.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or null
+ * if the listener should be invoked on the calling thread's looper.
+ * @param eventsMask A bitmask of the event types for which this listener is subscribed.
+ *
+ * @see #EVENT_FLAG_DISPLAY_ADDED
+ * @see #EVENT_FLAG_DISPLAY_CHANGED
+ * @see #EVENT_FLAG_DISPLAY_REMOVED
+ * @see #registerDisplayListener(DisplayListener, Handler)
+ * @see #unregisterDisplayListener
+ *
+ * @hide
+ */
+ public void registerDisplayListener(@NonNull DisplayListener listener,
+ @Nullable Handler handler, @EventsMask long eventsMask) {
+ mGlobal.registerDisplayListener(listener, handler, eventsMask);
}
/**
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 60fe582..fd0431c5 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -16,6 +16,9 @@
package android.hardware.display;
+import static android.hardware.display.DisplayManager.EventsMask;
+
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PropertyInvalidatedCache;
@@ -42,6 +45,10 @@
import android.view.DisplayInfo;
import android.view.Surface;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -66,6 +73,14 @@
// orientation change before the display info cache has actually been invalidated.
private static final boolean USE_CACHE = false;
+ @IntDef(prefix = {"SWITCHING_TYPE_"}, value = {
+ EVENT_DISPLAY_ADDED,
+ EVENT_DISPLAY_CHANGED,
+ EVENT_DISPLAY_REMOVED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DisplayEvent {}
+
public static final int EVENT_DISPLAY_ADDED = 1;
public static final int EVENT_DISPLAY_CHANGED = 2;
public static final int EVENT_DISPLAY_REMOVED = 3;
@@ -81,16 +96,17 @@
private final IDisplayManager mDm;
private DisplayManagerCallback mCallback;
- private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
- new ArrayList<DisplayListenerDelegate>();
+ private @EventsMask long mRegisteredEventsMask = 0;
+ private final ArrayList<DisplayListenerDelegate> mDisplayListeners = new ArrayList<>();
- private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
+ private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<>();
private final ColorSpace mWideColorSpace;
private int[] mDisplayIdCache;
private int mWifiDisplayScanNestCount;
- private DisplayManagerGlobal(IDisplayManager dm) {
+ @VisibleForTesting
+ public DisplayManagerGlobal(IDisplayManager dm) {
mDm = dm;
try {
mWideColorSpace =
@@ -274,18 +290,25 @@
* If that is still null, a runtime exception will be thrown.
*/
public void registerDisplayListener(@NonNull DisplayListener listener,
- @Nullable Handler handler) {
+ @Nullable Handler handler, @EventsMask long eventsMask) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
}
+ if (eventsMask == 0) {
+ throw new IllegalArgumentException("The set of events to listen to must not be empty.");
+ }
+
synchronized (mLock) {
int index = findDisplayListenerLocked(listener);
if (index < 0) {
Looper looper = getLooperForHandler(handler);
- mDisplayListeners.add(new DisplayListenerDelegate(listener, looper));
+ mDisplayListeners.add(new DisplayListenerDelegate(listener, looper, eventsMask));
registerCallbackIfNeededLocked();
+ } else {
+ mDisplayListeners.get(index).setEventsMask(eventsMask);
}
+ updateCallbackIfNeededLocked();
}
}
@@ -300,6 +323,7 @@
DisplayListenerDelegate d = mDisplayListeners.get(index);
d.clearEvents();
mDisplayListeners.remove(index);
+ updateCallbackIfNeededLocked();
}
}
}
@@ -325,18 +349,36 @@
return -1;
}
+ @EventsMask
+ private int calculateEventsMaskLocked() {
+ int mask = 0;
+ final int numListeners = mDisplayListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ mask |= mDisplayListeners.get(i).mEventsMask;
+ }
+ return mask;
+ }
+
private void registerCallbackIfNeededLocked() {
if (mCallback == null) {
mCallback = new DisplayManagerCallback();
+ updateCallbackIfNeededLocked();
+ }
+ }
+
+ private void updateCallbackIfNeededLocked() {
+ int mask = calculateEventsMaskLocked();
+ if (mask != mRegisteredEventsMask) {
try {
- mDm.registerCallback(mCallback);
+ mDm.registerCallbackWithEventMask(mCallback, mask);
+ mRegisteredEventsMask = mask;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
- private void handleDisplayEvent(int displayId, int event) {
+ private void handleDisplayEvent(int displayId, @DisplayEvent int event) {
synchronized (mLock) {
if (USE_CACHE) {
mDisplayInfoCache.remove(displayId);
@@ -754,7 +796,7 @@
private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
@Override
- public void onDisplayEvent(int displayId, int event) {
+ public void onDisplayEvent(int displayId, @DisplayEvent int event) {
if (DEBUG) {
Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event);
}
@@ -764,13 +806,16 @@
private static final class DisplayListenerDelegate extends Handler {
public final DisplayListener mListener;
+ public long mEventsMask;
- DisplayListenerDelegate(DisplayListener listener, @NonNull Looper looper) {
+ DisplayListenerDelegate(DisplayListener listener, @NonNull Looper looper,
+ @EventsMask long eventsMask) {
super(looper, null, true /*async*/);
mListener = listener;
+ mEventsMask = eventsMask;
}
- public void sendDisplayEvent(int displayId, int event) {
+ public void sendDisplayEvent(int displayId, @DisplayEvent int event) {
Message msg = obtainMessage(event, displayId, 0);
sendMessage(msg);
}
@@ -779,17 +824,27 @@
removeCallbacksAndMessages(null);
}
+ public synchronized void setEventsMask(@EventsMask long newEventsMask) {
+ mEventsMask = newEventsMask;
+ }
+
@Override
- public void handleMessage(Message msg) {
+ public synchronized void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_DISPLAY_ADDED:
- mListener.onDisplayAdded(msg.arg1);
+ if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0) {
+ mListener.onDisplayAdded(msg.arg1);
+ }
break;
case EVENT_DISPLAY_CHANGED:
- mListener.onDisplayChanged(msg.arg1);
+ if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0) {
+ mListener.onDisplayChanged(msg.arg1);
+ }
break;
case EVENT_DISPLAY_REMOVED:
- mListener.onDisplayRemoved(msg.arg1);
+ if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0) {
+ mListener.onDisplayRemoved(msg.arg1);
+ }
break;
}
}
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index ff8a720..dee9144 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -38,6 +38,7 @@
boolean isUidPresentOnDisplay(int uid, int displayId);
void registerCallback(in IDisplayManagerCallback callback);
+ void registerCallbackWithEventMask(in IDisplayManagerCallback callback, long eventsMask);
// Requires CONFIGURE_WIFI_DISPLAY permission.
// The process must have previously registered a callback.
diff --git a/core/java/android/hardware/face/FaceSensorProperties.java b/core/java/android/hardware/face/FaceSensorProperties.java
index 6ddea50..f613127 100644
--- a/core/java/android/hardware/face/FaceSensorProperties.java
+++ b/core/java/android/hardware/face/FaceSensorProperties.java
@@ -17,6 +17,7 @@
package android.hardware.face;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.SensorProperties;
@@ -74,7 +75,8 @@
* @hide
*/
public FaceSensorProperties(int sensorId, int sensorStrength,
- List<ComponentInfo> componentInfo, @FaceSensorProperties.SensorType int sensorType) {
+ @NonNull List<ComponentInfo> componentInfo,
+ @FaceSensorProperties.SensorType int sensorType) {
super(sensorId, sensorStrength, componentInfo);
mSensorType = sensorType;
}
diff --git a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
index 50ea60a2..44dffb2 100644
--- a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
+++ b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
@@ -16,6 +16,7 @@
package android.hardware.face;
+import android.annotation.NonNull;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.SensorProperties;
import android.hardware.biometrics.SensorPropertiesInternal;
@@ -48,7 +49,7 @@
* Initializes SensorProperties with specified values
*/
public FaceSensorPropertiesInternal(int sensorId, @SensorProperties.Strength int strength,
- int maxEnrollmentsPerUser, List<ComponentInfoInternal> componentInfo,
+ int maxEnrollmentsPerUser, @NonNull List<ComponentInfoInternal> componentInfo,
@FaceSensorProperties.SensorType int sensorType, boolean supportsFaceDetection,
boolean supportsSelfIllumination, boolean resetLockoutRequiresChallenge) {
// resetLockout is managed by the HAL and requires a HardwareAuthToken for all face
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 6e7c701..0b44150 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -59,7 +59,7 @@
// startPreparedClient().
void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- int cookie);
+ int cookie, boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
void startPreparedClient(int sensorId, int cookie);
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
index a338575..71b705f 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
@@ -17,6 +17,7 @@
package android.hardware.fingerprint;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.SensorProperties;
@@ -94,7 +95,7 @@
* @hide
*/
public FingerprintSensorProperties(int sensorId, int sensorStrength,
- List<ComponentInfo> componentInfo, @SensorType int sensorType) {
+ @NonNull List<ComponentInfo> componentInfo, @SensorType int sensorType) {
super(sensorId, sensorStrength, componentInfo);
mSensorType = sensorType;
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
index 1b13370..58f6e62 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
@@ -62,7 +62,7 @@
public FingerprintSensorPropertiesInternal(int sensorId,
@SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
- List<ComponentInfoInternal> componentInfo,
+ @NonNull List<ComponentInfoInternal> componentInfo,
@FingerprintSensorProperties.SensorType int sensorType,
boolean resetLockoutRequiresHardwareAuthToken, int sensorLocationX, int sensorLocationY,
int sensorRadius) {
@@ -83,7 +83,7 @@
*/
public FingerprintSensorPropertiesInternal(int sensorId,
@SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
- List<ComponentInfoInternal> componentInfo,
+ @NonNull List<ComponentInfoInternal> componentInfo,
@FingerprintSensorProperties.SensorType int sensorType,
boolean resetLockoutRequiresHardwareAuthToken) {
// TODO(b/179175438): Value should be provided from the HAL
@@ -99,7 +99,7 @@
// TODO(b/179175438): Remove this constructor once all HALs move to AIDL.
public FingerprintSensorPropertiesInternal(@NonNull Context context, int sensorId,
@SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
- List<ComponentInfoInternal> componentInfo,
+ @NonNull List<ComponentInfoInternal> componentInfo,
@FingerprintSensorProperties.SensorType int sensorType,
boolean resetLockoutRequiresHardwareAuthToken) {
super(sensorId, strength, maxEnrollmentsPerUser, componentInfo,
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 054c0d0..469e87e2 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -62,7 +62,8 @@
// by BiometricService. To start authentication after the clients are ready, use
// startPreparedClient().
void prepareForAuthentication(int sensorId, IBinder token, long operationId, int userId,
- IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie);
+ IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie,
+ boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
void startPreparedClient(int sensorId, int cookie);
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index eaa8bd4..f69a7d7 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -60,8 +60,8 @@
private static final String TAG = "ContextHubManager";
/**
- * An extra containing an int from {@link AuthorizationState} describing the client's
- * authorization state.
+ * An extra containing one of the {@code AUTHORIZATION_*} constants such as
+ * {@link #AUTHORIZATION_GRANTED} describing the client's authorization state.
*/
public static final String EXTRA_CLIENT_AUTHORIZATION_STATE =
"android.hardware.location.extra.CLIENT_AUTHORIZATION_STATE";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f1c80af..71ffa92 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -15795,48 +15795,6 @@
public static final String SHOW_NEW_NOTIF_DISMISS = "show_new_notif_dismiss";
/**
- * Whether to enforce the new notification rules (aka rules that are only applied to
- * notifications from apps targeting S) on all notifications.
- * - Collapsed custom view notifications will get the new 76dp height instead of 106dp.
- * - Custom view notifications will be partially decorated.
- * - Large icons will be given an aspect ratio of up to 16:9.
- *
- * Values are:
- * 0: Disabled (Only apps targeting S will receive the new rules)
- * 1: Enabled (All apps will receive the new rules)
- * @hide
- */
- public static final String BACKPORT_S_NOTIF_RULES = "backport_s_notif_rules";
-
- /**
- * The decoration to put on fully custom views that target S.
- *
- * <p>Values are:
- * <br>0: DECORATION_NONE: no decorations.
- * <br>1: DECORATION_MINIMAL: most minimal template; just the icon and the expander.
- * <br>2: DECORATION_PARTIAL: basic template without the top line.
- * <br>3: DECORATION_FULL_COMPATIBLE: basic template with the top line; 40dp of height.
- * <br>4: DECORATION_FULL_CONSTRAINED: basic template with the top line; 28dp of height.
- * <p>See {@link android.app.Notification.DevFlags} for more details.
- * @hide
- */
- public static final String FULLY_CUSTOM_VIEW_NOTIF_DECORATION =
- "fully_custom_view_notif_decoration";
-
- /**
- * The decoration to put on decorated custom views that target S.
- *
- * <p>Values are:
- * <br>2: DECORATION_PARTIAL: basic template without the top line.
- * <br>3: DECORATION_FULL_COMPATIBLE: basic template with the top line; 40dp of height.
- * <br>4: DECORATION_FULL_CONSTRAINED: basic template with the top line; 28dp of height.
- * <p>See {@link android.app.Notification.DevFlags} for more details.
- * @hide
- */
- public static final String DECORATED_CUSTOM_VIEW_NOTIF_DECORATION =
- "decorated_custom_view_notif_decoration";
-
- /**
* Block untrusted touches mode.
*
* Can be one of:
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl b/core/java/android/service/voice/HotwordDetectedResult.aidl
similarity index 66%
copy from packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
copy to core/java/android/service/voice/HotwordDetectedResult.aidl
index 54242be..c3201a19 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
+++ b/core/java/android/service/voice/HotwordDetectedResult.aidl
@@ -14,12 +14,6 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package android.service.voice;
-/**
- * Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
- */
-oneway interface ISplitScreenListener {
- void onStagePositionChanged(int stage, int position);
- void onTaskStageChanged(int taskId, int stage, boolean visible);
-}
+parcelable HotwordDetectedResult;
diff --git a/core/java/android/service/voice/HotwordDetectedResult.java b/core/java/android/service/voice/HotwordDetectedResult.java
new file mode 100644
index 0000000..dd6f698
--- /dev/null
+++ b/core/java/android/service/voice/HotwordDetectedResult.java
@@ -0,0 +1,501 @@
+/*
+ * 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 android.service.voice;
+
+import static android.service.voice.HotwordDetector.CONFIDENCE_LEVEL_NONE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Represents a result supporting the hotword detection.
+ *
+ * @hide
+ */
+@DataClass(
+ genConstructor = false,
+ genBuilder = true,
+ genEqualsHashCode = true,
+ genHiddenConstDefs = true,
+ genParcelable = true,
+ genToString = true
+)
+@SystemApi
+public final class HotwordDetectedResult implements Parcelable {
+
+ /** Represents unset value for byte offset. */
+ public static final int BYTE_OFFSET_UNSET = -1;
+
+ /** Confidence level in the trigger outcome. */
+ @HotwordDetector.HotwordConfidenceLevelValue
+ private final int mConfidenceLevel;
+ private static int defaultConfidenceLevel() {
+ return CONFIDENCE_LEVEL_NONE;
+ }
+
+ /**
+ * Byte offset in the audio stream when the trigger event happened.
+ *
+ * <p>If unset, the most recent bytes in the audio stream will be used.
+ */
+ private final int mByteOffset;
+ private static int defaultByteOffset() {
+ return BYTE_OFFSET_UNSET;
+ }
+
+ /**
+ * Score for the hotword trigger.
+ *
+ * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
+ */
+ private final int mScore;
+ private static int defaultScore() {
+ return 0;
+ }
+
+ /**
+ * Score for the hotword trigger for device user.
+ *
+ * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
+ */
+ private final int mPersonalizedScore;
+ private static int defaultPersonalizedScore() {
+ return 0;
+ }
+
+ /**
+ * Returns the maximum values of {@link #getScore} and {@link #getPersonalizedScore}.
+ *
+ * The float value should be calculated as {@code getScore() / getMaxScore()}.
+ */
+ public static int getMaxScore() {
+ return 255;
+ }
+
+ /**
+ * Triggered phrase.
+ *
+ * <p>This phrase has to be listed in the AndroidManifest of the application in order for
+ * trigger to be accepted by the system.
+ */
+ // TODO(b/183128696): allow listing this in the manifest.
+ @Nullable
+ private final String mHotwordPhrase;
+ private static String defaultHotwordPhrase() {
+ return null;
+ }
+
+ /**
+ * App-specific extras to support trigger.
+ *
+ * <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
+ * bundles will be rejected.
+ *
+ * <p>Only primitive types are supported in this bundle. Complex types will be removed from the
+ * bundle.
+ *
+ * <p>The use of this method is discouraged, and support for it will be removed in future
+ * versions of Android.
+ */
+ @NonNull
+ private final Bundle mExtras;
+ private static Bundle defaultExtras() {
+ return new Bundle();
+ }
+
+ /**
+ * Returns the maximum byte size of the information contained in the bundle.
+ *
+ * <p>The total size will be calculated as a sum of byte sizes over all bundle keys.
+ *
+ * <p>For example, for a bundle containing a single key: {@code "example_key" -> 42.0f}, the
+ * bundle size will be {@code 11 + Float.BYTES = 15} bytes.
+ */
+ public static int getMaxBundleSize() {
+ return 50;
+ }
+
+
+
+ // Code below generated by codegen v1.0.22.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ HotwordDetectedResult(
+ @HotwordDetector.HotwordConfidenceLevelValue int confidenceLevel,
+ int byteOffset,
+ int score,
+ int personalizedScore,
+ @Nullable String hotwordPhrase,
+ @NonNull Bundle extras) {
+ this.mConfidenceLevel = confidenceLevel;
+ com.android.internal.util.AnnotationValidations.validate(
+ HotwordDetector.HotwordConfidenceLevelValue.class, null, mConfidenceLevel);
+ this.mByteOffset = byteOffset;
+ this.mScore = score;
+ this.mPersonalizedScore = personalizedScore;
+ this.mHotwordPhrase = hotwordPhrase;
+ this.mExtras = extras;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mExtras);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * Confidence level in the trigger outcome.
+ */
+ @DataClass.Generated.Member
+ public @HotwordDetector.HotwordConfidenceLevelValue int getConfidenceLevel() {
+ return mConfidenceLevel;
+ }
+
+ /**
+ * Byte offset in the audio stream when the trigger event happened.
+ *
+ * <p>If unset, the most recent bytes in the audio stream will be used.
+ */
+ @DataClass.Generated.Member
+ public int getByteOffset() {
+ return mByteOffset;
+ }
+
+ /**
+ * Score for the hotword trigger.
+ *
+ * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
+ */
+ @DataClass.Generated.Member
+ public int getScore() {
+ return mScore;
+ }
+
+ /**
+ * Score for the hotword trigger for device user.
+ *
+ * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
+ */
+ @DataClass.Generated.Member
+ public int getPersonalizedScore() {
+ return mPersonalizedScore;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable String getHotwordPhrase() {
+ return mHotwordPhrase;
+ }
+
+ /**
+ * App-specific extras to support trigger.
+ *
+ * <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
+ * bundles will be rejected.
+ *
+ * <p>Only primitive types are supported in this bundle. Complex types will be removed from the
+ * bundle.
+ *
+ * <p>The use of this method is discouraged, and support for it will be removed in future
+ * versions of Android.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Bundle getExtras() {
+ return mExtras;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "HotwordDetectedResult { " +
+ "confidenceLevel = " + mConfidenceLevel + ", " +
+ "byteOffset = " + mByteOffset + ", " +
+ "score = " + mScore + ", " +
+ "personalizedScore = " + mPersonalizedScore + ", " +
+ "hotwordPhrase = " + mHotwordPhrase + ", " +
+ "extras = " + mExtras +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(HotwordDetectedResult other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ HotwordDetectedResult that = (HotwordDetectedResult) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mConfidenceLevel == that.mConfidenceLevel
+ && mByteOffset == that.mByteOffset
+ && mScore == that.mScore
+ && mPersonalizedScore == that.mPersonalizedScore
+ && java.util.Objects.equals(mHotwordPhrase, that.mHotwordPhrase)
+ && java.util.Objects.equals(mExtras, that.mExtras);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mConfidenceLevel;
+ _hash = 31 * _hash + mByteOffset;
+ _hash = 31 * _hash + mScore;
+ _hash = 31 * _hash + mPersonalizedScore;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mHotwordPhrase);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mExtras);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mHotwordPhrase != null) flg |= 0x10;
+ dest.writeByte(flg);
+ dest.writeInt(mConfidenceLevel);
+ dest.writeInt(mByteOffset);
+ dest.writeInt(mScore);
+ dest.writeInt(mPersonalizedScore);
+ if (mHotwordPhrase != null) dest.writeString(mHotwordPhrase);
+ dest.writeBundle(mExtras);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ HotwordDetectedResult(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int confidenceLevel = in.readInt();
+ int byteOffset = in.readInt();
+ int score = in.readInt();
+ int personalizedScore = in.readInt();
+ String hotwordPhrase = (flg & 0x10) == 0 ? null : in.readString();
+ Bundle extras = in.readBundle();
+
+ this.mConfidenceLevel = confidenceLevel;
+ com.android.internal.util.AnnotationValidations.validate(
+ HotwordDetector.HotwordConfidenceLevelValue.class, null, mConfidenceLevel);
+ this.mByteOffset = byteOffset;
+ this.mScore = score;
+ this.mPersonalizedScore = personalizedScore;
+ this.mHotwordPhrase = hotwordPhrase;
+ this.mExtras = extras;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mExtras);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<HotwordDetectedResult> CREATOR
+ = new Parcelable.Creator<HotwordDetectedResult>() {
+ @Override
+ public HotwordDetectedResult[] newArray(int size) {
+ return new HotwordDetectedResult[size];
+ }
+
+ @Override
+ public HotwordDetectedResult createFromParcel(@NonNull android.os.Parcel in) {
+ return new HotwordDetectedResult(in);
+ }
+ };
+
+ /**
+ * A builder for {@link HotwordDetectedResult}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private @HotwordDetector.HotwordConfidenceLevelValue int mConfidenceLevel;
+ private int mByteOffset;
+ private int mScore;
+ private int mPersonalizedScore;
+ private @Nullable String mHotwordPhrase;
+ private @NonNull Bundle mExtras;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * Confidence level in the trigger outcome.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setConfidenceLevel(@HotwordDetector.HotwordConfidenceLevelValue int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mConfidenceLevel = value;
+ return this;
+ }
+
+ /**
+ * Byte offset in the audio stream when the trigger event happened.
+ *
+ * <p>If unset, the most recent bytes in the audio stream will be used.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setByteOffset(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mByteOffset = value;
+ return this;
+ }
+
+ /**
+ * Score for the hotword trigger.
+ *
+ * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setScore(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mScore = value;
+ return this;
+ }
+
+ /**
+ * Score for the hotword trigger for device user.
+ *
+ * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setPersonalizedScore(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mPersonalizedScore = value;
+ return this;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull Builder setHotwordPhrase(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mHotwordPhrase = value;
+ return this;
+ }
+
+ /**
+ * App-specific extras to support trigger.
+ *
+ * <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
+ * bundles will be rejected.
+ *
+ * <p>Only primitive types are supported in this bundle. Complex types will be removed from the
+ * bundle.
+ *
+ * <p>The use of this method is discouraged, and support for it will be removed in future
+ * versions of Android.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setExtras(@NonNull Bundle value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mExtras = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull HotwordDetectedResult build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mConfidenceLevel = defaultConfidenceLevel();
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mByteOffset = defaultByteOffset();
+ }
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mScore = defaultScore();
+ }
+ if ((mBuilderFieldsSet & 0x8) == 0) {
+ mPersonalizedScore = defaultPersonalizedScore();
+ }
+ if ((mBuilderFieldsSet & 0x10) == 0) {
+ mHotwordPhrase = defaultHotwordPhrase();
+ }
+ if ((mBuilderFieldsSet & 0x20) == 0) {
+ mExtras = defaultExtras();
+ }
+ HotwordDetectedResult o = new HotwordDetectedResult(
+ mConfidenceLevel,
+ mByteOffset,
+ mScore,
+ mPersonalizedScore,
+ mHotwordPhrase,
+ mExtras);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x40) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1616110545582L,
+ codegenVersion = "1.0.22",
+ sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
+ inputSignatures = "public static final int BYTE_OFFSET_UNSET\nprivate final @android.service.voice.HotwordDetector.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate final int mByteOffset\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final @android.annotation.Nullable java.lang.String mHotwordPhrase\nprivate final @android.annotation.NonNull android.os.Bundle mExtras\nprivate static int defaultConfidenceLevel()\nprivate static int defaultByteOffset()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static java.lang.String defaultHotwordPhrase()\nprivate static android.os.Bundle defaultExtras()\npublic static int getMaxBundleSize()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java
new file mode 100644
index 0000000..abf49b7
--- /dev/null
+++ b/core/java/android/service/voice/HotwordDetector.java
@@ -0,0 +1,50 @@
+/*
+ * 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 android.service.voice;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+
+/**
+ * Basic functionality for hotword detectors.
+ *
+ * @hide
+ */
+@SystemApi
+public interface HotwordDetector {
+
+ /** No confidence in hotword detector result. */
+ int CONFIDENCE_LEVEL_NONE = 0;
+
+ /** Small confidence in hotword detector result. */
+ int CONFIDENCE_LEVEL_LOW = 1;
+
+ /** Medium confidence in hotword detector result. */
+ int CONFIDENCE_LEVEL_MEDIUM = 2;
+
+ /** High confidence in hotword detector result. */
+ int CONFIDENCE_LEVEL_HIGH = 3;
+
+ /** @hide */
+ @IntDef(prefix = { "CONFIDENCE_LEVEL_" }, value = {
+ CONFIDENCE_LEVEL_NONE,
+ CONFIDENCE_LEVEL_LOW,
+ CONFIDENCE_LEVEL_MEDIUM,
+ CONFIDENCE_LEVEL_HIGH
+ })
+ @interface HotwordConfidenceLevelValue {}
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl b/core/java/android/service/voice/HotwordRejectedResult.aidl
similarity index 66%
copy from packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
copy to core/java/android/service/voice/HotwordRejectedResult.aidl
index 54242be..ef38a15 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
+++ b/core/java/android/service/voice/HotwordRejectedResult.aidl
@@ -14,12 +14,6 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package android.service.voice;
-/**
- * Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
- */
-oneway interface ISplitScreenListener {
- void onStagePositionChanged(int stage, int position);
- void onTaskStageChanged(int taskId, int stage, boolean visible);
-}
+parcelable HotwordRejectedResult;
diff --git a/core/java/android/service/voice/HotwordRejectedResult.java b/core/java/android/service/voice/HotwordRejectedResult.java
new file mode 100644
index 0000000..5d85662
--- /dev/null
+++ b/core/java/android/service/voice/HotwordRejectedResult.java
@@ -0,0 +1,222 @@
+/*
+ * 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 android.service.voice;
+
+import static android.service.voice.HotwordDetector.CONFIDENCE_LEVEL_NONE;
+
+import android.annotation.SystemApi;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Represents a result supporting the rejected hotword trigger.
+ *
+ * @hide
+ */
+@DataClass(
+ genConstructor = false,
+ genHiddenBuilder = true,
+ genEqualsHashCode = true,
+ genHiddenConstDefs = true,
+ genParcelable = true,
+ genToString = true
+)
+@SystemApi
+public final class HotwordRejectedResult implements Parcelable {
+
+ /** Confidence level in the trigger outcome. */
+ @HotwordDetector.HotwordConfidenceLevelValue
+ private final int mConfidenceLevel;
+ private static int defaultConfidenceLevel() {
+ return CONFIDENCE_LEVEL_NONE;
+ }
+
+
+
+ // Code below generated by codegen v1.0.22.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/voice/HotwordRejectedResult.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ HotwordRejectedResult(
+ @HotwordDetector.HotwordConfidenceLevelValue int confidenceLevel) {
+ this.mConfidenceLevel = confidenceLevel;
+ com.android.internal.util.AnnotationValidations.validate(
+ HotwordDetector.HotwordConfidenceLevelValue.class, null, mConfidenceLevel);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * Confidence level in the trigger outcome.
+ */
+ @DataClass.Generated.Member
+ public @HotwordDetector.HotwordConfidenceLevelValue int getConfidenceLevel() {
+ return mConfidenceLevel;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "HotwordRejectedResult { " +
+ "confidenceLevel = " + mConfidenceLevel +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@android.annotation.Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(HotwordRejectedResult other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ HotwordRejectedResult that = (HotwordRejectedResult) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mConfidenceLevel == that.mConfidenceLevel;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mConfidenceLevel;
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@android.annotation.NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeInt(mConfidenceLevel);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ HotwordRejectedResult(@android.annotation.NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ int confidenceLevel = in.readInt();
+
+ this.mConfidenceLevel = confidenceLevel;
+ com.android.internal.util.AnnotationValidations.validate(
+ HotwordDetector.HotwordConfidenceLevelValue.class, null, mConfidenceLevel);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @android.annotation.NonNull Parcelable.Creator<HotwordRejectedResult> CREATOR
+ = new Parcelable.Creator<HotwordRejectedResult>() {
+ @Override
+ public HotwordRejectedResult[] newArray(int size) {
+ return new HotwordRejectedResult[size];
+ }
+
+ @Override
+ public HotwordRejectedResult createFromParcel(@android.annotation.NonNull android.os.Parcel in) {
+ return new HotwordRejectedResult(in);
+ }
+ };
+
+ /**
+ * A builder for {@link HotwordRejectedResult}
+ * @hide
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private @HotwordDetector.HotwordConfidenceLevelValue int mConfidenceLevel;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * Confidence level in the trigger outcome.
+ */
+ @DataClass.Generated.Member
+ public @android.annotation.NonNull Builder setConfidenceLevel(@HotwordDetector.HotwordConfidenceLevelValue int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mConfidenceLevel = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @android.annotation.NonNull HotwordRejectedResult build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mConfidenceLevel = defaultConfidenceLevel();
+ }
+ HotwordRejectedResult o = new HotwordRejectedResult(
+ mConfidenceLevel);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x2) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1616108967315L,
+ codegenVersion = "1.0.22",
+ sourceFile = "frameworks/base/core/java/android/service/voice/HotwordRejectedResult.java",
+ inputSignatures = "private final @android.service.voice.HotwordDetector.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate static int defaultConfidenceLevel()\nclass HotwordRejectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genHiddenBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index c1b66c7..ad09a48 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1645,7 +1645,7 @@
/**
* Called to receive data from the application that the user was currently viewing when
- * an assist session is started. If the original show request did not specify
+- * an assist session is started. If the original show request did not specify
* {@link #SHOW_WITH_ASSIST}, this method will not be called.
*
* @param data Arbitrary data supplied by the app through
@@ -1670,8 +1670,9 @@
/**
* Called to receive data from the application that the user was currently viewing when
- * an assist session is started. If the original show request did not specify
- * {@link #SHOW_WITH_ASSIST}, this method will not be called.
+ * an assist session is started. If the original show request did not specify
+ * {@link #SHOW_WITH_ASSIST}, {@link AssistState} parameter will only provide
+ * {@link ActivityId}.
*
* <p>This method is called for all activities along with an index and count that indicates
* which activity the data is for. {@code index} will be between 0 and {@code count}-1 and
@@ -1685,7 +1686,10 @@
* @param state The state object capturing the state of an activity.
*/
public void onHandleAssist(@NonNull AssistState state) {
- if (state.getIndex() == 0) {
+ if (state.getAssistData() == null && state.getAssistStructure() == null
+ && state.getAssistContent() == null) {
+ return;
+ } else if (state.getIndex() == 0) {
onHandleAssist(state.getAssistData(), state.getAssistStructure(),
state.getAssistContent());
} else {
@@ -2028,7 +2032,8 @@
/**
* @return Arbitrary data supplied by the app through
* {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
- * May be null if assist data has been disabled by the user or device policy.
+ * May be null if assist data has been disabled by the user or device policy; will be null
+ * if the original show request did not specify {@link #SHOW_WITH_ASSIST}.
*/
public @Nullable Bundle getAssistData() {
return mData;
@@ -2037,7 +2042,8 @@
/**
* @return If available, the structure definition of all windows currently
* displayed by the app. May be null if assist data has been disabled by the user
- * or device policy; will be an empty stub if the application has disabled assist
+ * or device policy; will be null if the original show request did not specify
+ * {@link #SHOW_WITH_ASSIST}; will be an empty stub if the application has disabled assist
* by marking its window as secure.
*/
public @Nullable AssistStructure getAssistStructure() {
@@ -2047,9 +2053,10 @@
/**
* @return Additional content data supplied by the app through
* {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}.
- * May be null if assist data has been disabled by the user or device policy; will
- * not be automatically filled in with data from the app if the app has marked its
- * window as secure.
+ * May be null if assist data has been disabled by the user or device policy; will be null
+ * if the original show request did not specify {@link #SHOW_WITH_ASSIST}. Will not be
+ * automatically filled in with data from the app if the app has marked its window as
+ * secure.
*/
public @Nullable AssistContent getAssistContent() {
return mContent;
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index f61ab29..d3eaeae 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -30,11 +30,11 @@
*/
public final class Slog {
- @GuardedBy("sMessageBuilder")
- private static final StringBuilder sMessageBuilder = new StringBuilder();
+ @GuardedBy("Slog.class")
+ private static StringBuilder sMessageBuilder;
- @GuardedBy("sMessageBuilder")
- private static final Formatter sFormatter = new Formatter(sMessageBuilder, Locale.ENGLISH);
+ @GuardedBy("Slog.class")
+ private static Formatter sFormatter;
private Slog() {
}
@@ -226,7 +226,12 @@
}
private static String getMessage(String format, @Nullable Object... args) {
- synchronized (sMessageBuilder) {
+ synchronized (Slog.class) {
+ if (sMessageBuilder == null) {
+ // Lazy load so they're not created if not used by the process
+ sMessageBuilder = new StringBuilder();
+ sFormatter = new Formatter(sMessageBuilder, Locale.ENGLISH);
+ }
sFormatter.format(format, args);
String message = sMessageBuilder.toString();
sMessageBuilder.setLength(0);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 0167147..85d4878 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -105,7 +105,6 @@
private static native void nativeMergeTransaction(long transactionObj,
long otherTransactionObj);
private static native void nativeSetAnimationTransaction(long transactionObj);
- private static native void nativeSetEarlyWakeup(long transactionObj);
private static native void nativeSetEarlyWakeupStart(long transactionObj);
private static native void nativeSetEarlyWakeupEnd(long transactionObj);
@@ -3175,23 +3174,6 @@
return this;
}
- /**
- * @deprecated use {@link Transaction#setEarlyWakeupStart()}
- *
- * Indicate that SurfaceFlinger should wake up earlier than usual as a result of this
- * transaction. This should be used when the caller thinks that the scene is complex enough
- * that it's likely to hit GL composition, and thus, SurfaceFlinger needs to more time in
- * order not to miss frame deadlines.
- * <p>
- * Corresponds to setting ISurfaceComposer::eEarlyWakeup
- * @hide
- */
- @Deprecated
- public Transaction setEarlyWakeup() {
- nativeSetEarlyWakeup(mNativeObject);
- return this;
- }
-
/**
* Provides a hint to SurfaceFlinger to change its offset so that SurfaceFlinger wakes up
* earlier to compose surfaces. The caller should use this as a hint to SurfaceFlinger
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 35d5d8e..7455b8b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,6 +17,7 @@
package android.view;
import static android.content.res.Resources.ID_NULL;
+import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
@@ -26747,6 +26748,21 @@
* {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
* in DragEvent. The method uses these to determine what is happening in the drag and drop
* operation.
+ * </p>
+ * <p>
+ * The default implementation returns false, except if an {@link OnReceiveContentListener}
+ * is {@link #setOnReceiveContentListener set} for this view. If an
+ * {@link OnReceiveContentListener} is set, the default implementation...
+ * <ul>
+ * <li>returns true for an
+ * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
+ * <li>calls {@link #performReceiveContent} for an
+ * {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event
+ * <li>returns true for an {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event, if
+ * the listener consumed some or all of the content
+ * </ul>
+ * </p>
+ *
* @param event The {@link android.view.DragEvent} sent by the system.
* The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
* in DragEvent, indicating the type of drag event represented by this object.
@@ -26766,6 +26782,24 @@
* </p>
*/
public boolean onDragEvent(DragEvent event) {
+ if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
+ return false;
+ }
+ // Accept drag events by default if there's an OnReceiveContentListener set.
+ if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
+ return true;
+ }
+ if (event.getAction() == DragEvent.ACTION_DROP) {
+ final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
+ if (permissions != null) {
+ permissions.takeTransient();
+ }
+ final ContentInfo payload = new ContentInfo.Builder(
+ event.getClipData(), SOURCE_DRAG_AND_DROP).build();
+ ContentInfo remainingPayload = performReceiveContent(payload);
+ // Return true unless none of the payload was consumed.
+ return remainingPayload != payload;
+ }
return false;
}
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 3c41112..58dfc0d 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -117,12 +117,12 @@
/**
* The natural frequency of the stretch spring.
*/
- private static final double NATURAL_FREQUENCY = 14.4222;
+ private static final double NATURAL_FREQUENCY = 17.55;
/**
* The damping ratio of the stretch spring.
*/
- private static final double DAMPING_RATIO = 0.875;
+ private static final double DAMPING_RATIO = 0.92;
/** @hide */
@IntDef({TYPE_GLOW, TYPE_STRETCH})
@@ -130,7 +130,11 @@
public @interface EdgeEffectType {
}
- private static final float DEFAULT_MAX_STRETCH_INTENSITY = 0.08f;
+ private static final float LINEAR_STRETCH_INTENSITY = 0.03f;
+
+ private static final float EXP_STRETCH_INTENSITY = 0.02f;
+
+ private static final float SCROLL_DIST_AFFECTED_BY_EXP_STRETCH = 0.4f;
@SuppressWarnings("UnusedDeclaration")
private static final String TAG = "EdgeEffect";
@@ -176,9 +180,6 @@
private long mStartTime;
private float mDuration;
- private float mStretchIntensity = DEFAULT_MAX_STRETCH_INTENSITY;
- private float mStretchDistanceFraction = 1f;
- private float mStretchDistance = -1f;
private final Interpolator mInterpolator = new DecelerateInterpolator();
@@ -269,16 +270,6 @@
}
/**
- * Configure the distance in pixels to stretch the content. This is only consumed as part
- * if {@link #setType(int)} is set to {@link #TYPE_STRETCH}
- * @param stretchDistance Stretch distance in pixels when the target View is overscrolled
- * @hide
- */
- public void setStretchDistance(float stretchDistance) {
- mStretchDistance = stretchDistance;
- }
-
- /**
* Reports if this EdgeEffect's animation is finished. If this method returns false
* after a call to {@link #draw(Canvas)} the host widget should schedule another
* drawing pass to continue the animation.
@@ -520,13 +511,6 @@
}
/**
- * @hide
- */
- public void setMaxStretchIntensity(float stretchIntensity) {
- mStretchIntensity = stretchIntensity;
- }
-
- /**
* Set or clear the blend mode. A blend mode defines how source pixels
* (generated by a drawing command) are composited with the destination pixels
* (content of the render target).
@@ -642,22 +626,19 @@
// assume rotations of increments of 90 degrees
float x = mTmpPoints[10] - mTmpPoints[8];
float width = right - left;
- float vecX = Math.max(-1f, Math.min(1f, x / width));
+ float vecX = dampStretchVector(Math.max(-1f, Math.min(1f, x / width)));
float y = mTmpPoints[11] - mTmpPoints[9];
float height = bottom - top;
- float vecY = Math.max(-1f, Math.min(1f, y / height));
+ float vecY = dampStretchVector(Math.max(-1f, Math.min(1f, y / height)));
renderNode.stretch(
left,
top,
right,
bottom,
- vecX * mStretchIntensity,
- vecY * mStretchIntensity,
- // TODO (njawad/mount) figure out proper stretch distance from UX
- // for now leverage placeholder logic if no stretch distance is provided to
- // consume the displacement ratio times the minimum of the width or height
- mStretchDistance > 0 ? mStretchDistance :
- (mStretchDistanceFraction * Math.max(mWidth, mHeight))
+ vecX,
+ vecY,
+ mWidth,
+ mHeight
);
}
@@ -794,4 +775,13 @@
return Math.abs(mVelocity) < VELOCITY_THRESHOLD
&& Math.abs(displacement) < VALUE_THRESHOLD;
}
+
+ private float dampStretchVector(float normalizedVec) {
+ float sign = normalizedVec > 0 ? 1f : -1f;
+ float overscroll = Math.abs(normalizedVec);
+ float linearIntensity = LINEAR_STRETCH_INTENSITY * overscroll;
+ double scalar = Math.E / SCROLL_DIST_AFFECTED_BY_EXP_STRETCH;
+ double expIntensity = EXP_STRETCH_INTENSITY * (1 - Math.exp(-overscroll * scalar));
+ return sign * (float) (linearIntensity + expIntensity);
+ }
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index bf552e2..23915e0 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -249,26 +249,6 @@
}
/**
- * API used for prototyping stretch effect parameters in framework sample apps
- * @hide
- */
- public void setEdgeEffectIntensity(float intensity) {
- mEdgeGlowLeft.setMaxStretchIntensity(intensity);
- mEdgeGlowRight.setMaxStretchIntensity(intensity);
- invalidate();
- }
-
- /**
- * API used for prototyping stretch effect parameters in the framework sample apps
- * @hide
- */
- public void setStretchDistance(float distance) {
- mEdgeGlowLeft.setStretchDistance(distance);
- mEdgeGlowRight.setStretchDistance(distance);
- invalidate();
- }
-
- /**
* Sets the right edge effect color.
*
* @param color The color for the right edge effect.
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2b73923..319e788 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2196,7 +2196,7 @@
int recycledViewIndex = findViewIndexToRecycle(target, rvToApply);
if (recycledViewIndex >= 0) {
View child = target.getChildAt(recycledViewIndex);
- if (getViewLayoutId(child) == rvToApply.getLayoutId()) {
+ if (rvToApply.canRecycleView(child)) {
if (nextChild < recycledViewIndex) {
target.removeViews(nextChild, recycledViewIndex - nextChild);
}
@@ -2254,7 +2254,7 @@
// application are placed before.
ViewTree recycled = target.mChildren.get(recycledViewIndex);
// We can only recycle the view if the layout id is the same.
- if (getViewLayoutId(recycled.mRoot) == rvToApply.getLayoutId()) {
+ if (rvToApply.canRecycleView(recycled.mRoot)) {
if (recycledViewIndex > nextChild) {
target.removeChildren(nextChild, recycledViewIndex - nextChild);
}
@@ -3726,7 +3726,8 @@
*
* The {@code stableId} will be used to identify a potential view to recycled when the remote
* view is inflated. Views can be re-used if inserted in the same order, potentially with
- * some views appearing / disappearing.
+ * some views appearing / disappearing. To be recycled the view must not change the layout
+ * used to inflate it or its view id (see {@link RemoteViews#setViewId}).
*
* Note: if a view is re-used, all the actions will be re-applied on it. However, its properties
* are not reset, so what was applied in previous round will have an effect. As a view may be
@@ -5116,6 +5117,7 @@
View v = inflater.inflate(rv.getLayoutId(), parent, false);
if (mViewId != View.NO_ID) {
v.setId(mViewId);
+ v.setTagInternal(R.id.remote_views_override_id, mViewId);
}
v.setTagInternal(R.id.widget_frame, rv.getLayoutId());
return v;
@@ -5335,6 +5337,24 @@
reapply(context, v, handler, size, colorResources, true);
}
+ /** @hide */
+ public boolean canRecycleView(@Nullable View v) {
+ if (v == null) {
+ return false;
+ }
+ Integer previousLayoutId = (Integer) v.getTag(R.id.widget_frame);
+ if (previousLayoutId == null) {
+ return false;
+ }
+ Integer overrideIdTag = (Integer) v.getTag(R.id.remote_views_override_id);
+ int overrideId = overrideIdTag == null ? View.NO_ID : overrideIdTag;
+ // If mViewId is View.NO_ID, we only recycle if overrideId is also View.NO_ID.
+ // Otherwise, it might be that, on a previous iteration, the view's ID was set to
+ // something else, and it should now be reset to the ID defined in the XML layout file,
+ // whatever it is.
+ return previousLayoutId == getLayoutId() && mViewId == overrideId;
+ }
+
// Note: topLevel should be true only for calls on the topLevel RemoteViews, internal calls
// should set it to false.
private void reapply(Context context, View v, InteractionHandler handler, SizeF size,
@@ -5347,7 +5367,7 @@
// (orientation or size), we throw an exception, since the layouts may be completely
// unrelated.
if (hasMultipleLayouts()) {
- if ((Integer) v.getTag(R.id.widget_frame) != rvToApply.getLayoutId()) {
+ if (!rvToApply.canRecycleView(v)) {
throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
" that does not share the same root layout id.");
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 3006729..65f3da7 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -281,26 +281,6 @@
}
/**
- * API used for prototyping stretch effect parameters in framework sample apps
- * @hide
- */
- public void setEdgeEffectIntensity(float intensity) {
- mEdgeGlowTop.setMaxStretchIntensity(intensity);
- mEdgeGlowBottom.setMaxStretchIntensity(intensity);
- invalidate();
- }
-
- /**
- * API used for prototyping stretch effect parameters in the framework sample apps
- * @hide
- */
- public void setStretchDistance(float distance) {
- mEdgeGlowTop.setStretchDistance(distance);
- mEdgeGlowBottom.setStretchDistance(distance);
- invalidate();
- }
-
- /**
* Sets the bottom edge effect color.
*
* @param color The color for the bottom edge effect.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index dba7fa9..940a3c9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -13071,11 +13071,37 @@
return getLayout().getOffsetForHorizontal(line, x);
}
+ /**
+ * Handles drag events sent by the system following a call to
+ * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
+ * startDragAndDrop()}.
+ *
+ * <p>If this text view is not editable, delegates to the default {@link View#onDragEvent}
+ * implementation.
+ *
+ * <p>If this text view is editable, accepts all drag actions (returns true for an
+ * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event and all
+ * subsequent drag events). While the drag is in progress, updates the cursor position
+ * to follow the touch location. Once a drop event is received, handles content insertion
+ * via {@link #performReceiveContent}.
+ *
+ * @param event The {@link android.view.DragEvent} sent by the system.
+ * The {@link android.view.DragEvent#getAction()} method returns an action type constant
+ * defined in DragEvent, indicating the type of drag event represented by this object.
+ * @return Returns true if this text view is editable and delegates to super otherwise.
+ * See {@link View#onDragEvent}.
+ */
@Override
public boolean onDragEvent(DragEvent event) {
+ if (mEditor == null || !mEditor.hasInsertionController()) {
+ // If this TextView is not editable, defer to the default View implementation. This
+ // will check for the presence of an OnReceiveContentListener and accept/reject
+ // drag events depending on whether the listener is/isn't set.
+ return super.onDragEvent(event);
+ }
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
- return mEditor != null && mEditor.hasInsertionController();
+ return true;
case DragEvent.ACTION_DRAG_ENTERED:
TextView.this.requestFocus();
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index ddea64a..3709aa1 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -17,8 +17,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import android.animation.Animator;
-import android.animation.ValueAnimator;
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -29,7 +27,6 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
-import android.graphics.drawable.Animatable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
@@ -47,6 +44,8 @@
import com.android.internal.R;
import com.android.internal.policy.DecorView;
+import java.util.function.Consumer;
+
/**
* <p>The view which allows an activity to customize its splash screen exit animation.</p>
*
@@ -69,6 +68,7 @@
private boolean mNotCopyable;
private int mInitBackgroundColor;
+ private int mInitIconBackgroundColor;
private View mIconView;
private Bitmap mParceledIconBitmap;
private View mBrandingImageView;
@@ -76,8 +76,6 @@
private long mIconAnimationDuration;
private long mIconAnimationStart;
- private Animatable mAnimatableIcon;
- private ValueAnimator mAnimator;
// The host activity when transfer view to it.
private Activity mHostActivity;
// cache original window and status
@@ -94,6 +92,7 @@
private final Context mContext;
private int mIconSize;
private @ColorInt int mBackgroundColor;
+ private @ColorInt int mIconBackground;
private Bitmap mParceledIconBitmap;
private Drawable mIconDrawable;
private int mBrandingImageWidth;
@@ -114,6 +113,7 @@
public Builder createFromParcel(SplashScreenViewParcelable parcelable) {
mIconSize = parcelable.getIconSize();
mBackgroundColor = parcelable.getBackgroundColor();
+ mIconBackground = parcelable.getIconBackground();
if (parcelable.mIconBitmap != null) {
mIconDrawable = new BitmapDrawable(mContext.getResources(), parcelable.mIconBitmap);
mParceledIconBitmap = parcelable.mIconBitmap;
@@ -154,6 +154,14 @@
}
/**
+ * Set the background color for the icon.
+ */
+ public Builder setIconBackground(int color) {
+ mIconBackground = color;
+ return this;
+ }
+
+ /**
* Set the animation duration if icon is animatable.
*/
public Builder setAnimationDuration(int duration) {
@@ -179,6 +187,7 @@
final SplashScreenView view = (SplashScreenView)
layoutInflater.inflate(R.layout.splash_screen_view, null, false);
view.mInitBackgroundColor = mBackgroundColor;
+ view.mInitIconBackgroundColor = mIconBackground;
view.setBackgroundColor(mBackgroundColor);
view.mIconView = view.findViewById(R.id.splashscreen_icon_view);
view.mBrandingImageView = view.findViewById(R.id.splashscreen_branding_view);
@@ -266,43 +275,15 @@
}
void initIconAnimation(Drawable iconDrawable, long duration) {
- if (iconDrawable instanceof Animatable) {
- mAnimatableIcon = (Animatable) iconDrawable;
- mAnimator = ValueAnimator.ofInt(0, 1);
- mAnimator.setDuration(duration);
- mAnimator.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- mIconAnimationStart = SystemClock.uptimeMillis();
- mAnimatableIcon.start();
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mAnimatableIcon.stop();
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mAnimatableIcon.stop();
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- // do not repeat
- mAnimatableIcon.stop();
- }
- });
+ if (!(iconDrawable instanceof SplashscreenIconDrawable)) {
+ return;
}
+ SplashscreenIconDrawable aniDrawable = (SplashscreenIconDrawable) iconDrawable;
+ aniDrawable.prepareAnimate(duration, this::animationStartCallback);
}
- /**
- * @hide
- */
- public void startIntroAnimation() {
- if (mAnimatableIcon != null) {
- mAnimator.start();
- }
+ private void animationStartCallback(long startAt) {
+ mIconAnimationStart = startAt;
}
/**
@@ -401,6 +382,15 @@
}
/**
+ * Get the icon background color
+ * @hide
+ */
+ @TestApi
+ public @ColorInt int getIconBackgroundColor() {
+ return mInitIconBackgroundColor;
+ }
+
+ /**
* Get the initial background color of this view.
* @hide
*/
@@ -409,12 +399,30 @@
}
/**
+ * A lightweight Drawable object to make the view drawing faster and keep this
+ * drawable masked by config_icon_mask.
+ * @hide
+ */
+ public abstract static class SplashscreenIconDrawable extends Drawable {
+ /**
+ * Prepare the animation if this drawable also be animatable.
+ * @param duration The animation duration.
+ * @param startListener The callback listener used to receive the start of the animation.
+ * @return true if this drawable object can also be animated and it can be played now.
+ */
+ protected boolean prepareAnimate(long duration, Consumer<Long> startListener) {
+ return false;
+ }
+ }
+
+ /**
* Use to create {@link SplashScreenView} object across process.
* @hide
*/
public static class SplashScreenViewParcelable implements Parcelable {
private int mIconSize;
private int mBackgroundColor;
+ private int mIconBackground;
private Bitmap mIconBitmap;
private int mBrandingWidth;
@@ -428,7 +436,7 @@
ViewGroup.LayoutParams params = view.getIconView().getLayoutParams();
mIconSize = params.height;
mBackgroundColor = view.getInitBackgroundColor();
-
+ mIconBackground = view.getIconBackgroundColor();
mIconBitmap = copyDrawable(view.getIconView().getBackground());
mBrandingBitmap = copyDrawable(view.getBrandingView().getBackground());
params = view.getBrandingView().getLayoutParams();
@@ -469,6 +477,7 @@
mBrandingBitmap = source.readTypedObject(Bitmap.CREATOR);
mIconAnimationStart = source.readLong();
mIconAnimationDuration = source.readLong();
+ mIconBackground = source.readInt();
}
@Override
@@ -486,6 +495,7 @@
dest.writeTypedObject(mBrandingBitmap, flags);
dest.writeLong(mIconAnimationStart);
dest.writeLong(mIconAnimationDuration);
+ dest.writeInt(mIconBackground);
}
public static final @NonNull Parcelable.Creator<SplashScreenViewParcelable> CREATOR =
@@ -519,5 +529,9 @@
int getBackgroundColor() {
return mBackgroundColor;
}
+
+ int getIconBackground() {
+ return mIconBackground;
+ }
}
}
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index 7ade05c..e6c911e 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -3,6 +3,9 @@
per-file *Chooser* = file:/packages/SystemUI/OWNERS
per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS
per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS
-per-file IVoice* = file:/core/java/android/service/voice/OWNERS
-per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS
+
+# Voice Interaction
+per-file *Assist* = file:/core/java/android/service/voice/OWNERS
+per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
+per-file *Voice* = file:/core/java/android/service/voice/OWNERS
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 6f377b9..93cde3d 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -353,8 +353,8 @@
mTouchSlop = configuration.getScaledPagingTouchSlop();
mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density);
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
- mLeftEdge = new EdgeEffect(context);
- mRightEdge = new EdgeEffect(context);
+ mLeftEdge = new EdgeEffect(context, attrs);
+ mRightEdge = new EdgeEffect(context, attrs);
mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
@@ -387,6 +387,28 @@
}
/**
+ * Returns the {@link EdgeEffect#getType()} for the edge effects.
+ * @return the {@link EdgeEffect#getType()} for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ @EdgeEffect.EdgeEffectType
+ public int getEdgeEffectType() {
+ // Both left and right edge have the same edge effect type
+ return mLeftEdge.getType();
+ }
+
+ /**
+ * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+ * @param type The edge effect type to use for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+ mLeftEdge.setType(type);
+ mRightEdge.setType(type);
+ invalidate();
+ }
+
+ /**
* Set a PagerAdapter that will supply views for this pager as needed.
*
* @param adapter Adapter to use
@@ -1891,7 +1913,7 @@
}
if (mIsBeingDragged) {
// Scroll to follow the motion event
- if (performDrag(x)) {
+ if (performDrag(x, y)) {
postInvalidateOnAnimation();
}
}
@@ -1918,6 +1940,17 @@
mIsBeingDragged = true;
requestParentDisallowInterceptTouchEvent(true);
setScrollState(SCROLL_STATE_DRAGGING);
+ } else if (mLeftEdge.getDistance() != 0
+ || mRightEdge.getDistance() != 0) {
+ // Caught the edge glow animation
+ mIsBeingDragged = true;
+ setScrollState(SCROLL_STATE_DRAGGING);
+ if (mLeftEdge.getDistance() != 0) {
+ mLeftEdge.onPullDistance(0f, 1 - mLastMotionY / getHeight());
+ }
+ if (mRightEdge.getDistance() != 0) {
+ mRightEdge.onPullDistance(0f, mLastMotionY / getHeight());
+ }
} else {
completeScroll(false);
mIsBeingDragged = false;
@@ -2009,7 +2042,7 @@
// Scroll to follow the motion event
final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(activePointerIndex);
- needsInvalidate |= performDrag(x);
+ needsInvalidate |= performDrag(x, ev.getY(activePointerIndex));
}
break;
case MotionEvent.ACTION_UP:
@@ -2080,12 +2113,43 @@
}
}
- private boolean performDrag(float x) {
+ /**
+ * If either of the horizontal edge glows are currently active, this consumes part or all of
+ * deltaX on the edge glow.
+ *
+ * @param deltaX The pointer motion, in pixels, in the horizontal direction, positive
+ * for moving down and negative for moving up.
+ * @param y The vertical position of the pointer.
+ * @return The amount of <code>deltaX</code> that has been consumed by the
+ * edge glow.
+ */
+ private float releaseHorizontalGlow(float deltaX, float y) {
+ // First allow releasing existing overscroll effect:
+ float consumed = 0;
+ float displacement = y / getHeight();
+ float pullDistance = (float) deltaX / getWidth();
+ if (mLeftEdge.getDistance() != 0) {
+ consumed = -mLeftEdge.onPullDistance(-pullDistance, 1 - displacement);
+ } else if (mRightEdge.getDistance() != 0) {
+ consumed = mRightEdge.onPullDistance(pullDistance, displacement);
+ }
+ return consumed * getWidth();
+ }
+
+ private boolean performDrag(float x, float y) {
boolean needsInvalidate = false;
+ final float dX = mLastMotionX - x;
final int width = getPaddedWidth();
- final float deltaX = mLastMotionX - x;
mLastMotionX = x;
+ final float releaseConsumed = releaseHorizontalGlow(dX, y);
+ final float deltaX = dX - releaseConsumed;
+ if (releaseConsumed != 0) {
+ needsInvalidate = true;
+ }
+ if (Math.abs(deltaX) < 0.0001f) { // ignore rounding errors from releaseHorizontalGlow()
+ return needsInvalidate;
+ }
final EdgeEffect startEdge;
final EdgeEffect endEdge;
@@ -2128,14 +2192,14 @@
if (scrollStart < startBound) {
if (startAbsolute) {
final float over = startBound - scrollStart;
- startEdge.onPull(Math.abs(over) / width);
+ startEdge.onPullDistance(over / width, 1 - y / getHeight());
needsInvalidate = true;
}
clampedScrollStart = startBound;
} else if (scrollStart > endBound) {
if (endAbsolute) {
final float over = scrollStart - endBound;
- endEdge.onPull(Math.abs(over) / width);
+ endEdge.onPullDistance(over / width, y / getHeight());
needsInvalidate = true;
}
clampedScrollStart = endBound;
@@ -2228,7 +2292,9 @@
*/
private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) {
int targetPage;
- if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) {
+ if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity
+ && mLeftEdge.getDistance() == 0 // don't fling while stretched
+ && mRightEdge.getDistance() == 0) {
targetPage = currentPage - (velocity < 0 ? mLeftIncr : 0);
} else {
final float truncator = currentPage >= mCurItem ? 0.4f : 0.6f;
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index a153fab..f49a834 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -149,7 +149,6 @@
"android_os_VintfRuntimeInfo.cpp",
"android_os_incremental_IncrementalManager.cpp",
"android_net_LocalSocketImpl.cpp",
- "android_net_NetworkUtils.cpp",
"android_service_DataLoaderService.cpp",
"android_util_AssetManager.cpp",
"android_util_Binder.cpp",
@@ -222,6 +221,7 @@
static_libs: [
"libasync_safe",
+ "libconnectivityframeworkutils",
"libbinderthreadstateutils",
"libdmabufinfo",
"libgif",
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 62767a6..de5df20 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -1450,6 +1450,42 @@
track->setPlayerIId(playerIId);
}
+static jint android_media_AudioTrack_getStartThresholdInFrames(JNIEnv *env, jobject thiz) {
+ sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+ if (lpTrack == nullptr) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Unable to retrieve AudioTrack pointer for getStartThresholdInFrames()");
+ return (jint)AUDIO_JAVA_ERROR;
+ }
+ const ssize_t result = lpTrack->getStartThresholdInFrames();
+ if (result <= 0) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Internal error detected in getStartThresholdInFrames() = %zd",
+ result);
+ return (jint)AUDIO_JAVA_ERROR;
+ }
+ return (jint)result; // this should be a positive value.
+}
+
+static jint android_media_AudioTrack_setStartThresholdInFrames(JNIEnv *env, jobject thiz,
+ jint startThresholdInFrames) {
+ sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+ if (lpTrack == nullptr) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Unable to retrieve AudioTrack pointer for setStartThresholdInFrames()");
+ return (jint)AUDIO_JAVA_ERROR;
+ }
+ // non-positive values of startThresholdInFrames are not allowed by the Java layer.
+ const ssize_t result = lpTrack->setStartThresholdInFrames(startThresholdInFrames);
+ if (result <= 0) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Internal error detected in setStartThresholdInFrames() = %zd",
+ result);
+ return (jint)AUDIO_JAVA_ERROR;
+ }
+ return (jint)result; // this should be a positive value.
+}
+
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
@@ -1530,6 +1566,10 @@
{"native_setLogSessionId", "(Ljava/lang/String;)V",
(void *)android_media_AudioTrack_setLogSessionId},
{"native_setPlayerIId", "(I)V", (void *)android_media_AudioTrack_setPlayerIId},
+ {"native_setStartThresholdInFrames", "(I)I",
+ (void *)android_media_AudioTrack_setStartThresholdInFrames},
+ {"native_getStartThresholdInFrames", "()I",
+ (void *)android_media_AudioTrack_getStartThresholdInFrames},
};
// field names found in android/media/AudioTrack.java
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 65b8b98..f54ffc5 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -498,19 +498,14 @@
transaction->setAnimationTransaction();
}
-static void nativeSetEarlyWakeup(JNIEnv* env, jclass clazz, jlong transactionObj) {
- auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->setEarlyWakeup();
-}
-
static void nativeSetEarlyWakeupStart(JNIEnv* env, jclass clazz, jlong transactionObj) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->setExplicitEarlyWakeupStart();
+ transaction->setEarlyWakeupStart();
}
static void nativeSetEarlyWakeupEnd(JNIEnv* env, jclass clazz, jlong transactionObj) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->setExplicitEarlyWakeupEnd();
+ transaction->setEarlyWakeupEnd();
}
static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -1737,8 +1732,6 @@
(void*)nativeMergeTransaction },
{"nativeSetAnimationTransaction", "(J)V",
(void*)nativeSetAnimationTransaction },
- {"nativeSetEarlyWakeup", "(J)V",
- (void*)nativeSetEarlyWakeup },
{"nativeSetEarlyWakeupStart", "(J)V",
(void*)nativeSetEarlyWakeupStart },
{"nativeSetEarlyWakeupEnd", "(J)V",
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index be17d92..0bed29b 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -825,7 +825,7 @@
PrepareDir(user_source, 0710, user_id ? AID_ROOT : AID_SHELL,
multiuser_get_uid(user_id, AID_EVERYBODY), fail_fn);
- bool isAppDataIsolationEnabled = GetBoolProperty(kVoldAppDataIsolation, true);
+ bool isAppDataIsolationEnabled = GetBoolProperty(kVoldAppDataIsolation, false);
if (mount_mode == MOUNT_EXTERNAL_PASS_THROUGH) {
const std::string pass_through_source = StringPrintf("/mnt/pass_through/%d", user_id);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5507261..45fd96a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4824,7 +4824,7 @@
TODO(159952358): STOPSHIP: This must be updated to the new "internal" protectionLevel
-->
<permission android:name="android.permission.DOMAIN_VERIFICATION_AGENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="internal|privileged" />
<!-- @SystemApi @hide Must be required by the domain verification agent's intent
BroadcastReceiver, to ensure that only the system can interact with it.
@@ -5546,6 +5546,10 @@
<permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS"
android:protectionLevel="signature|appPredictor" />
+ <!-- @hide @SystemApi Allows an application to manage app hibernation state. -->
+ <permission android:name="android.permission.MANAGE_APP_HIBERNATION"
+ android:protectionLevel="signature|installer" />
+
<!-- @hide @TestApi Allows apps to reset the state of {@link com.android.server.am.AppErrors}.
<p>CTS tests will use UiAutomation.adoptShellPermissionIdentity() to gain access. -->
<permission android:name="android.permission.RESET_APP_ERRORS"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9e1a085..5e95f94 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2280,6 +2280,10 @@
<!-- Place an drawable image in the bottom of the starting window, it can be used to
represent the branding of the application. -->
<attr name="windowSplashScreenBrandingImage" format="reference"/>
+ <!-- Set a background behind the splash screen icon. This is useful if there is not enough
+ contrast between the window background and the icon. Note the shape would also be
+ masking like an icon. -->
+ <attr name="windowSplashScreenIconBackgroundColor" format="color"/>
</declare-styleable>
<!-- The set of attributes that describe a AlertDialog's theme. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0318be7..140163e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2063,13 +2063,14 @@
requested. If it does support the feature, it will be as if the manifest didn't
request it at all. -->
<attr name="requiredNotFeature" format="string" />
- <!-- Optional: set of flags that should apply to this permission request. -->
+ <!-- Optional: set of flags that should apply to this permission request. Note that
+ these flags start at 0x4 to match PackageInfo.requestedPermissionsFlags. -->
<attr name="usesPermissionFlags">
<!-- Strong assertion by a developer that they will never use this
permission to derive the physical location of the device, even
when the app has been granted the ACCESS_FINE_LOCATION and/or
ACCESS_COARSE_LOCATION permissions. -->
- <flag name="neverForLocation" value="0x1" />
+ <flag name="neverForLocation" value="0x00010000" />
</attr>
</declare-styleable>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f6fee88..b4ef63f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -59,6 +59,7 @@
<item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_no_calling</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_call_strength</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_sensors_off</xliff:g></item>
</string-array>
@@ -96,6 +97,7 @@
<string translatable="false" name="status_bar_camera">camera</string>
<string translatable="false" name="status_bar_airplane">airplane</string>
<string translatable="false" name="status_bar_no_calling">no_calling</string>
+ <string translatable="false" name="status_bar_call_strength">call_strength</string>
<string translatable="false" name="status_bar_sensors_off">sensors_off</string>
<string translatable="false" name="status_bar_screen_record">screen_record</string>
@@ -4647,6 +4649,10 @@
<!-- WindowsManager JetPack display features -->
<string name="config_display_features" translatable="false" />
+ <!-- Map of System DeviceState supplied by DeviceStateManager to WM Jetpack posture. Must be in
+ the format [System DeviceState]:[WM Jetpack Posture], for example: "0:1". -->
+ <string-array name="config_device_state_postures" translatable="false" />
+
<!-- Aspect ratio of letterboxing for fixed orientation. Values <= 1.0 will be ignored.
Note: Activity min/max aspect ratio restrictions will still be respected.
Therefore this override can control the maximum screen area that can be occupied by
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 7bc4663..c3b35c8 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -252,5 +252,8 @@
<item type="id" name="remote_views_next_child" />
<!-- View tag associating a view with its stable id for potential recycling. -->
- <item type="id" name = "remote_views_stable_id" />
+ <item type="id" name="remote_views_stable_id" />
+
+ <!-- View tag associating a view with its overridden id, to ensure valid recycling only. -->
+ <item type="id" name="remote_views_override_id" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ba21679..3e5fad8 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3071,6 +3071,7 @@
<public name="windowSplashScreenAnimatedIcon"/>
<public name="windowSplashScreenAnimationDuration"/>
<public name="windowSplashScreenBrandingImage"/>
+ <public name="windowSplashScreenIconBackgroundColor"/>
<public name="splashScreenTheme" />
<public name="maxResizeWidth" />
<public name="maxResizeHeight" />
@@ -3090,6 +3091,7 @@
<public name="isAccessibilityTool"/>
<public name="attributionTags"/>
<public name="suppressesSpellChecker" />
+ <public name="usesPermissionFlags" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0228dfd..7ea762c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4592,7 +4592,7 @@
<string name="color_correction_feature_name">Color Correction</string>
<!-- Title of Reduce Brightness feature, shown in the warning dialog about the accessibility shortcut. [CHAR LIMIT=none] -->
- <string name="reduce_bright_colors_feature_name">Reduce brightness</string>
+ <string name="reduce_bright_colors_feature_name">Extra dim</string>
<!-- Text in toast to alert the user that the accessibility shortcut turned on an accessibility service. [CHAR LIMIT=none] -->
<string name="accessibility_shortcut_enabling_service">Held volume keys. <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g> turned on.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0f834933..1d74d85 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2977,6 +2977,7 @@
<java-symbol type="string" name="status_bar_clock" />
<java-symbol type="string" name="status_bar_airplane" />
<java-symbol type="string" name="status_bar_no_calling" />
+ <java-symbol type="string" name="status_bar_call_strength" />
<java-symbol type="string" name="status_bar_mobile" />
<java-symbol type="string" name="status_bar_ethernet" />
<java-symbol type="string" name="status_bar_vpn" />
@@ -3390,6 +3391,8 @@
<java-symbol type="drawable" name="ic_accessibility_color_correction" />
<java-symbol type="drawable" name="ic_accessibility_magnification" />
+ <java-symbol type="string" name="reduce_bright_colors_feature_name" />
+
<!-- com.android.internal.widget.RecyclerView -->
<java-symbol type="id" name="item_touch_helper_previous_elevation"/>
<java-symbol type="dimen" name="item_touch_helper_max_drag_scroll_per_frame"/>
@@ -4179,6 +4182,7 @@
<java-symbol type="dimen" name="default_background_blur_radius" />
<java-symbol type="array" name="config_keep_warming_services" />
<java-symbol type="string" name="config_display_features" />
+ <java-symbol type="array" name="config_device_state_postures" />
<java-symbol type="dimen" name="controls_thumbnail_image_max_height" />
<java-symbol type="dimen" name="controls_thumbnail_image_max_width" />
@@ -4321,8 +4325,11 @@
<java-symbol type="bool" name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_allowed" />
<java-symbol type="bool" name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_default" />
+ <!-- Ids for RemoteViews -->
<java-symbol type="id" name="remote_views_next_child" />
<java-symbol type="id" name="remote_views_stable_id" />
+ <java-symbol type="id" name="remote_views_override_id" />
+
<!-- View and control prompt -->
<java-symbol type="drawable" name="ic_accessibility_24dp" />
<java-symbol type="string" name="view_and_control_notification_title" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 87ae162..bf42da0 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -170,6 +170,7 @@
<item name="windowSplashScreenBackground">@color/transparent</item>
<item name="windowSplashScreenAnimatedIcon">@null</item>
<item name="windowSplashScreenBrandingImage">@null</item>
+ <item name="windowSplashScreenIconBackgroundColor">@color/transparent</item>
<item name="windowClipToOutline">false</item>
<item name="windowFrame">@null</item>
<item name="windowNoTitle">false</item>
diff --git a/core/tests/coretests/BstatsTestApp/AndroidManifest.xml b/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
index 1e6bdc6..fcb1e71 100644
--- a/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
+++ b/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
@@ -19,7 +19,7 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="25"/>
+ <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="26"/>
<application>
<activity android:name=".TestActivity"
diff --git a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
new file mode 100644
index 0000000..dfc9013
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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 android.hardware.display;
+
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.RemoteException;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DisplayManagerGlobalTest {
+
+ private static final long ALL_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
+
+ @Mock
+ private IDisplayManager mDisplayManager;
+
+ @Mock
+ private DisplayManager.DisplayListener mListener;
+
+ @Captor
+ private ArgumentCaptor<IDisplayManagerCallback> mCallbackCaptor;
+
+ private Context mContext;
+ private DisplayManagerGlobal mDisplayManagerGlobal;
+ private Handler mHandler;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+ Mockito.when(mDisplayManager.getPreferredWideGamutColorSpaceId()).thenReturn(0);
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mHandler = mContext.getMainThreadHandler();
+ mDisplayManagerGlobal = new DisplayManagerGlobal(mDisplayManager);
+ }
+
+ @Test
+ public void testDisplayListenerIsCalled_WhenDisplayEventOccurs() throws RemoteException {
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler, ALL_DISPLAY_EVENTS);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), anyLong());
+ IDisplayManagerCallback callback = mCallbackCaptor.getValue();
+
+ int displayId = 1;
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
+ waitForHandler();
+ Mockito.verify(mListener).onDisplayAdded(eq(displayId));
+ Mockito.verifyNoMoreInteractions(mListener);
+
+ Mockito.reset(mListener);
+ callback.onDisplayEvent(1, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+ waitForHandler();
+ Mockito.verify(mListener).onDisplayChanged(eq(displayId));
+ Mockito.verifyNoMoreInteractions(mListener);
+
+ Mockito.reset(mListener);
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+ waitForHandler();
+ Mockito.verify(mListener).onDisplayRemoved(eq(displayId));
+ Mockito.verifyNoMoreInteractions(mListener);
+ }
+
+ @Test
+ public void testDisplayListenerIsNotCalled_WhenClientIsNotSubscribed() throws RemoteException {
+ // First we subscribe to all events in order to test that the subsequent calls to
+ // registerDisplayListener will update the event mask.
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler, ALL_DISPLAY_EVENTS);
+ Mockito.verify(mDisplayManager)
+ .registerCallbackWithEventMask(mCallbackCaptor.capture(), anyLong());
+ IDisplayManagerCallback callback = mCallbackCaptor.getValue();
+
+ int displayId = 1;
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
+ ALL_DISPLAY_EVENTS & ~DisplayManager.EVENT_FLAG_DISPLAY_ADDED);
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
+ waitForHandler();
+ Mockito.verifyZeroInteractions(mListener);
+
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
+ ALL_DISPLAY_EVENTS & ~DisplayManager.EVENT_FLAG_DISPLAY_CHANGED);
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+ waitForHandler();
+ Mockito.verifyZeroInteractions(mListener);
+
+ mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
+ ALL_DISPLAY_EVENTS & ~DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+ callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+ waitForHandler();
+ Mockito.verifyZeroInteractions(mListener);
+ }
+
+ private void waitForHandler() {
+ mHandler.runWithScissors(() -> { }, 0);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
index 4fe7d70..13d529c 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -124,6 +124,7 @@
sContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
sTestPkgUid = sContext.getPackageManager().getPackageUid(TEST_PKG, 0);
+ executeCmd("cmd deviceidle whitelist +" + TEST_PKG);
final ArrayMap<String, String> desiredConstants = new ArrayMap<>();
desiredConstants.put(KEY_TRACK_CPU_TIMES_BY_PROC_STATE, Boolean.toString(true));
@@ -134,6 +135,7 @@
@AfterClass
public static void tearDownOnce() throws Exception {
+ executeCmd("cmd deviceidle whitelist -" + TEST_PKG);
if (sBatteryStatsConstsUpdated) {
Settings.Global.putString(sContext.getContentResolver(),
Settings.Global.BATTERY_STATS_CONSTANTS, sOriginalBatteryStatsConsts);
@@ -382,7 +384,7 @@
}
@Test
- @SkipPresubmit("b/180015146 flakey")
+ @SkipPresubmit("b/183225190 flaky")
public void testCpuFreqTimes_stateFgService() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
Log.w(TAG, "Skipping " + testName.getMethodName()
@@ -515,7 +517,6 @@
}
@Test
- @SkipPresubmit("b/180015146")
public void testCpuFreqTimes_trackingDisabled() throws Exception {
if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
Log.w(TAG, "Skipping " + testName.getMethodName()
@@ -625,7 +626,7 @@
splitter.setString(settingsDump);
String next;
while (splitter.hasNext()) {
- next = splitter.next();
+ next = splitter.next().trim();
if (next.startsWith(key)) {
return next.split("=")[1];
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 31cdaeb..1924e5f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -492,6 +492,9 @@
<permission name="android.permission.UPDATE_FONTS" />
<!-- Permission required for hotword detection service CTS tests -->
<permission name="android.permission.MANAGE_HOTWORD_DETECTION" />
+ <permission name="android.permission.MANAGE_APP_HIBERNATION"/>
+ <!-- Permission required for CTS test - ResourceObserverNativeTest -->
+ <permission name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index da5162b..6fcd8d0 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -275,6 +275,8 @@
* Call to apply a stretch effect to any child SurfaceControl layers
*
* TODO: Fold this into positionChanged & have HWUI do the ASurfaceControl calls?
+ * (njawad) update to consume different stretch parameters for horizontal/vertical stretch
+ * to ensure SkiaGLRenderEngine can also apply the same stretch to a surface
*
* @hide
*/
@@ -718,7 +720,7 @@
/** @hide */
public boolean stretch(float left, float top, float right, float bottom,
- float vecX, float vecY, float maxStretchAmount) {
+ float vecX, float vecY, float maxStretchAmountX, float maxStretchAmountY) {
if (Float.isInfinite(vecX) || Float.isNaN(vecX)) {
throw new IllegalArgumentException("vecX must be a finite, non-NaN value " + vecX);
}
@@ -730,9 +732,13 @@
"Stretch region must not be empty, got "
+ new RectF(left, top, right, bottom).toString());
}
- if (maxStretchAmount <= 0.0f) {
+ if (maxStretchAmountX <= 0.0f) {
throw new IllegalArgumentException(
- "The max stretch amount must be >0, got " + maxStretchAmount);
+ "The max horizontal stretch amount must be >0, got " + maxStretchAmountX);
+ }
+ if (maxStretchAmountY <= 0.0f) {
+ throw new IllegalArgumentException(
+ "The max vertical stretch amount must be >0, got " + maxStretchAmountY);
}
return nStretch(
mNativeRenderNode,
@@ -742,7 +748,8 @@
bottom,
vecX,
vecY,
- maxStretchAmount
+ maxStretchAmountX,
+ maxStretchAmountY
);
}
@@ -1695,7 +1702,7 @@
@CriticalNative
private static native boolean nStretch(long renderNode, float left, float top, float right,
- float bottom, float vecX, float vecY, float maxStretch);
+ float bottom, float vecX, float vecY, float maxStretchX, float maxStretchY);
@CriticalNative
private static native boolean nHasShadow(long renderNode);
diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
index b57f7af..94d5c22 100644
--- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java
+++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
@@ -26,8 +26,8 @@
import android.graphics.Paint;
import android.graphics.RecordingCanvas;
import android.graphics.animation.RenderNodeAnimator;
-import android.util.ArraySet;
import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
@@ -41,8 +41,8 @@
private static final int ENTER_ANIM_DURATION = 450;
private static final int EXIT_ANIM_DURATION = 300;
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
- private static final TimeInterpolator PATH_INTERPOLATOR =
- new PathInterpolator(.2f, 0, 0, 1f);
+ private static final Interpolator FAST_OUT_LINEAR_IN =
+ new PathInterpolator(0.4f, 0f, 1f, 1f);
private Consumer<RippleAnimationSession> mOnSessionEnd;
private final AnimationProperties<Float, Paint> mProperties;
private AnimationProperties<CanvasProperty<Float>, CanvasProperty<Paint>> mCanvasProperties;
@@ -59,7 +59,7 @@
mSparkle.addUpdateListener(anim -> {
final long now = AnimationUtils.currentAnimationTimeMillis();
final long elapsed = now - mStartTime - ENTER_ANIM_DURATION;
- final float phase = (float) elapsed / 30000f;
+ final float phase = (float) elapsed / 800;
mProperties.getShader().setNoisePhase(phase);
notifyUpdate();
});
@@ -174,7 +174,7 @@
private void startAnimation(Animator expand) {
expand.setDuration(ENTER_ANIM_DURATION);
expand.addListener(new AnimatorListener(this));
- expand.setInterpolator(LINEAR_INTERPOLATOR);
+ expand.setInterpolator(FAST_OUT_LINEAR_IN);
expand.start();
if (!mSparkle.isRunning()) {
mSparkle.start();
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index fb2b9b3..d5711c8 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -914,7 +914,7 @@
shader.setColor(color);
shader.setOrigin(w / 2, y / 2);
shader.setTouch(x, y);
- shader.setResolution(w, h);
+ shader.setResolution(w, h, mState.mDensity);
shader.setNoisePhase(0);
shader.setRadius(radius);
shader.setProgress(.0f);
diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java
index ea9ba32..5dd250c 100644
--- a/graphics/java/android/graphics/drawable/RippleShader.java
+++ b/graphics/java/android/graphics/drawable/RippleShader.java
@@ -20,13 +20,15 @@
import android.graphics.Color;
import android.graphics.RuntimeShader;
import android.graphics.Shader;
+import android.util.DisplayMetrics;
final class RippleShader extends RuntimeShader {
private static final String SHADER_UNIFORMS = "uniform vec2 in_origin;\n"
+ "uniform vec2 in_touch;\n"
+ "uniform float in_progress;\n"
+ "uniform float in_maxRadius;\n"
- + "uniform vec2 in_resolution;\n"
+ + "uniform vec2 in_resolutionScale;\n"
+ + "uniform vec2 in_noiseScale;\n"
+ "uniform float in_hasMask;\n"
+ "uniform float in_noisePhase;\n"
+ "uniform vec4 in_color;\n"
@@ -40,18 +42,15 @@
+ "}"
+ "const float PI = 3.1415926535897932384626;\n"
+ "\n"
- + "float threshold(float v, float l, float h) {\n"
- + " return step(l, v) * (1.0 - step(h, v));\n"
- + "}\n"
- + "\n"
+ "float sparkles(vec2 uv, float t) {\n"
+ " float n = triangleNoise(uv);\n"
+ " float s = 0.0;\n"
+ " for (float i = 0; i < 4; i += 1) {\n"
- + " float l = i * 0.25;\n"
- + " float h = l + 0.005;\n"
- + " float o = abs(sin(0.1 * PI * (t + i)));\n"
- + " s += threshold(n + o, l, h);\n"
+ + " float l = i * 0.01;\n"
+ + " float h = l + 0.1;\n"
+ + " float o = smoothstep(n - l, h, n);\n"
+ + " o *= abs(sin(PI * o * (t + 0.55 * i)));\n"
+ + " s += o;\n"
+ " }\n"
+ " return saturate(s);\n"
+ "}\n"
@@ -83,7 +82,9 @@
+ " vec2 center = mix(in_touch, in_origin, fadeIn);\n"
+ " float ring = getRingMask(p, center, in_maxRadius, fadeIn);\n"
+ " float alpha = min(fadeIn, 1. - fadeOutNoise);\n"
- + " float sparkle = sparkles(p, in_noisePhase) * ring * alpha;\n"
+ + " vec2 uv = p * in_resolutionScale;\n"
+ + " vec2 densityUv = uv - mod(uv, in_noiseScale);\n"
+ + " float sparkle = sparkles(densityUv, in_noisePhase) * ring * alpha;\n"
+ " float fade = min(fadeIn, 1. - fadeOutRipple);\n"
+ " vec4 circle = in_color * (softCircle(p, center, in_maxRadius "
+ " * fadeIn, 0.2) * fade);\n"
@@ -135,7 +136,10 @@
color.green(), color.blue(), color.alpha()});
}
- public void setResolution(float w, float h) {
- setUniform("in_resolution", w, h);
+ public void setResolution(float w, float h, int density) {
+ float noiseScale = 0.8f;
+ float densityScale = density * DisplayMetrics.DENSITY_DEFAULT_SCALE * 0.5f * noiseScale;
+ setUniform("in_resolutionScale", new float[] {1f / w, 1f / h});
+ setUniform("in_noiseScale", new float[] {densityScale / w, densityScale / h});
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
index d9d5300..9d8a5ef 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
@@ -124,7 +124,7 @@
resetAll();
// Public key operations get diverted to the default provider.
- if (opmode == Cipher.ENCRYPT_MODE
+ if (!(key instanceof AndroidKeyStorePrivateKey)
&& (key instanceof PrivateKey || key instanceof PublicKey)) {
try {
mCipher = Cipher.getInstance(getTransform());
@@ -186,7 +186,7 @@
resetAll();
// Public key operations get diverted to the default provider.
- if (opmode == Cipher.ENCRYPT_MODE
+ if (!(key instanceof AndroidKeyStorePrivateKey)
&& (key instanceof PrivateKey || key instanceof PublicKey)) {
try {
mCipher = Cipher.getInstance(getTransform());
@@ -216,7 +216,7 @@
resetAll();
// Public key operations get diverted to the default provider.
- if (opmode == Cipher.ENCRYPT_MODE
+ if (!(key instanceof AndroidKeyStorePrivateKey)
&& (key instanceof PrivateKey || key instanceof PublicKey)) {
try {
mCipher = Cipher.getInstance(getTransform());
diff --git a/libs/WindowManager/Jetpack/Android.bp b/libs/WindowManager/Jetpack/Android.bp
index d8f00bb..dc4b563 100644
--- a/libs/WindowManager/Jetpack/Android.bp
+++ b/libs/WindowManager/Jetpack/Android.bp
@@ -30,13 +30,20 @@
java_library {
name: "androidx.window.sidecar",
- srcs: ["src/androidx/window/sidecar/**/*.java", "src/androidx/window/util/**/*.java"],
+ srcs: [
+ "src/androidx/window/sidecar/**/*.java",
+ "src/androidx/window/util/**/*.java",
+ "src/androidx/window/common/**/*.java",
+ ],
static_libs: ["window-sidecar"],
installable: true,
sdk_version: "core_platform",
system_ext_specific: true,
- libs: ["framework", "androidx.annotation_annotation",],
- required: ["androidx.window.sidecar.xml",],
+ libs: [
+ "framework",
+ "androidx.annotation_annotation",
+ ],
+ required: ["androidx.window.sidecar.xml"],
}
prebuilt_etc {
@@ -58,13 +65,20 @@
java_library {
name: "androidx.window.extensions",
- srcs: ["src/androidx/window/extensions/**/*.java", "src/androidx/window/util/**/*.java"],
+ srcs: [
+ "src/androidx/window/extensions/**/*.java",
+ "src/androidx/window/util/**/*.java",
+ "src/androidx/window/common/**/*.java",
+ ],
static_libs: ["window-extensions"],
installable: true,
sdk_version: "core_platform",
system_ext_specific: true,
- libs: ["framework", "androidx.annotation_annotation",],
- required: ["androidx.window.extensions.xml",],
+ libs: [
+ "framework",
+ "androidx.annotation_annotation",
+ ],
+ required: ["androidx.window.extensions.xml"],
}
prebuilt_etc {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java
new file mode 100644
index 0000000..e6ad011
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java
@@ -0,0 +1,128 @@
+/*
+ * 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 androidx.window.common;
+
+import static androidx.window.util.ExtensionHelper.isZero;
+
+import android.annotation.Nullable;
+import android.graphics.Rect;
+
+import androidx.annotation.NonNull;
+
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/** Wrapper for both Extension and Sidecar versions of DisplayFeature. */
+final class CommonDisplayFeature implements DisplayFeature {
+ private static final Pattern FEATURE_PATTERN =
+ Pattern.compile("([a-z]+)-\\[(\\d+),(\\d+),(\\d+),(\\d+)]");
+
+ private static final String FEATURE_TYPE_FOLD = "fold";
+ private static final String FEATURE_TYPE_HINGE = "hinge";
+
+ // TODO(b/183049815): Support feature strings that include the state of the feature.
+ /**
+ * Parses a display feature from a string.
+ *
+ * @throws IllegalArgumentException if the provided string is improperly formatted or could not
+ * otherwise be parsed.
+ *
+ * @see #FEATURE_PATTERN
+ */
+ @NonNull
+ static CommonDisplayFeature parseFromString(@NonNull String string) {
+ Matcher featureMatcher = FEATURE_PATTERN.matcher(string);
+ if (!featureMatcher.matches()) {
+ throw new IllegalArgumentException("Malformed feature description format: " + string);
+ }
+ try {
+ String featureType = featureMatcher.group(1);
+ int type;
+ switch (featureType) {
+ case FEATURE_TYPE_FOLD:
+ type = 1 /* TYPE_FOLD */;
+ break;
+ case FEATURE_TYPE_HINGE:
+ type = 2 /* TYPE_HINGE */;
+ break;
+ default: {
+ throw new IllegalArgumentException("Malformed feature type: " + featureType);
+ }
+ }
+
+ int left = Integer.parseInt(featureMatcher.group(2));
+ int top = Integer.parseInt(featureMatcher.group(3));
+ int right = Integer.parseInt(featureMatcher.group(4));
+ int bottom = Integer.parseInt(featureMatcher.group(5));
+ Rect featureRect = new Rect(left, top, right, bottom);
+ if (isZero(featureRect)) {
+ throw new IllegalArgumentException("Feature has empty bounds: " + string);
+ }
+
+ return new CommonDisplayFeature(type, null, featureRect);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Malformed feature description: " + string, e);
+ }
+ }
+
+ private final int mType;
+ @Nullable
+ private final Integer mState;
+ @NonNull
+ private final Rect mRect;
+
+ CommonDisplayFeature(int type, @Nullable Integer state, @NonNull Rect rect) {
+ this.mType = type;
+ this.mState = state;
+ if (rect.width() == 0 && rect.height() == 0) {
+ throw new IllegalArgumentException(
+ "Display feature rectangle cannot have zero width and height simultaneously.");
+ }
+ this.mRect = rect;
+ }
+
+ public int getType() {
+ return mType;
+ }
+
+ /** Returns the state of the feature, or {@code null} if the feature has no state. */
+ @Nullable
+ public Integer getState() {
+ return mState;
+ }
+
+ @NonNull
+ public Rect getRect() {
+ return mRect;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ CommonDisplayFeature that = (CommonDisplayFeature) o;
+ return mType == that.mType
+ && Objects.equals(mState, that.mState)
+ && mRect.equals(that.mRect);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mType, mState, mRect);
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerPostureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerPostureProducer.java
new file mode 100644
index 0000000..fa9a5a8
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerPostureProducer.java
@@ -0,0 +1,93 @@
+/*
+ * 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 androidx.window.common;
+
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.devicestate.DeviceStateManager;
+import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
+import android.util.Log;
+import android.util.SparseIntArray;
+
+import androidx.window.util.BaseDataProducer;
+
+import com.android.internal.R;
+
+import java.util.Optional;
+
+/**
+ * An implementation of {@link androidx.window.util.DataProducer} that returns the device's posture
+ * by mapping the state returned from {@link DeviceStateManager} to values provided in the resources
+ * config at {@link R.array#config_device_state_postures}.
+ */
+public final class DeviceStateManagerPostureProducer extends BaseDataProducer<Integer> {
+ private static final String TAG = "ConfigDevicePostureProducer";
+ private static final boolean DEBUG = false;
+
+ private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray();
+
+ private int mCurrentDeviceState = INVALID_DEVICE_STATE;
+
+ private final DeviceStateCallback mDeviceStateCallback = (state) -> {
+ mCurrentDeviceState = state;
+ notifyDataChanged();
+ };
+
+ public DeviceStateManagerPostureProducer(@NonNull Context context) {
+ String[] deviceStatePosturePairs = context.getResources()
+ .getStringArray(R.array.config_device_state_postures);
+ for (String deviceStatePosturePair : deviceStatePosturePairs) {
+ String[] deviceStatePostureMapping = deviceStatePosturePair.split(":");
+ if (deviceStatePostureMapping.length != 2) {
+ if (DEBUG) {
+ Log.e(TAG, "Malformed device state posture pair: " + deviceStatePosturePair);
+ }
+ continue;
+ }
+
+ int deviceState;
+ int posture;
+ try {
+ deviceState = Integer.parseInt(deviceStatePostureMapping[0]);
+ posture = Integer.parseInt(deviceStatePostureMapping[1]);
+ } catch (NumberFormatException e) {
+ if (DEBUG) {
+ Log.e(TAG, "Failed to parse device state or posture: " + deviceStatePosturePair,
+ e);
+ }
+ continue;
+ }
+
+ mDeviceStateToPostureMap.put(deviceState, posture);
+ }
+
+ if (mDeviceStateToPostureMap.size() > 0) {
+ context.getSystemService(DeviceStateManager.class)
+ .registerCallback(context.getMainExecutor(), mDeviceStateCallback);
+ }
+ }
+
+ @Override
+ @Nullable
+ public Optional<Integer> getData() {
+ final int posture = mDeviceStateToPostureMap.get(mCurrentDeviceState, -1);
+ return posture != -1 ? Optional.of(posture) : Optional.empty();
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java
new file mode 100644
index 0000000..b6c4c43
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java
@@ -0,0 +1,36 @@
+/*
+ * 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 androidx.window.common;
+
+import android.annotation.Nullable;
+import android.graphics.Rect;
+
+import androidx.annotation.NonNull;
+
+/** Wrapper for both Extension and Sidecar versions of DisplayFeature. */
+public interface DisplayFeature {
+ /** Returns the type of the feature. */
+ int getType();
+
+ /** Returns the state of the feature, or {@code null} if the feature has no state. */
+ @Nullable
+ Integer getState();
+
+ /** Returns the bounds of the feature. */
+ @NonNull
+ Rect getRect();
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java
new file mode 100644
index 0000000..cd2cadc
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java
@@ -0,0 +1,74 @@
+/*
+ * 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 androidx.window.common;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.window.util.BaseDataProducer;
+
+import com.android.internal.R;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Implementation of {@link androidx.window.util.DataProducer} that produces
+ * {@link CommonDisplayFeature} parsed from a string stored in the resources config at
+ * {@link R.string#config_display_features}.
+ */
+public final class ResourceConfigDisplayFeatureProducer extends
+ BaseDataProducer<List<DisplayFeature>> {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "ResourceConfigDisplayFeatureProducer";
+
+ private final Context mContext;
+
+ public ResourceConfigDisplayFeatureProducer(@NonNull Context context) {
+ mContext = context;
+ }
+
+ @Override
+ @Nullable
+ public Optional<List<DisplayFeature>> getData() {
+ String displayFeaturesString = mContext.getResources().getString(
+ R.string.config_display_features);
+ if (TextUtils.isEmpty(displayFeaturesString)) {
+ return Optional.empty();
+ }
+
+ List<DisplayFeature> features = new ArrayList<>();
+ String[] featureStrings = displayFeaturesString.split(";");
+ for (String featureString : featureStrings) {
+ CommonDisplayFeature feature;
+ try {
+ feature = CommonDisplayFeature.parseFromString(featureString);
+ } catch (IllegalArgumentException e) {
+ if (DEBUG) {
+ Log.w(TAG, "Failed to parse display feature: " + featureString, e);
+ }
+ continue;
+ }
+ features.add(feature);
+ }
+ return Optional.of(features);
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDevicePostureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDevicePostureProducer.java
new file mode 100644
index 0000000..2026df3
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDevicePostureProducer.java
@@ -0,0 +1,96 @@
+/*
+ * 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 androidx.window.common;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+
+import androidx.window.util.BaseDataProducer;
+
+import java.util.Optional;
+
+/**
+ * Implementation of {@link androidx.window.util.DataProducer} that provides the device posture
+ * as an {@link Integer} from a value stored in {@link Settings}.
+ */
+public final class SettingsDevicePostureProducer extends BaseDataProducer<Integer> {
+ private static final String DEVICE_POSTURE = "device_posture";
+
+ private final Uri mDevicePostureUri =
+ Settings.Global.getUriFor(DEVICE_POSTURE);
+
+ private final ContentResolver mResolver;
+ private final ContentObserver mObserver;
+ private boolean mRegisteredObservers;
+
+ public SettingsDevicePostureProducer(@NonNull Context context) {
+ mResolver = context.getContentResolver();
+ mObserver = new SettingsObserver();
+ }
+
+ @Override
+ @Nullable
+ public Optional<Integer> getData() {
+ int posture = Settings.Global.getInt(mResolver, DEVICE_POSTURE, -1);
+ return posture == -1 ? Optional.empty() : Optional.of(posture);
+ }
+
+ /**
+ * Registers settings observers, if needed. When settings observers are registered for this
+ * producer callbacks for changes in data will be triggered.
+ */
+ public void registerObserversIfNeeded() {
+ if (mRegisteredObservers) {
+ return;
+ }
+ mRegisteredObservers = true;
+ mResolver.registerContentObserver(mDevicePostureUri, false /* notifyForDescendants */,
+ mObserver /* ContentObserver */);
+ }
+
+ /**
+ * Unregisters settings observers, if needed. When settings observers are unregistered for this
+ * producer callbacks for changes in data will not be triggered.
+ */
+ public void unregisterObserversIfNeeded() {
+ if (!mRegisteredObservers) {
+ return;
+ }
+ mRegisteredObservers = false;
+ mResolver.unregisterContentObserver(mObserver);
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ SettingsObserver() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mDevicePostureUri.equals(uri)) {
+ notifyDataChanged();
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java
new file mode 100644
index 0000000..0406626
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java
@@ -0,0 +1,125 @@
+/*
+ * 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 androidx.window.common;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.window.util.BaseDataProducer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Implementation of {@link androidx.window.util.DataProducer} that produces
+ * {@link CommonDisplayFeature} parsed from a string stored in {@link Settings}.
+ */
+public final class SettingsDisplayFeatureProducer
+ extends BaseDataProducer<List<DisplayFeature>> {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "SettingsDisplayFeatureProducer";
+ private static final String DISPLAY_FEATURES = "display_features";
+
+ private final Uri mDisplayFeaturesUri =
+ Settings.Global.getUriFor(DISPLAY_FEATURES);
+
+ private final ContentResolver mResolver;
+ private final ContentObserver mObserver;
+ private boolean mRegisteredObservers;
+
+ public SettingsDisplayFeatureProducer(@NonNull Context context) {
+ mResolver = context.getContentResolver();
+ mObserver = new SettingsObserver();
+ }
+
+ @Override
+ @Nullable
+ public Optional<List<DisplayFeature>> getData() {
+ String displayFeaturesString = Settings.Global.getString(mResolver, DISPLAY_FEATURES);
+ if (displayFeaturesString == null) {
+ return Optional.empty();
+ }
+
+ List<DisplayFeature> features = new ArrayList<>();
+ if (TextUtils.isEmpty(displayFeaturesString)) {
+ return Optional.of(features);
+ }
+ String[] featureStrings = displayFeaturesString.split(";");
+
+ for (String featureString : featureStrings) {
+ CommonDisplayFeature feature;
+ try {
+ feature = CommonDisplayFeature.parseFromString(featureString);
+ } catch (IllegalArgumentException e) {
+ if (DEBUG) {
+ Log.w(TAG, "Failed to parse display feature: " + featureString, e);
+ }
+ continue;
+ }
+ features.add(feature);
+ }
+ return Optional.of(features);
+ }
+
+ /**
+ * Registers settings observers, if needed. When settings observers are registered for this
+ * producer callbacks for changes in data will be triggered.
+ */
+ public void registerObserversIfNeeded() {
+ if (mRegisteredObservers) {
+ return;
+ }
+ mRegisteredObservers = true;
+ mResolver.registerContentObserver(mDisplayFeaturesUri, false /* notifyForDescendants */,
+ mObserver /* ContentObserver */);
+ }
+
+ /**
+ * Unregisters settings observers, if needed. When settings observers are unregistered for this
+ * producer callbacks for changes in data will not be triggered.
+ */
+ public void unregisterObserversIfNeeded() {
+ if (!mRegisteredObservers) {
+ return;
+ }
+ mRegisteredObservers = false;
+ mResolver.unregisterContentObserver(mObserver);
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ SettingsObserver() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mDisplayFeaturesUri.equals(uri)) {
+ notifyDataChanged();
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java
index 5c91cf41..ce9be6a 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java
@@ -27,11 +27,17 @@
import android.util.Log;
import androidx.annotation.NonNull;
-import androidx.window.util.BaseDisplayFeature;
-import androidx.window.util.SettingsConfigProvider;
+import androidx.window.common.DeviceStateManagerPostureProducer;
+import androidx.window.common.DisplayFeature;
+import androidx.window.common.ResourceConfigDisplayFeatureProducer;
+import androidx.window.common.SettingsDevicePostureProducer;
+import androidx.window.common.SettingsDisplayFeatureProducer;
+import androidx.window.util.DataProducer;
+import androidx.window.util.PriorityDataProducer;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* Reference implementation of androidx.window.extensions OEM interface for use with
@@ -41,23 +47,46 @@
* production builds since the interface can still change before reaching stable version.
* Please refer to {@link androidx.window.sidecar.SampleSidecarImpl} instead.
*/
-class SampleExtensionImpl extends StubExtension implements
- SettingsConfigProvider.StateChangeCallback {
+class SampleExtensionImpl extends StubExtension {
private static final String TAG = "SampleExtension";
- private final SettingsConfigProvider mConfigProvider;
+ private final SettingsDevicePostureProducer mSettingsDevicePostureProducer;
+ private final DataProducer<Integer> mDevicePostureProducer;
+
+ private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer;
+ private final DataProducer<List<DisplayFeature>> mDisplayFeatureProducer;
SampleExtensionImpl(Context context) {
- mConfigProvider = new SettingsConfigProvider(context, this);
+ mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context);
+ mDevicePostureProducer = new PriorityDataProducer<>(List.of(
+ mSettingsDevicePostureProducer,
+ new DeviceStateManagerPostureProducer(context)
+ ));
+
+ mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context);
+ mDisplayFeatureProducer = new PriorityDataProducer<>(List.of(
+ mSettingsDisplayFeatureProducer,
+ new ResourceConfigDisplayFeatureProducer(context)
+ ));
+
+ mDevicePostureProducer.addDataChangedCallback(this::onDevicePostureChanged);
+ mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
}
- @Override
- public void onDevicePostureChanged() {
- updateDeviceState(new ExtensionDeviceState(mConfigProvider.getDeviceState()));
+ private void onDevicePostureChanged() {
+ updateDeviceState(new ExtensionDeviceState(getDevicePosture()));
+
+ // Trigger a change in display features as the posture will be used in place of the feature
+ // state if the state is left unset by the producer.
+ onDisplayFeaturesChanged();
}
- @Override
- public void onDisplayFeaturesChanged() {
+ private int getDevicePosture() {
+ Optional<Integer> posture = mDevicePostureProducer.getData();
+ return posture.orElse(ExtensionDeviceState.POSTURE_UNKNOWN);
+ }
+
+ private void onDisplayFeaturesChanged() {
for (Activity activity : getActivitiesListeningForLayoutChanges()) {
ExtensionWindowLayoutInfo newLayout = getWindowLayoutInfo(activity);
updateWindowLayout(activity, newLayout);
@@ -84,13 +113,20 @@
return features;
}
- List<BaseDisplayFeature> storedFeatures = mConfigProvider.getDisplayFeatures();
- for (BaseDisplayFeature baseFeature : storedFeatures) {
- Rect featureRect = baseFeature.getRect();
- rotateRectToDisplayRotation(displayId, featureRect);
- transformToWindowSpaceRect(activity, featureRect);
- features.add(new ExtensionFoldingFeature(featureRect, baseFeature.getType(),
- baseFeature.getState()));
+ Optional<List<DisplayFeature>> storedFeatures = mDisplayFeatureProducer.getData();
+ if (storedFeatures.isPresent()) {
+ int posture = getDevicePosture();
+
+ for (DisplayFeature baseFeature : storedFeatures.get()) {
+ Rect featureRect = baseFeature.getRect();
+ rotateRectToDisplayRotation(displayId, featureRect);
+ transformToWindowSpaceRect(activity, featureRect);
+
+ Integer featureState = baseFeature.getState();
+
+ features.add(new ExtensionFoldingFeature(featureRect, baseFeature.getType(),
+ featureState == null ? posture : featureState));
+ }
}
return features;
}
@@ -98,9 +134,11 @@
@Override
protected void onListenersChanged() {
if (hasListeners()) {
- mConfigProvider.registerObserversIfNeeded();
+ mSettingsDevicePostureProducer.registerObserversIfNeeded();
+ mSettingsDisplayFeatureProducer.registerObserversIfNeeded();
} else {
- mConfigProvider.unregisterObserversIfNeeded();
+ mSettingsDevicePostureProducer.unregisterObserversIfNeeded();
+ mSettingsDisplayFeatureProducer.unregisterObserversIfNeeded();
}
onDevicePostureChanged();
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
index d3700f8..ece198c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
@@ -29,33 +29,53 @@
import android.util.Log;
import androidx.annotation.NonNull;
-import androidx.window.util.BaseDisplayFeature;
-import androidx.window.util.SettingsConfigProvider;
+import androidx.window.common.DeviceStateManagerPostureProducer;
+import androidx.window.common.DisplayFeature;
+import androidx.window.common.ResourceConfigDisplayFeatureProducer;
+import androidx.window.common.SettingsDevicePostureProducer;
+import androidx.window.common.SettingsDisplayFeatureProducer;
+import androidx.window.util.DataProducer;
+import androidx.window.util.PriorityDataProducer;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* Reference implementation of androidx.window.sidecar OEM interface for use with
* WindowManager Jetpack.
*/
-class SampleSidecarImpl extends StubSidecar implements
- SettingsConfigProvider.StateChangeCallback {
+class SampleSidecarImpl extends StubSidecar {
private static final String TAG = "SampleSidecar";
- private final SettingsConfigProvider mConfigProvider;
+ private final SettingsDevicePostureProducer mSettingsDevicePostureProducer;
+ private final DataProducer<Integer> mDevicePostureProducer;
+
+ private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer;
+ private final DataProducer<List<DisplayFeature>> mDisplayFeatureProducer;
SampleSidecarImpl(Context context) {
- mConfigProvider = new SettingsConfigProvider(context, this);
+ mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context);
+ mDevicePostureProducer = new PriorityDataProducer<>(List.of(
+ mSettingsDevicePostureProducer,
+ new DeviceStateManagerPostureProducer(context)
+ ));
+
+ mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context);
+ mDisplayFeatureProducer = new PriorityDataProducer<>(List.of(
+ mSettingsDisplayFeatureProducer,
+ new ResourceConfigDisplayFeatureProducer(context)
+ ));
+
+ mDevicePostureProducer.addDataChangedCallback(this::onDevicePostureChanged);
+ mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
}
- @Override
- public void onDevicePostureChanged() {
+ private void onDevicePostureChanged() {
updateDeviceState(getDeviceState());
}
- @Override
- public void onDisplayFeaturesChanged() {
+ private void onDisplayFeaturesChanged() {
for (IBinder windowToken : getWindowsListeningForLayoutChanges()) {
SidecarWindowLayoutInfo newLayout = getWindowLayoutInfo(windowToken);
updateWindowLayout(windowToken, newLayout);
@@ -65,8 +85,10 @@
@NonNull
@Override
public SidecarDeviceState getDeviceState() {
+ Optional<Integer> posture = mDevicePostureProducer.getData();
+
SidecarDeviceState deviceState = new SidecarDeviceState();
- deviceState.posture = mConfigProvider.getDeviceState();
+ deviceState.posture = posture.orElse(SidecarDeviceState.POSTURE_UNKNOWN);
return deviceState;
}
@@ -96,15 +118,17 @@
return features;
}
- List<BaseDisplayFeature> storedFeatures = mConfigProvider.getDisplayFeatures();
- for (BaseDisplayFeature baseFeature : storedFeatures) {
- SidecarDisplayFeature feature = new SidecarDisplayFeature();
- Rect featureRect = baseFeature.getRect();
- rotateRectToDisplayRotation(displayId, featureRect);
- transformToWindowSpaceRect(activity, featureRect);
- feature.setRect(featureRect);
- feature.setType(baseFeature.getType());
- features.add(feature);
+ Optional<List<DisplayFeature>> storedFeatures = mDisplayFeatureProducer.getData();
+ if (storedFeatures.isPresent()) {
+ for (DisplayFeature baseFeature : storedFeatures.get()) {
+ SidecarDisplayFeature feature = new SidecarDisplayFeature();
+ Rect featureRect = baseFeature.getRect();
+ rotateRectToDisplayRotation(displayId, featureRect);
+ transformToWindowSpaceRect(activity, featureRect);
+ feature.setRect(featureRect);
+ feature.setType(baseFeature.getType());
+ features.add(feature);
+ }
}
return features;
}
@@ -112,9 +136,11 @@
@Override
protected void onListenersChanged() {
if (hasListeners()) {
- mConfigProvider.registerObserversIfNeeded();
+ mSettingsDevicePostureProducer.registerObserversIfNeeded();
+ mSettingsDisplayFeatureProducer.registerObserversIfNeeded();
} else {
- mConfigProvider.unregisterObserversIfNeeded();
+ mSettingsDevicePostureProducer.unregisterObserversIfNeeded();
+ mSettingsDisplayFeatureProducer.unregisterObserversIfNeeded();
}
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java
new file mode 100644
index 0000000..0a46703451
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java
@@ -0,0 +1,52 @@
+/*
+ * 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 androidx.window.util;
+
+import androidx.annotation.NonNull;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Base class that provides the implementation for the callback mechanism of the
+ * {@link DataProducer} API.
+ *
+ * @param <T> The type of data this producer returns through {@link #getData()}.
+ */
+public abstract class BaseDataProducer<T> implements DataProducer<T> {
+ private final Set<Runnable> mCallbacks = new LinkedHashSet<>();
+
+ @Override
+ public final void addDataChangedCallback(@NonNull Runnable callback) {
+ mCallbacks.add(callback);
+ }
+
+ @Override
+ public final void removeDataChangedCallback(@NonNull Runnable callback) {
+ mCallbacks.remove(callback);
+ }
+
+ /**
+ * Called to notify all registered callbacks that the data provided by {@link #getData()} has
+ * changed.
+ */
+ protected void notifyDataChanged() {
+ for (Runnable callback : mCallbacks) {
+ callback.run();
+ }
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDisplayFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDisplayFeature.java
deleted file mode 100644
index b74a2a4..0000000
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDisplayFeature.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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 androidx.window.util;
-
-import android.graphics.Rect;
-
-import androidx.annotation.NonNull;
-
-/** Wrapper for both Extension and Sidecar versions of DisplayFeature. */
-public class BaseDisplayFeature {
- private final int mType;
- private final int mState;
- @NonNull
- public final Rect mRect;
-
- public BaseDisplayFeature(int type, int state, @NonNull Rect rect) {
- this.mType = type;
- this.mState = state;
- if (rect.width() == 0 && rect.height() == 0) {
- throw new IllegalArgumentException(
- "Display feature rectangle cannot have zero width and height simultaneously.");
- }
- this.mRect = rect;
- }
-
- public int getType() {
- return mType;
- }
-
- public int getState() {
- return mState;
- }
-
- @NonNull
- public Rect getRect() {
- return mRect;
- }
-}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/DataProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/util/DataProducer.java
new file mode 100644
index 0000000..d4d1a23
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/DataProducer.java
@@ -0,0 +1,43 @@
+/*
+ * 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 androidx.window.util;
+
+import android.annotation.NonNull;
+
+import java.util.Optional;
+
+/**
+ * Produces data through {@link #getData()} and provides a mechanism for receiving a callback when
+ * the data managed by the produces has changed.
+ *
+ * @param <T> The type of data this producer returns through {@link #getData()}.
+ */
+public interface DataProducer<T> {
+ /**
+ * Returns the data currently stored in the provider, or {@link Optional#empty()} if the
+ * provider has no data.
+ */
+ Optional<T> getData();
+
+ /**
+ * Adds a callback to be notified when the data returned from {@link #getData()} has changed.
+ */
+ void addDataChangedCallback(@NonNull Runnable callback);
+
+ /** Removes a callback previously added with {@link #addDataChangedCallback(Runnable)}. */
+ void removeDataChangedCallback(@NonNull Runnable callback);
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/PriorityDataProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/util/PriorityDataProducer.java
new file mode 100644
index 0000000..990ae20
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/PriorityDataProducer.java
@@ -0,0 +1,56 @@
+/*
+ * 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 androidx.window.util;
+
+import android.annotation.Nullable;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Implementation of {@link DataProducer} that delegates calls to {@link #getData()} to the list of
+ * provided child producers.
+ * <p>
+ * The value returned is based on the precedence of the supplied children where the producer with
+ * index 0 has a higher precedence than producers that come later in the list. When a producer with
+ * a higher precedence has a non-empty value returned from {@link #getData()}, its value will be
+ * returned from an instance of this class, ignoring all other producers with lower precedence.
+ *
+ * @param <T> The type of data this producer returns through {@link #getData()}.
+ */
+public final class PriorityDataProducer<T> extends BaseDataProducer<T> {
+ private final List<DataProducer<T>> mChildProducers;
+
+ public PriorityDataProducer(List<DataProducer<T>> childProducers) {
+ mChildProducers = childProducers;
+ for (DataProducer<T> childProducer : mChildProducers) {
+ childProducer.addDataChangedCallback(this::notifyDataChanged);
+ }
+ }
+
+ @Nullable
+ @Override
+ public Optional<T> getData() {
+ for (DataProducer<T> childProducer : mChildProducers) {
+ final Optional<T> data = childProducer.getData();
+ if (data.isPresent()) {
+ return data;
+ }
+ }
+ return Optional.empty();
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/SettingsConfigProvider.java b/libs/WindowManager/Jetpack/src/androidx/window/util/SettingsConfigProvider.java
deleted file mode 100644
index 6dd190c..0000000
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/SettingsConfigProvider.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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 androidx.window.util;
-
-import static androidx.window.util.ExtensionHelper.isZero;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Device and display feature state provider that uses Settings as the source.
- */
-public final class SettingsConfigProvider extends ContentObserver {
- private static final String TAG = "SettingsConfigProvider";
- private static final String DEVICE_POSTURE = "device_posture";
- private static final String DISPLAY_FEATURES = "display_features";
-
- private static final Pattern FEATURE_PATTERN =
- Pattern.compile("([a-z]+)-\\[(\\d+),(\\d+),(\\d+),(\\d+)]");
-
- private static final String FEATURE_TYPE_FOLD = "fold";
- private static final String FEATURE_TYPE_HINGE = "hinge";
-
- private final Uri mDevicePostureUri =
- Settings.Global.getUriFor(DEVICE_POSTURE);
- private final Uri mDisplayFeaturesUri =
- Settings.Global.getUriFor(DISPLAY_FEATURES);
- private final Context mContext;
- private final ContentResolver mResolver;
- private final StateChangeCallback mCallback;
- private boolean mRegisteredObservers;
-
- public SettingsConfigProvider(@NonNull Context context, @NonNull StateChangeCallback callback) {
- super(new Handler(Looper.getMainLooper()));
- mContext = context;
- mResolver = context.getContentResolver();
- mCallback = callback;
- }
-
- /**
- * Registers the content observers for Settings keys that store device state and display feature
- * configurations.
- */
- public void registerObserversIfNeeded() {
- if (mRegisteredObservers) {
- return;
- }
- mRegisteredObservers = true;
- mResolver.registerContentObserver(mDevicePostureUri, false /* notifyForDescendants */,
- this /* ContentObserver */);
- mResolver.registerContentObserver(mDisplayFeaturesUri, false /* notifyForDescendants */,
- this /* ContentObserver */);
- }
-
- /**
- * Unregisters the content observers that are tracking the state changes.
- * @see #registerObserversIfNeeded()
- */
- public void unregisterObserversIfNeeded() {
- if (!mRegisteredObservers) {
- return;
- }
- mRegisteredObservers = false;
- mResolver.unregisterContentObserver(this);
- }
-
- /**
- * Gets the device posture int stored in Settings.
- */
- public int getDeviceState() {
- return Settings.Global.getInt(mResolver, DEVICE_POSTURE,
- 0 /* POSTURE_UNKNOWN */);
- }
-
- /**
- * Gets the list of all display feature configs stored in Settings. Uses a custom
- * {@link BaseDisplayFeature} class to report the config to be translated for actual
- * containers in Sidecar or Extensions.
- */
- public List<BaseDisplayFeature> getDisplayFeatures() {
- List<BaseDisplayFeature> features = new ArrayList<>();
- String displayFeaturesString = Settings.Global.getString(mResolver, DISPLAY_FEATURES);
- if (TextUtils.isEmpty(displayFeaturesString)) {
- displayFeaturesString = mContext.getResources().getString(
- R.string.config_display_features);
- }
- if (TextUtils.isEmpty(displayFeaturesString)) {
- return features;
- }
- String[] featureStrings = displayFeaturesString.split(";");
-
- int deviceState = getDeviceState();
-
- for (String featureString : featureStrings) {
- Matcher featureMatcher = FEATURE_PATTERN.matcher(featureString);
- if (!featureMatcher.matches()) {
- Log.e(TAG, "Malformed feature description format: " + featureString);
- continue;
- }
- try {
- String featureType = featureMatcher.group(1);
- int type;
- switch (featureType) {
- case FEATURE_TYPE_FOLD:
- type = 1 /* TYPE_FOLD */;
- break;
- case FEATURE_TYPE_HINGE:
- type = 2 /* TYPE_HINGE */;
- break;
- default: {
- Log.e(TAG, "Malformed feature type: " + featureType);
- continue;
- }
- }
-
- int left = Integer.parseInt(featureMatcher.group(2));
- int top = Integer.parseInt(featureMatcher.group(3));
- int right = Integer.parseInt(featureMatcher.group(4));
- int bottom = Integer.parseInt(featureMatcher.group(5));
- Rect featureRect = new Rect(left, top, right, bottom);
- if (!isZero(featureRect)) {
- BaseDisplayFeature feature = new BaseDisplayFeature(type, deviceState,
- featureRect);
- features.add(feature);
- } else {
- Log.w(TAG, "Read empty feature");
- }
- } catch (NumberFormatException e) {
- Log.e(TAG, "Malformed feature description: " + featureString);
- }
- }
- return features;
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (uri == null) {
- return;
- }
-
- if (mDevicePostureUri.equals(uri)) {
- mCallback.onDevicePostureChanged();
- mCallback.onDisplayFeaturesChanged();
- return;
- }
- if (mDisplayFeaturesUri.equals(uri)) {
- mCallback.onDisplayFeaturesChanged();
- }
- }
-
- /**
- * Callback that notifies about device or display feature state changes.
- */
- public interface StateChangeCallback {
- /**
- * Notifies about the device state update.
- */
- void onDevicePostureChanged();
-
- /**
- * Notifies about the display feature config update.
- */
- void onDisplayFeaturesChanged();
- }
-}
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 1b5dc8b..3f03302 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -38,6 +38,14 @@
path: "src",
}
+filegroup {
+ name: "wm_shell-aidls",
+ srcs: [
+ "src/**/*.aidl",
+ ],
+ path: "src",
+}
+
// TODO(b/168581922) protologtool do not support kotlin(*.kt)
filegroup {
name: "wm_shell-sources-kt",
@@ -98,7 +106,7 @@
":wm_shell_protolog_src",
// TODO(b/168581922) protologtool do not support kotlin(*.kt)
":wm_shell-sources-kt",
- "src/**/I*.aidl",
+ ":wm_shell-aidls",
],
resource_dirs: [
"res",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
index eaed24d..d451f4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
@@ -47,21 +47,7 @@
private final ShellExecutor mMainExecutor;
private final HandlerImpl mImpl = new HandlerImpl();
- public static ShellCommandHandler create(
- ShellTaskOrganizer shellTaskOrganizer,
- Optional<LegacySplitScreenController> legacySplitScreenOptional,
- Optional<SplitScreenController> splitScreenOptional,
- Optional<Pip> pipOptional,
- Optional<OneHandedController> oneHandedOptional,
- Optional<HideDisplayCutoutController> hideDisplayCutout,
- Optional<AppPairsController> appPairsOptional,
- ShellExecutor mainExecutor) {
- return new ShellCommandHandlerImpl(shellTaskOrganizer, legacySplitScreenOptional,
- splitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
- appPairsOptional, mainExecutor).mImpl;
- }
-
- private ShellCommandHandlerImpl(
+ public ShellCommandHandlerImpl(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
@@ -80,6 +66,10 @@
mMainExecutor = mainExecutor;
}
+ public ShellCommandHandler asShellCommandHandler() {
+ return mImpl;
+ }
+
/** Dumps WM Shell internal state. */
private void dump(PrintWriter pw) {
mShellTaskOrganizer.dump(pw, "");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index 85bd24c..6f4550c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -26,7 +26,7 @@
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.pip.phone.PipTouchHandler;
import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.startingsurface.StartingSurface;
+import com.android.wm.shell.startingsurface.StartingWindowController;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -47,44 +47,20 @@
private final FullscreenTaskListener mFullscreenTaskListener;
private final ShellExecutor mMainExecutor;
private final Transitions mTransitions;
- private final Optional<StartingSurface> mStartingSurfaceOptional;
+ private final StartingWindowController mStartingWindow;
private final InitImpl mImpl = new InitImpl();
- public static ShellInit create(DisplayImeController displayImeController,
+ public ShellInitImpl(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
- Optional<StartingSurface> startingSurfaceOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
- ShellExecutor mainExecutor) {
- return new ShellInitImpl(displayImeController,
- dragAndDropController,
- shellTaskOrganizer,
- legacySplitScreenOptional,
- splitScreenOptional,
- appPairsOptional,
- startingSurfaceOptional,
- pipTouchHandlerOptional,
- fullscreenTaskListener,
- transitions,
- mainExecutor).mImpl;
- }
-
- private ShellInitImpl(DisplayImeController displayImeController,
- DragAndDropController dragAndDropController,
- ShellTaskOrganizer shellTaskOrganizer,
- Optional<LegacySplitScreenController> legacySplitScreenOptional,
- Optional<SplitScreenController> splitScreenOptional,
- Optional<AppPairsController> appPairsOptional,
- Optional<StartingSurface> startingSurfaceOptional,
- Optional<PipTouchHandler> pipTouchHandlerOptional,
- FullscreenTaskListener fullscreenTaskListener,
- Transitions transitions,
+ StartingWindowController startingWindow,
ShellExecutor mainExecutor) {
mDisplayImeController = displayImeController;
mDragAndDropController = dragAndDropController;
@@ -96,17 +72,21 @@
mPipTouchHandlerOptional = pipTouchHandlerOptional;
mTransitions = transitions;
mMainExecutor = mainExecutor;
- mStartingSurfaceOptional = startingSurfaceOptional;
+ mStartingWindow = startingWindow;
+ }
+
+ public ShellInit asShellInit() {
+ return mImpl;
}
private void init() {
// Start listening for display changes
mDisplayImeController.startMonitorDisplays();
+ // Setup the shell organizer
mShellTaskOrganizer.addListenerForType(
mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
- mStartingSurfaceOptional.ifPresent(mShellTaskOrganizer::initStartingSurface);
- // Register the shell organizer
+ mShellTaskOrganizer.initStartingWindow(mStartingWindow);
mShellTaskOrganizer.registerOrganizer();
mAppPairsOptional.ifPresent(AppPairsController::onOrganizerRegistered);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index fcb53cd..94d13ea 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -48,7 +48,7 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.sizecompatui.SizeCompatUIController;
-import com.android.wm.shell.startingsurface.StartingSurface;
+import com.android.wm.shell.startingsurface.StartingWindowController;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -133,7 +133,7 @@
private final ArraySet<LocusIdListener> mLocusIdListeners = new ArraySet<>();
private final Object mLock = new Object();
- private StartingSurface mStartingSurface;
+ private StartingWindowController mStartingWindow;
/**
* In charge of showing size compat UI. Can be {@code null} if device doesn't support size
@@ -184,8 +184,8 @@
/**
* @hide
*/
- public void initStartingSurface(StartingSurface startingSurface) {
- mStartingSurface = startingSurface;
+ public void initStartingWindow(StartingWindowController startingWindow) {
+ mStartingWindow = startingWindow;
}
/**
@@ -302,23 +302,23 @@
@Override
public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
- if (mStartingSurface != null) {
- mStartingSurface.addStartingWindow(info, appToken);
+ if (mStartingWindow != null) {
+ mStartingWindow.addStartingWindow(info, appToken);
}
}
@Override
public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
boolean playRevealAnimation) {
- if (mStartingSurface != null) {
- mStartingSurface.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
+ if (mStartingWindow != null) {
+ mStartingWindow.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
}
}
@Override
public void copySplashScreenView(int taskId) {
- if (mStartingSurface != null) {
- mStartingSurface.copySplashScreenView(taskId);
+ if (mStartingWindow != null) {
+ mStartingWindow.copySplashScreenView(taskId);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ExecutorUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ExecutorUtils.java
new file mode 100644
index 0000000..b29058b
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ExecutorUtils.java
@@ -0,0 +1,64 @@
+/*
+ * 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 com.android.wm.shell.common;
+
+import android.Manifest;
+import android.util.Slog;
+
+import java.util.function.Consumer;
+
+/**
+ * Helpers for working with executors
+ */
+public class ExecutorUtils {
+
+ /**
+ * Checks that the caller has the MANAGE_ACTIVITY_TASKS permission and executes the given
+ * callback.
+ */
+ public static <T> void executeRemoteCallWithTaskPermission(RemoteCallable<T> controllerInstance,
+ String log, Consumer<T> callback) {
+ executeRemoteCallWithTaskPermission(controllerInstance, log, callback,
+ false /* blocking */);
+ }
+
+ /**
+ * Checks that the caller has the MANAGE_ACTIVITY_TASKS permission and executes the given
+ * callback.
+ */
+ public static <T> void executeRemoteCallWithTaskPermission(RemoteCallable<T> controllerInstance,
+ String log, Consumer<T> callback, boolean blocking) {
+ if (controllerInstance == null) return;
+
+ final RemoteCallable<T> controller = controllerInstance;
+ controllerInstance.getContext().enforceCallingPermission(
+ Manifest.permission.MANAGE_ACTIVITY_TASKS, log);
+ if (blocking) {
+ try {
+ controllerInstance.getRemoteCallExecutor().executeBlocking(() -> {
+ callback.accept((T) controller);
+ });
+ } catch (InterruptedException e) {
+ Slog.e("ExecutorUtils", "Remote call failed", e);
+ }
+ } else {
+ controllerInstance.getRemoteCallExecutor().execute(() -> {
+ callback.accept((T) controller);
+ });
+ }
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/common/RemoteCallable.java
similarity index 61%
copy from packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
copy to libs/WindowManager/Shell/src/com/android/wm/shell/common/RemoteCallable.java
index 54242be..30f535b 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/RemoteCallable.java
@@ -14,12 +14,21 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package com.android.wm.shell.common;
+
+import android.content.Context;
/**
- * Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
+ * An interface for controllers that can receive remote calls.
*/
-oneway interface ISplitScreenListener {
- void onStagePositionChanged(int stage, int position);
- void onTaskStageChanged(int taskId, int stage, boolean visible);
-}
+public interface RemoteCallable<T> {
+ /**
+ * Returns a context used for permission checking.
+ */
+ Context getContext();
+
+ /**
+ * Returns the executor to post the handler callback to.
+ */
+ ShellExecutor getRemoteCallExecutor();
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index aab2334..9a09ca4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -235,7 +235,7 @@
mStarter.startShortcut(packageName, id, stage, position, opts, user);
} else {
mStarter.startIntent(intent.getParcelableExtra(EXTRA_PENDING_INTENT),
- mContext, null, stage, position, opts);
+ null, stage, position, opts);
}
}
@@ -295,7 +295,7 @@
@Nullable Bundle options);
void startShortcut(String packageName, String shortcutId, @StageType int stage,
@StagePosition int position, @Nullable Bundle options, UserHandle user);
- void startIntent(PendingIntent intent, Context context, Intent fillInIntent,
+ void startIntent(PendingIntent intent, Intent fillInIntent,
@StageType int stage, @StagePosition int position,
@Nullable Bundle options);
void enterSplitScreen(int taskId, boolean leftOrTop);
@@ -337,9 +337,8 @@
}
@Override
- public void startIntent(PendingIntent intent, Context context,
- @Nullable Intent fillInIntent, int stage, int position,
- @Nullable Bundle options) {
+ public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, int stage,
+ int position, @Nullable Bundle options) {
try {
intent.send(mContext, 0, fillInIntent, null, null, null, options);
} catch (PendingIntent.CanceledException e) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl
similarity index 66%
copy from packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
copy to libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl
index 54242be..008b508 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl
@@ -14,12 +14,20 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package com.android.wm.shell.onehanded;
/**
- * Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
+ * Interface that is exposed to remote callers to manipulate the OneHanded feature.
*/
-oneway interface ISplitScreenListener {
- void onStagePositionChanged(int stage, int position);
- void onTaskStageChanged(int taskId, int stage, boolean visible);
+interface IOneHanded {
+
+ /**
+ * Enters one handed mode.
+ */
+ oneway void startOneHanded() = 1;
+
+ /**
+ * Exits one handed mode.
+ */
+ oneway void stopOneHanded() = 2;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
index 4f31c37..a7e9a01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
@@ -26,6 +26,14 @@
*/
@ExternalThread
public interface OneHanded {
+
+ /**
+ * Returns a binder that can be passed to an external process to manipulate OneHanded.
+ */
+ default IOneHanded createExternalInterface() {
+ return null;
+ }
+
/**
* Return one handed settings enabled or not.
*/
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 c1a93ce..25968eb 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
@@ -18,6 +18,10 @@
import static android.os.UserHandle.USER_CURRENT;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+
+import android.Manifest;
+import android.annotation.BinderThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.om.IOverlayManager;
@@ -43,6 +47,8 @@
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ExecutorUtils;
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
@@ -54,7 +60,7 @@
/**
* Manages and manipulates the one handed states, transitions, and gesture for phones.
*/
-public class OneHandedController {
+public class OneHandedController implements RemoteCallable<OneHandedController> {
private static final String TAG = "OneHandedController";
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
@@ -247,6 +253,16 @@
return mImpl;
}
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mMainExecutor;
+ }
+
/**
* Set one handed enabled or disabled when user update settings
*/
@@ -576,8 +592,22 @@
}
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
@ExternalThread
private class OneHandedImpl implements OneHanded {
+ private IOneHandedImpl mIOneHanded;
+
+ @Override
+ public IOneHanded createExternalInterface() {
+ if (mIOneHanded != null) {
+ mIOneHanded.invalidate();
+ }
+ mIOneHanded = new IOneHandedImpl(OneHandedController.this);
+ return mIOneHanded;
+ }
+
@Override
public boolean isOneHandedEnabled() {
// This is volatile so return directly
@@ -646,4 +676,39 @@
});
}
}
+
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class IOneHandedImpl extends IOneHanded.Stub {
+ private OneHandedController mController;
+
+ IOneHandedImpl(OneHandedController controller) {
+ mController = controller;
+ }
+
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mController = null;
+ }
+
+ @Override
+ public void startOneHanded() {
+ executeRemoteCallWithTaskPermission(mController, "startOneHanded",
+ (controller) -> {
+ controller.startOneHanded();
+ });
+ }
+
+ @Override
+ public void stopOneHanded() {
+ executeRemoteCallWithTaskPermission(mController, "stopOneHanded",
+ (controller) -> {
+ controller.stopOneHanded();
+ });
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
new file mode 100644
index 0000000..a6ffa6e
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
@@ -0,0 +1,63 @@
+/*
+ * 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 com.android.wm.shell.pip;
+
+import android.app.PictureInPictureParams;
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
+
+import com.android.wm.shell.pip.IPipAnimationListener;
+
+/**
+ * Interface that is exposed to remote callers to manipulate the Pip feature.
+ */
+interface IPip {
+
+ /**
+ * Notifies that Activity is about to be swiped to home with entering PiP transition and
+ * queries the destination bounds for PiP depends on Launcher's rotation and shelf height.
+ *
+ * @param componentName ComponentName represents the Activity
+ * @param activityInfo ActivityInfo tied to the Activity
+ * @param pictureInPictureParams PictureInPictureParams tied to the Activity
+ * @param launcherRotation Launcher rotation to calculate the PiP destination bounds
+ * @param shelfHeight Shelf height of launcher to calculate the PiP destination bounds
+ * @return destination bounds the PiP window should land into
+ */
+ Rect startSwipePipToHome(in ComponentName componentName, in ActivityInfo activityInfo,
+ in PictureInPictureParams pictureInPictureParams,
+ int launcherRotation, int shelfHeight) = 1;
+
+ /**
+ * Notifies the swiping Activity to PiP onto home transition is finished
+ *
+ * @param componentName ComponentName represents the Activity
+ * @param destinationBounds the destination bounds the PiP window lands into
+ */
+ oneway void stopSwipePipToHome(in ComponentName componentName, in Rect destinationBounds) = 2;
+
+ /**
+ * Sets listener to get pinned stack animation callbacks.
+ */
+ oneway void setPinnedStackAnimationListener(IPipAnimationListener listener) = 3;
+
+ /**
+ * Sets the shelf height and visibility.
+ */
+ oneway void setShelfHeight(boolean visible, int shelfHeight) = 4;
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IPinnedStackAnimationListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
similarity index 68%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/IPinnedStackAnimationListener.aidl
rename to libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
index 97aa512..2569b78 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IPinnedStackAnimationListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package com.android.wm.shell.pip;
/**
- * Listener interface that Launcher attaches to SystemUI to get
- * pinned stack animation callbacks.
+ * Listener interface that Launcher attaches to SystemUI to get Pip animation callbacks.
*/
-oneway interface IPinnedStackAnimationListener {
+oneway interface IPipAnimationListener {
/**
- * Notifies the pinned stack animation is started.
+ * Notifies the listener that the Pip animation is started.
*/
- void onPinnedStackAnimationStarted();
+ void onPipAnimationStarted();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
index d14c3e3c..6d4773b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
@@ -16,15 +16,10 @@
package com.android.wm.shell.pip;
-import android.annotation.Nullable;
-import android.app.PictureInPictureParams;
-import android.content.ComponentName;
-import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import com.android.wm.shell.common.annotations.ExternalThread;
-import com.android.wm.shell.pip.phone.PipTouchHandler;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -34,6 +29,14 @@
*/
@ExternalThread
public interface Pip {
+
+ /**
+ * Returns a binder that can be passed to an external process to manipulate PIP.
+ */
+ default IPip createExternalInterface() {
+ return null;
+ }
+
/**
* Expand PIP, it's possible that specific request to activate the window via Alt-tab.
*/
@@ -109,30 +112,6 @@
default void showPictureInPictureMenu() {}
/**
- * Called by Launcher when swiping an auto-pip enabled Activity to home starts
- * @param componentName {@link ComponentName} represents the Activity entering PiP
- * @param activityInfo {@link ActivityInfo} tied to the Activity
- * @param pictureInPictureParams {@link PictureInPictureParams} tied to the Activity
- * @param launcherRotation Rotation Launcher is in
- * @param shelfHeight Shelf height when landing PiP window onto Launcher
- * @return Destination bounds of PiP window based on the parameters passed in
- */
- default Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
- PictureInPictureParams pictureInPictureParams,
- int launcherRotation, int shelfHeight) {
- return null;
- }
-
- /**
- * Called by Launcher when swiping an auto-pip enable Activity to home finishes
- * @param componentName {@link ComponentName} represents the Activity entering PiP
- * @param destinationBounds Destination bounds of PiP window
- */
- default void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
- return;
- }
-
- /**
* Called by NavigationBar in order to listen in for PiP bounds change. This is mostly used
* for times where the PiP bounds could conflict with SystemUI elements, such as a stashed
* PiP and the Back-from-Edge gesture.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 1f5c136..debdceb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -21,8 +21,10 @@
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
+import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.PictureInPictureParams;
@@ -33,6 +35,7 @@
import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -44,6 +47,7 @@
import android.view.WindowManagerGlobal;
import android.window.WindowContainerTransaction;
+import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -51,9 +55,13 @@
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.ExecutorUtils;
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.pip.IPip;
+import com.android.wm.shell.pip.IPipAnimationListener;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
@@ -71,7 +79,8 @@
/**
* Manages the picture-in-picture (PIP) UI and states for Phones.
*/
-public class PipController implements PipTransitionController.PipTransitionCallback {
+public class PipController implements PipTransitionController.PipTransitionCallback,
+ RemoteCallable<PipController> {
private static final String TAG = "PipController";
private Context mContext;
@@ -85,12 +94,12 @@
private PipBoundsState mPipBoundsState;
private PipTouchHandler mTouchHandler;
private PipTransitionController mPipTransitionController;
- protected final PipImpl mImpl = new PipImpl();
+ protected final PipImpl mImpl;
private final Rect mTmpInsetBounds = new Rect();
private boolean mIsInFixedRotation;
- private Consumer<Boolean> mPinnedStackAnimationRecentsCallback;
+ private IPipAnimationListener mPinnedStackAnimationRecentsCallback;
protected PhonePipMenuController mMenuController;
protected PipTaskOrganizer mPipTaskOrganizer;
@@ -264,6 +273,7 @@
}
mContext = context;
+ mImpl = new PipImpl();
mWindowManagerShellWrapper = windowManagerShellWrapper;
mDisplayController = displayController;
mPipBoundsAlgorithm = pipBoundsAlgorithm;
@@ -366,6 +376,16 @@
});
}
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mMainExecutor;
+ }
+
private void onConfigurationChanged(Configuration newConfig) {
mPipBoundsAlgorithm.onConfigurationChanged(mContext);
mTouchHandler.onConfigurationChanged();
@@ -474,7 +494,7 @@
mPipTaskOrganizer.setOneShotAnimationType(animationType);
}
- private void setPinnedStackAnimationListener(Consumer<Boolean> callback) {
+ private void setPinnedStackAnimationListener(IPipAnimationListener callback) {
mPinnedStackAnimationRecentsCallback = callback;
}
@@ -503,7 +523,11 @@
// Disable touches while the animation is running
mTouchHandler.setTouchEnabled(false);
if (mPinnedStackAnimationRecentsCallback != null) {
- mPinnedStackAnimationRecentsCallback.accept(true);
+ try {
+ mPinnedStackAnimationRecentsCallback.onPipAnimationStarted();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to call onPinnedStackAnimationStarted()", e);
+ }
}
}
@@ -629,7 +653,21 @@
mPipInputConsumer.dump(pw, innerPrefix);
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
private class PipImpl implements Pip {
+ private IPipImpl mIPip;
+
+ @Override
+ public IPip createExternalInterface() {
+ if (mIPip != null) {
+ mIPip.invalidate();
+ }
+ mIPip = new IPipImpl(PipController.this);
+ return mIPip;
+ }
+
@Override
public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
mMainExecutor.execute(() -> {
@@ -687,13 +725,6 @@
}
@Override
- public void setPinnedStackAnimationListener(Consumer<Boolean> callback) {
- mMainExecutor.execute(() -> {
- PipController.this.setPinnedStackAnimationListener(callback);
- });
- }
-
- @Override
public void setPinnedStackAnimationType(int animationType) {
mMainExecutor.execute(() -> {
PipController.this.setPinnedStackAnimationType(animationType);
@@ -715,29 +746,6 @@
}
@Override
- public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
- PictureInPictureParams pictureInPictureParams, int launcherRotation,
- int shelfHeight) {
- Rect[] result = new Rect[1];
- try {
- mMainExecutor.executeBlocking(() -> {
- result[0] = PipController.this.startSwipePipToHome(componentName, activityInfo,
- pictureInPictureParams, launcherRotation, shelfHeight);
- });
- } catch (InterruptedException e) {
- Slog.e(TAG, "Failed to start swipe pip to home");
- }
- return result[0];
- }
-
- @Override
- public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
- mMainExecutor.execute(() -> {
- PipController.this.stopSwipePipToHome(componentName, destinationBounds);
- });
- }
-
- @Override
public void dump(PrintWriter pw) {
try {
mMainExecutor.executeBlocking(() -> {
@@ -748,4 +756,89 @@
}
}
}
+
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class IPipImpl extends IPip.Stub {
+ private PipController mController;
+ private IPipAnimationListener mListener;
+ private final IBinder.DeathRecipient mListenerDeathRecipient =
+ new IBinder.DeathRecipient() {
+ @Override
+ @BinderThread
+ public void binderDied() {
+ final PipController controller = mController;
+ controller.getRemoteCallExecutor().execute(() -> {
+ mListener = null;
+ controller.setPinnedStackAnimationListener(null);
+ });
+ }
+ };
+
+ IPipImpl(PipController controller) {
+ mController = controller;
+ }
+
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mController = null;
+ }
+
+ @Override
+ public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
+ PictureInPictureParams pictureInPictureParams, int launcherRotation,
+ int shelfHeight) {
+ Rect[] result = new Rect[1];
+ executeRemoteCallWithTaskPermission(mController, "startSwipePipToHome",
+ (controller) -> {
+ result[0] = controller.startSwipePipToHome(componentName, activityInfo,
+ pictureInPictureParams, launcherRotation, shelfHeight);
+ }, true /* blocking */);
+ return result[0];
+ }
+
+ @Override
+ public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
+ executeRemoteCallWithTaskPermission(mController, "stopSwipePipToHome",
+ (controller) -> {
+ controller.stopSwipePipToHome(componentName, destinationBounds);
+ });
+ }
+
+ @Override
+ public void setShelfHeight(boolean visible, int height) {
+ executeRemoteCallWithTaskPermission(mController, "setShelfHeight",
+ (controller) -> {
+ controller.setShelfHeight(visible, height);
+ });
+ }
+
+ @Override
+ public void setPinnedStackAnimationListener(IPipAnimationListener listener) {
+ executeRemoteCallWithTaskPermission(mController, "setPinnedStackAnimationListener",
+ (controller) -> {
+ if (mListener != null) {
+ // Reset the old death recipient
+ mListener.asBinder().unlinkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ }
+ if (listener != null) {
+ // Register the death recipient for the new listener to clear the listener
+ try {
+ listener.asBinder().linkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death");
+ return;
+ }
+ }
+ mListener = listener;
+ controller.setPinnedStackAnimationListener(listener);
+ });
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
new file mode 100644
index 0000000..0c46eab
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
@@ -0,0 +1,77 @@
+/*
+ * 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 com.android.wm.shell.splitscreen;
+
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+import com.android.wm.shell.splitscreen.ISplitScreenListener;
+
+/**
+ * Interface that is exposed to remote callers to manipulate the splitscreen feature.
+ */
+interface ISplitScreen {
+
+ /**
+ * Registers a split screen listener.
+ */
+ oneway void registerSplitScreenListener(in ISplitScreenListener listener) = 1;
+
+ /**
+ * Unregisters a split screen listener.
+ */
+ oneway void unregisterSplitScreenListener(in ISplitScreenListener listener) = 2;
+
+ /**
+ * Hides the side-stage if it is currently visible.
+ */
+ oneway void setSideStageVisibility(boolean visible) = 3;
+
+ /**
+ * Removes a task from the side stage.
+ */
+ oneway void removeFromSideStage(int taskId) = 4;
+
+ /**
+ * Removes the split-screen stages.
+ */
+ oneway void exitSplitScreen() = 5;
+
+ /**
+ * @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible.
+ */
+ oneway void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) = 6;
+
+ /**
+ * Starts a task in a stage.
+ */
+ oneway void startTask(int taskId, int stage, int position, in Bundle options) = 7;
+
+ /**
+ * Starts a shortcut in a stage.
+ */
+ oneway void startShortcut(String packageName, String shortcutId, int stage, int position,
+ in Bundle options, in UserHandle user) = 8;
+
+ /**
+ * Starts an activity in a stage.
+ */
+ oneway void startIntent(in PendingIntent intent, in Intent fillInIntent, int stage,
+ int position, in Bundle options) = 9;
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreenListener.aidl
similarity index 83%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
rename to libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreenListener.aidl
index 54242be..faab4c2 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreenListener.aidl
@@ -14,12 +14,20 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package com.android.wm.shell.splitscreen;
/**
* Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
*/
oneway interface ISplitScreenListener {
+
+ /**
+ * Called when the stage position changes.
+ */
void onStagePositionChanged(int stage, int position);
+
+ /**
+ * Called when a task changes stages.
+ */
void onTaskStageChanged(int taskId, int stage, boolean visible);
-}
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index 25a84bd..340b55d7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -35,7 +35,7 @@
* TODO: Figure out which of these are actually needed outside of the Shell
*/
@ExternalThread
-public interface SplitScreen extends DragAndDropPolicy.Starter {
+public interface SplitScreen {
/**
* Stage position isn't specified normally meaning to use what ever it is currently set to.
*/
@@ -89,35 +89,10 @@
void onTaskStageChanged(int taskId, @StageType int stage, boolean visible);
}
- /** @return {@code true} if split-screen is currently visible. */
- boolean isSplitScreenVisible();
- /** Moves a task in the side-stage of split-screen. */
- boolean moveToSideStage(int taskId, @StagePosition int sideStagePosition);
- /** Moves a task in the side-stage of split-screen. */
- boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
- @StagePosition int sideStagePosition);
- /** Removes a task from the side-stage of split-screen. */
- boolean removeFromSideStage(int taskId);
- /** Sets the position of the side-stage. */
- void setSideStagePosition(@StagePosition int sideStagePosition);
- /** Hides the side-stage if it is currently visible. */
- void setSideStageVisibility(boolean visible);
-
- /** Removes the split-screen stages. */
- void exitSplitScreen();
- /** @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible. */
- void exitSplitScreenOnHide(boolean exitSplitScreenOnHide);
- /** Gets the stage bounds. */
- void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds);
-
- void registerSplitScreenListener(SplitScreenListener listener);
- void unregisterSplitScreenListener(SplitScreenListener listener);
-
- void startTask(int taskId,
- @StageType int stage, @StagePosition int position, @Nullable Bundle options);
- void startShortcut(String packageName, String shortcutId, @StageType int stage,
- @StagePosition int position, @Nullable Bundle options, UserHandle user);
- void startIntent(PendingIntent intent, Context context,
- @Nullable Intent fillInIntent, @StageType int stage,
- @StagePosition int position, @Nullable Bundle options);
+ /**
+ * Returns a binder that can be passed to an external process to manipulate SplitScreen.
+ */
+ default ISplitScreen createExternalInterface() {
+ return null;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index bb6f6f2..d4362ef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -18,6 +18,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_UNDEFINED;
@@ -34,19 +35,24 @@
import android.content.pm.LauncherApps;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
+import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
+import com.android.wm.shell.splitscreen.ISplitScreenListener;
import java.io.PrintWriter;
@@ -55,7 +61,8 @@
* {@link SplitScreen}.
* @see StageCoordinator
*/
-public class SplitScreenController implements DragAndDropPolicy.Starter {
+public class SplitScreenController implements DragAndDropPolicy.Starter,
+ RemoteCallable<SplitScreenController> {
private static final String TAG = SplitScreenController.class.getSimpleName();
private final ShellTaskOrganizer mTaskOrganizer;
@@ -84,6 +91,16 @@
return mImpl;
}
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mMainExecutor;
+ }
+
public void onOrganizerRegistered() {
if (mStageCoordinator == null) {
// TODO: Multi-display
@@ -172,13 +189,13 @@
}
}
- public void startIntent(PendingIntent intent, Context context,
- Intent fillInIntent, @SplitScreen.StageType int stage,
- @SplitScreen.StagePosition int position, @Nullable Bundle options) {
+ public void startIntent(PendingIntent intent, Intent fillInIntent,
+ @SplitScreen.StageType int stage, @SplitScreen.StagePosition int position,
+ @Nullable Bundle options) {
options = resolveStartStage(stage, position, options);
try {
- intent.send(context, 0, fillInIntent, null, null, null, options);
+ intent.send(mContext, 0, fillInIntent, null, null, null, options);
} catch (PendingIntent.CanceledException e) {
Slog.e(TAG, "Failed to launch activity", e);
}
@@ -242,121 +259,170 @@
}
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
+ @ExternalThread
private class SplitScreenImpl implements SplitScreen {
+ private ISplitScreenImpl mISplitScreen;
+
@Override
- public boolean isSplitScreenVisible() {
- return mMainExecutor.executeBlockingForResult(() -> {
- return SplitScreenController.this.isSplitScreenVisible();
- }, Boolean.class);
+ public ISplitScreen createExternalInterface() {
+ if (mISplitScreen != null) {
+ mISplitScreen.invalidate();
+ }
+ mISplitScreen = new ISplitScreenImpl(SplitScreenController.this);
+ return mISplitScreen;
+ }
+ }
+
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class ISplitScreenImpl extends ISplitScreen.Stub {
+ private SplitScreenController mController;
+ private ISplitScreenListener mListener;
+ private final SplitScreen.SplitScreenListener mSplitScreenListener =
+ new SplitScreen.SplitScreenListener() {
+ @Override
+ public void onStagePositionChanged(int stage, int position) {
+ try {
+ if (mListener != null) {
+ mListener.onStagePositionChanged(stage, position);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "onStagePositionChanged", e);
+ }
+ }
+
+ @Override
+ public void onTaskStageChanged(int taskId, int stage, boolean visible) {
+ try {
+ if (mListener != null) {
+ mListener.onTaskStageChanged(taskId, stage, visible);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "onTaskStageChanged", e);
+ }
+ }
+ };
+ private final IBinder.DeathRecipient mListenerDeathRecipient =
+ new IBinder.DeathRecipient() {
+ @Override
+ @BinderThread
+ public void binderDied() {
+ final SplitScreenController controller = mController;
+ controller.getRemoteCallExecutor().execute(() -> {
+ mListener = null;
+ controller.unregisterSplitScreenListener(mSplitScreenListener);
+ });
+ }
+ };
+
+ public ISplitScreenImpl(SplitScreenController controller) {
+ mController = controller;
+ }
+
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mController = null;
}
@Override
- public boolean moveToSideStage(int taskId, int sideStagePosition) {
- return mMainExecutor.executeBlockingForResult(() -> {
- return SplitScreenController.this.moveToSideStage(taskId, sideStagePosition);
- }, Boolean.class);
+ public void registerSplitScreenListener(ISplitScreenListener listener) {
+ executeRemoteCallWithTaskPermission(mController, "registerSplitScreenListener",
+ (controller) -> {
+ if (mListener != null) {
+ mListener.asBinder().unlinkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ }
+ if (listener != null) {
+ try {
+ listener.asBinder().linkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death");
+ return;
+ }
+ }
+ mListener = listener;
+ controller.registerSplitScreenListener(mSplitScreenListener);
+ });
}
@Override
- public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
- int sideStagePosition) {
- return mMainExecutor.executeBlockingForResult(() -> {
- return SplitScreenController.this.moveToSideStage(task, sideStagePosition);
- }, Boolean.class);
- }
-
- @Override
- public boolean removeFromSideStage(int taskId) {
- return mMainExecutor.executeBlockingForResult(() -> {
- return SplitScreenController.this.removeFromSideStage(taskId);
- }, Boolean.class);
- }
-
- @Override
- public void setSideStagePosition(int sideStagePosition) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.setSideStagePosition(sideStagePosition);
- });
- }
-
- @Override
- public void setSideStageVisibility(boolean visible) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.setSideStageVisibility(visible);
- });
- }
-
- @Override
- public void enterSplitScreen(int taskId, boolean leftOrTop) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.enterSplitScreen(taskId, leftOrTop);
- });
+ public void unregisterSplitScreenListener(ISplitScreenListener listener) {
+ executeRemoteCallWithTaskPermission(mController, "unregisterSplitScreenListener",
+ (controller) -> {
+ if (mListener != null) {
+ mListener.asBinder().unlinkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ }
+ mListener = null;
+ controller.unregisterSplitScreenListener(mSplitScreenListener);
+ });
}
@Override
public void exitSplitScreen() {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.exitSplitScreen();
- });
+ executeRemoteCallWithTaskPermission(mController, "exitSplitScreen",
+ (controller) -> {
+ controller.exitSplitScreen();
+ });
}
@Override
public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.exitSplitScreenOnHide(exitSplitScreenOnHide);
- });
+ executeRemoteCallWithTaskPermission(mController, "exitSplitScreenOnHide",
+ (controller) -> {
+ controller.exitSplitScreenOnHide(exitSplitScreenOnHide);
+ });
}
@Override
- public void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) {
- try {
- mMainExecutor.executeBlocking(() -> {
- SplitScreenController.this.getStageBounds(outTopOrLeftBounds,
- outBottomOrRightBounds);
- });
- } catch (InterruptedException e) {
- Slog.e(TAG, "Failed to get stage bounds in 2s");
- }
+ public void setSideStageVisibility(boolean visible) {
+ executeRemoteCallWithTaskPermission(mController, "setSideStageVisibility",
+ (controller) -> {
+ controller.setSideStageVisibility(visible);
+ });
}
@Override
- public void registerSplitScreenListener(SplitScreenListener listener) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.registerSplitScreenListener(listener);
- });
- }
-
- @Override
- public void unregisterSplitScreenListener(SplitScreenListener listener) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.unregisterSplitScreenListener(listener);
- });
+ public void removeFromSideStage(int taskId) {
+ executeRemoteCallWithTaskPermission(mController, "removeFromSideStage",
+ (controller) -> {
+ controller.removeFromSideStage(taskId);
+ });
}
@Override
public void startTask(int taskId, int stage, int position, @Nullable Bundle options) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.startTask(taskId, stage, position, options);
- });
+ executeRemoteCallWithTaskPermission(mController, "startTask",
+ (controller) -> {
+ controller.startTask(taskId, stage, position, options);
+ });
}
@Override
public void startShortcut(String packageName, String shortcutId, int stage, int position,
@Nullable Bundle options, UserHandle user) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.startShortcut(packageName, shortcutId, stage, position,
- options, user);
- });
+ executeRemoteCallWithTaskPermission(mController, "startShortcut",
+ (controller) -> {
+ controller.startShortcut(packageName, shortcutId, stage, position,
+ options, user);
+ });
}
@Override
- public void startIntent(PendingIntent intent, Context context, Intent fillInIntent,
- int stage, int position, @Nullable Bundle options) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.startIntent(intent, context, fillInIntent, stage,
- position, options);
- });
+ public void startIntent(PendingIntent intent, Intent fillInIntent, int stage, int position,
+ @Nullable Bundle options) {
+ executeRemoteCallWithTaskPermission(mController, "startIntent",
+ (controller) -> {
+ controller.startIntent(intent, fillInIntent, stage, position, options);
+ });
}
}
-
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl
similarity index 62%
copy from packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
copy to libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl
index 54242be..546c406 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl
@@ -14,12 +14,16 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package com.android.wm.shell.startingsurface;
+
+import com.android.wm.shell.startingsurface.IStartingWindowListener;
/**
- * Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
+ * Interface that is exposed to remote callers to manipulate starting windows.
*/
-oneway interface ISplitScreenListener {
- void onStagePositionChanged(int stage, int position);
- void onTaskStageChanged(int taskId, int stage, boolean visible);
+interface IStartingWindow {
+ /**
+ * Sets listener to get task launching callbacks.
+ */
+ oneway void setStartingWindowListener(IStartingWindowListener listener) = 43;
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IStartingWindowListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl
similarity index 90%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/IStartingWindowListener.aidl
rename to libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl
index eb3e60c..f562c8f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IStartingWindowListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package com.android.wm.shell.startingsurface;
/**
* Listener interface that Launcher attaches to SystemUI to get
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 3f9c271..3f46fee 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
@@ -16,6 +16,7 @@
package com.android.wm.shell.startingsurface;
+import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.app.ActivityThread;
import android.content.Context;
@@ -149,14 +150,16 @@
.setThemeDrawable(themeBGDrawable)
.setIconDrawable(iconDrawable)
.setIconAnimationDuration(animationDuration)
- .setBrandingDrawable(attrs.mBrandingImage).build();
+ .setBrandingDrawable(attrs.mBrandingImage)
+ .setIconBackground(attrs.mIconBgColor).build();
}
- private static class SplashScreenWindowAttrs {
+ static class SplashScreenWindowAttrs {
private int mWindowBgResId = 0;
private int mWindowBgColor = Color.TRANSPARENT;
private Drawable mReplaceIcon = null;
private Drawable mBrandingImage = null;
+ private int mIconBgColor = Color.TRANSPARENT;
private int mAnimationDuration = 0;
static SplashScreenWindowAttrs createWindowAttrs(Context context) {
@@ -172,6 +175,8 @@
R.styleable.Window_windowSplashScreenAnimationDuration, 0);
attrs.mBrandingImage = typedArray.getDrawable(
R.styleable.Window_windowSplashScreenBrandingImage);
+ attrs.mIconBgColor = typedArray.getColor(
+ R.styleable.Window_windowSplashScreenIconBackgroundColor, Color.TRANSPARENT);
typedArray.recycle();
if (DEBUG) {
Slog.d(TAG, "window attributes color: "
@@ -189,6 +194,7 @@
private int mIconAnimationDuration;
private Context mContext;
private Drawable mBrandingDrawable;
+ private @ColorInt int mIconBackground;
// result
private boolean mBuildComplete = false;
@@ -221,6 +227,12 @@
return this;
}
+ StartingWindowViewBuilder setIconBackground(int color) {
+ mIconBackground = color;
+ mBuildComplete = false;
+ return this;
+ }
+
StartingWindowViewBuilder setContext(Context context) {
mContext = context;
mBuildComplete = false;
@@ -244,7 +256,9 @@
if (DEBUG) {
Slog.d(TAG, "The icon is not an AdaptiveIconDrawable");
}
- mFinalIconDrawable = mIconDrawable;
+ mFinalIconDrawable = SplashscreenIconDrawableFactory.makeIconDrawable(
+ mIconBackground != Color.TRANSPARENT
+ ? mIconBackground : mThemeColor, mIconDrawable);
}
final int iconSize = mFinalIconDrawable != null ? (int) (mIconSize * mScale) : 0;
mCachedResult = fillViewWithIcon(mContext, iconSize, mFinalIconDrawable);
@@ -252,6 +266,12 @@
return mCachedResult;
}
+ private void createIconDrawable(Drawable iconDrawable) {
+ mFinalIconDrawable = SplashscreenIconDrawableFactory.makeIconDrawable(
+ mIconBackground != Color.TRANSPARENT
+ ? mIconBackground : mThemeColor, iconDrawable);
+ }
+
private void processThemeColor() {
final DrawableColorTester themeBGTester =
new DrawableColorTester(mThemeBGDrawable, true /* filterTransparent */);
@@ -307,8 +327,7 @@
}
// Using AdaptiveIconDrawable here can help keep the shape consistent with the
// current settings.
- mFinalIconDrawable = new AdaptiveIconDrawable(
- new ColorDrawable(mThemeColor), iconForeground);
+ createIconDrawable(iconForeground);
// Reference AdaptiveIcon description, outer is 108 and inner is 72, so we
// should enlarge the size 108/72 if we only draw adaptiveIcon's foreground.
if (foreIconTester.nonTransparentRatio() < ENLARGE_FOREGROUND_ICON_THRESHOLD) {
@@ -318,7 +337,11 @@
if (DEBUG) {
Slog.d(TAG, "makeSplashScreenContentView: draw whole icon");
}
- mFinalIconDrawable = adaptiveIconDrawable;
+ if (mIconBackground != Color.TRANSPARENT) {
+ createIconDrawable(adaptiveIconDrawable);
+ } else {
+ mFinalIconDrawable = adaptiveIconDrawable;
+ }
}
return true;
}
@@ -326,7 +349,8 @@
private SplashScreenView fillViewWithIcon(Context context,
int iconSize, Drawable iconDrawable) {
final SplashScreenView.Builder builder = new SplashScreenView.Builder(context);
- builder.setIconSize(iconSize).setBackgroundColor(mThemeColor);
+ builder.setIconSize(iconSize).setBackgroundColor(mThemeColor)
+ .setIconBackground(mIconBackground);
if (iconDrawable != null) {
builder.setCenterViewDrawable(iconDrawable);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
new file mode 100644
index 0000000..8626dbc
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
@@ -0,0 +1,217 @@
+/*
+ * 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 com.android.wm.shell.startingsurface;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.SystemClock;
+import android.util.PathParser;
+import android.window.SplashScreenView;
+
+import com.android.internal.R;
+
+import java.util.function.Consumer;
+
+/**
+ * Creating a lightweight Drawable object used for splash screen.
+ * @hide
+ */
+public class SplashscreenIconDrawableFactory {
+
+ static Drawable makeIconDrawable(@ColorInt int backgroundColor,
+ @NonNull Drawable foregroundDrawable) {
+ if (foregroundDrawable instanceof Animatable) {
+ return new AnimatableIconDrawable(backgroundColor, foregroundDrawable);
+ } else {
+ // TODO make a light weight drawable instead of AdaptiveIconDrawable
+ return new AdaptiveIconDrawable(new ColorDrawable(backgroundColor), foregroundDrawable);
+ }
+ }
+
+ /**
+ * A lightweight AdaptiveIconDrawable which support foreground to be Animatable, and keep this
+ * drawable masked by config_icon_mask.
+ * @hide
+ */
+ private static class AnimatableIconDrawable extends SplashScreenView.SplashscreenIconDrawable {
+ private static final float MASK_SIZE = AdaptiveIconDrawable.MASK_SIZE;
+ private static final float EXTRA_INSET_PERCENTAGE = 1 / 4f;
+ private static final float DEFAULT_VIEW_PORT_SCALE = 1f / (1 + 2 * EXTRA_INSET_PERCENTAGE);
+ private final Rect mTmpOutRect = new Rect();
+ /**
+ * Clip path defined in R.string.config_icon_mask.
+ */
+ private static Path sMask;
+
+ /**
+ * Scaled mask based on the view bounds.
+ */
+ private final Path mMask;
+ private final Path mMaskScaleOnly;
+ private final Matrix mMaskMatrix;
+ private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Drawable mForegroundDrawable;
+ private Animatable mAnimatableIcon;
+ private Animator mIconAnimator;
+ private boolean mAnimationTriggered;
+ private long mIconAnimationStart;
+
+ AnimatableIconDrawable(@ColorInt int backgroundColor, Drawable foregroundDrawable) {
+ mForegroundDrawable = foregroundDrawable;
+ final Resources r = Resources.getSystem();
+ sMask = PathParser.createPathFromPathData(r.getString(R.string.config_icon_mask));
+ mMask = new Path(sMask);
+ mMaskScaleOnly = new Path(mMask);
+ mMaskMatrix = new Matrix();
+ mPaint.setColor(backgroundColor);
+ mPaint.setStyle(Paint.Style.FILL);
+ if (mForegroundDrawable != null) {
+ mForegroundDrawable.setCallback(mCallback);
+ }
+ }
+
+ @Override
+ protected boolean prepareAnimate(long duration, Consumer<Long> startListener) {
+ mAnimatableIcon = (Animatable) mForegroundDrawable;
+ mIconAnimator = ValueAnimator.ofInt(0, 1);
+ mIconAnimator.setDuration(duration);
+ mIconAnimator.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mIconAnimationStart = SystemClock.uptimeMillis();
+ if (startListener != null) {
+ startListener.accept(mIconAnimationStart);
+ }
+ mAnimatableIcon.start();
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAnimatableIcon.stop();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mAnimatableIcon.stop();
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ // do not repeat
+ mAnimatableIcon.stop();
+ }
+ });
+ return true;
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ if (bounds.isEmpty()) {
+ return;
+ }
+ updateLayerBounds(bounds);
+ }
+
+ private final Callback mCallback = new Callback() {
+ @Override
+ public void invalidateDrawable(@NonNull Drawable who) {
+ invalidateSelf();
+ }
+
+ @Override
+ public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
+ scheduleSelf(what, when);
+ }
+
+ @Override
+ public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
+ unscheduleSelf(what);
+ }
+ };
+
+ private void updateLayerBounds(Rect bounds) {
+ int cX = bounds.width() / 2;
+ int cY = bounds.height() / 2;
+
+ int insetWidth = (int) (bounds.width() / (DEFAULT_VIEW_PORT_SCALE * 2));
+ int insetHeight = (int) (bounds.height() / (DEFAULT_VIEW_PORT_SCALE * 2));
+ final Rect outRect = mTmpOutRect;
+ outRect.set(cX - insetWidth, cY - insetHeight, cX + insetWidth, cY + insetHeight);
+
+ if (mForegroundDrawable != null) {
+ mForegroundDrawable.setBounds(outRect);
+ }
+ // reset everything that depends on the view bounds
+ mMaskMatrix.setScale(bounds.width() / MASK_SIZE, bounds.height() / MASK_SIZE);
+ sMask.transform(mMaskMatrix, mMaskScaleOnly);
+ invalidateSelf();
+ }
+
+ private void ensureAnimationStarted() {
+ if (mAnimationTriggered) {
+ return;
+ }
+ if (mIconAnimator != null && !mIconAnimator.isRunning()) {
+ mIconAnimator.start();
+ }
+ mAnimationTriggered = true;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (mMaskScaleOnly != null) {
+ canvas.drawPath(mMaskScaleOnly, mPaint);
+ }
+ if (mForegroundDrawable != null) {
+ ensureAnimationStarted();
+ mForegroundDrawable.draw(canvas);
+ }
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mPaint.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ if (mForegroundDrawable != null) {
+ mForegroundDrawable.setColorFilter(colorFilter);
+ }
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+ }
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
index f258286..079d689 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
@@ -16,35 +16,15 @@
package com.android.wm.shell.startingsurface;
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.view.SurfaceControl;
-import android.window.StartingWindowInfo;
-
-import java.util.function.BiConsumer;
/**
* Interface to engage starting window feature.
*/
public interface StartingSurface {
- /**
- * Called when a task need a starting window.
- */
- void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken);
- /**
- * Called when the content of a task is ready to show, starting window can be removed.
- */
- void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
- boolean playRevealAnimation);
- /**
- * Called when the Task wants to copy the splash screen.
- * @param taskId
- */
- void copySplashScreenView(int taskId);
/**
- * Registers the starting window listener.
- *
- * @param listener The callback when need a starting window.
+ * Returns a binder that can be passed to an external process to manipulate starting windows.
*/
- void setStartingWindowListener(BiConsumer<Integer, Integer> listener);
+ default IStartingWindow createExternalInterface() {
+ return null;
+ }
}
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 9212c4b..b592121 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
@@ -362,7 +362,6 @@
final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
if (record != null) {
record.setSplashScreenView(splashScreenView);
- splashScreenView.startIntroAnimation();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index d7cae36..a06068d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -25,6 +25,8 @@
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.content.Context;
@@ -37,6 +39,9 @@
import android.window.TaskOrganizer;
import android.window.TaskSnapshot;
+import androidx.annotation.BinderThread;
+
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
@@ -58,7 +63,7 @@
* constructor to keep everything synchronized.
* @hide
*/
-public class StartingWindowController {
+public class StartingWindowController implements RemoteCallable<StartingWindowController> {
private static final String TAG = StartingWindowController.class.getSimpleName();
static final boolean DEBUG_SPLASH_SCREEN = false;
static final boolean DEBUG_TASK_SNAPSHOT = false;
@@ -68,17 +73,17 @@
private BiConsumer<Integer, Integer> mTaskLaunchingCallback;
private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl();
+ private final Context mContext;
private final ShellExecutor mSplashScreenExecutor;
// For Car Launcher
public StartingWindowController(Context context, ShellExecutor splashScreenExecutor) {
- mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, splashScreenExecutor,
- new TransactionPool());
- mSplashScreenExecutor = splashScreenExecutor;
+ this(context, splashScreenExecutor, new TransactionPool());
}
public StartingWindowController(Context context, ShellExecutor splashScreenExecutor,
TransactionPool pool) {
+ mContext = context;
mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, splashScreenExecutor, pool);
mSplashScreenExecutor = splashScreenExecutor;
}
@@ -90,6 +95,16 @@
return mImpl;
}
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mSplashScreenExecutor;
+ }
+
private static class StartingTypeChecker {
TaskSnapshot mSnapshot;
@@ -195,59 +210,121 @@
/**
* Called when a task need a starting window.
*/
- void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
- final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo);
- final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
- if (mTaskLaunchingCallback != null) {
- mTaskLaunchingCallback.accept(runningTaskInfo.taskId, suggestionType);
- }
- if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken);
- } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
- final TaskSnapshot snapshot = mStartingTypeChecker.mSnapshot;
- mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
- }
- // If prefer don't show, then don't show!
+ public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+ mSplashScreenExecutor.execute(() -> {
+ final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo);
+ final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
+ if (mTaskLaunchingCallback != null) {
+ mTaskLaunchingCallback.accept(runningTaskInfo.taskId, suggestionType);
+ }
+ if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken);
+ } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
+ final TaskSnapshot snapshot = mStartingTypeChecker.mSnapshot;
+ mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
+ }
+ // If prefer don't show, then don't show!
+ });
}
- void copySplashScreenView(int taskId) {
- mStartingSurfaceDrawer.copySplashScreenView(taskId);
+ public void copySplashScreenView(int taskId) {
+ mSplashScreenExecutor.execute(() -> {
+ mStartingSurfaceDrawer.copySplashScreenView(taskId);
+ });
}
/**
* Called when the content of a task is ready to show, starting window can be removed.
*/
- void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
+ public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
boolean playRevealAnimation) {
- mStartingSurfaceDrawer.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
+ mSplashScreenExecutor.execute(() -> {
+ mStartingSurfaceDrawer.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
+ });
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
private class StartingSurfaceImpl implements StartingSurface {
+ private IStartingWindowImpl mIStartingWindow;
@Override
- public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
- mSplashScreenExecutor.execute(() ->
- StartingWindowController.this.addStartingWindow(windowInfo, appToken));
+ public IStartingWindowImpl createExternalInterface() {
+ if (mIStartingWindow != null) {
+ mIStartingWindow.invalidate();
+ }
+ mIStartingWindow = new IStartingWindowImpl(StartingWindowController.this);
+ return mIStartingWindow;
+ }
+ }
+
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class IStartingWindowImpl extends IStartingWindow.Stub {
+ private StartingWindowController mController;
+ private IStartingWindowListener mListener;
+ private final BiConsumer<Integer, Integer> mStartingWindowListener =
+ this::notifyIStartingWindowListener;
+ private final IBinder.DeathRecipient mListenerDeathRecipient =
+ new IBinder.DeathRecipient() {
+ @Override
+ @BinderThread
+ public void binderDied() {
+ final StartingWindowController controller = mController;
+ controller.getRemoteCallExecutor().execute(() -> {
+ mListener = null;
+ controller.setStartingWindowListener(null);
+ });
+ }
+ };
+
+ public IStartingWindowImpl(StartingWindowController controller) {
+ mController = controller;
+ }
+
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mController = null;
}
@Override
- public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
- boolean playRevealAnimation) {
- mSplashScreenExecutor.execute(() ->
- StartingWindowController.this.removeStartingWindow(taskId, leash, frame,
- playRevealAnimation));
+ public void setStartingWindowListener(IStartingWindowListener listener) {
+ executeRemoteCallWithTaskPermission(mController, "setStartingWindowListener",
+ (controller) -> {
+ if (mListener != null) {
+ // Reset the old death recipient
+ mListener.asBinder().unlinkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ }
+ if (listener != null) {
+ try {
+ listener.asBinder().linkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death");
+ return;
+ }
+ }
+ mListener = listener;
+ controller.setStartingWindowListener(mStartingWindowListener);
+ });
}
- @Override
- public void copySplashScreenView(int taskId) {
- mSplashScreenExecutor.execute(() ->
- StartingWindowController.this.copySplashScreenView(taskId));
- }
+ private void notifyIStartingWindowListener(int taskId, int supportedType) {
+ if (mListener == null) {
+ return;
+ }
- @Override
- public void setStartingWindowListener(BiConsumer<Integer, Integer> listener) {
- mSplashScreenExecutor.execute(() ->
- StartingWindowController.this.setStartingWindowListener(listener));
+ try {
+ mListener.onTaskLaunching(taskId, supportedType);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to notify task launching", e);
+ }
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
similarity index 63%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java
copy to libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
index 85bbf74..dffc700 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
@@ -16,25 +16,22 @@
package com.android.wm.shell.transition;
-import android.annotation.NonNull;
import android.window.IRemoteTransition;
import android.window.TransitionFilter;
-import com.android.wm.shell.common.annotations.ExternalThread;
-
/**
- * Interface to manage remote transitions.
+ * Interface that is exposed to remote callers to manipulate the transitions feature.
*/
-@ExternalThread
-public interface RemoteTransitions {
- /**
- * Registers a remote transition.
- */
- void registerRemote(@NonNull TransitionFilter filter,
- @NonNull IRemoteTransition remoteTransition);
+interface IShellTransitions {
/**
- * Unregisters a remote transition.
+ * Registers a remote transition handler.
*/
- void unregisterRemote(@NonNull IRemoteTransition remoteTransition);
+ oneway void registerRemote(in TransitionFilter filter,
+ in IRemoteTransition remoteTransition) = 1;
+
+ /**
+ * Unregisters a remote transition handler.
+ */
+ oneway void unregisterRemote(in IRemoteTransition remoteTransition) = 2;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index ac93a17..9667f4b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.transition;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
@@ -23,6 +25,7 @@
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
+import android.util.Slog;
import android.view.SurfaceControl;
import android.window.IRemoteTransition;
import android.window.IRemoteTransitionFinishedCallback;
@@ -31,6 +34,8 @@
import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
+import androidx.annotation.BinderThread;
+
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -42,6 +47,8 @@
* if the request includes a specific remote.
*/
public class RemoteTransitionHandler implements Transitions.TransitionHandler {
+ private static final String TAG = "RemoteTransitionHandler";
+
private final ShellExecutor mMainExecutor;
/** Includes remotes explicitly requested by, eg, ActivityOptions */
@@ -51,15 +58,33 @@
private final ArrayList<Pair<TransitionFilter, IRemoteTransition>> mFilters =
new ArrayList<>();
+ private final IBinder.DeathRecipient mTransitionDeathRecipient =
+ new IBinder.DeathRecipient() {
+ @Override
+ @BinderThread
+ public void binderDied() {
+ mMainExecutor.execute(() -> {
+ mFilters.clear();
+ });
+ }
+ };
+
RemoteTransitionHandler(@NonNull ShellExecutor mainExecutor) {
mMainExecutor = mainExecutor;
}
void addFiltered(TransitionFilter filter, IRemoteTransition remote) {
+ try {
+ remote.asBinder().linkToDeath(mTransitionDeathRecipient, 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death");
+ return;
+ }
mFilters.add(new Pair<>(filter, remote));
}
void removeFiltered(IRemoteTransition remote) {
+ remote.asBinder().unlinkToDeath(mTransitionDeathRecipient, 0 /* flags */);
for (int i = mFilters.size() - 1; i >= 0; --i) {
if (mFilters.get(i).second == remote) {
mFilters.remove(i);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java
similarity index 83%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java
index 85bbf74..bc42c6e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java
@@ -26,7 +26,15 @@
* Interface to manage remote transitions.
*/
@ExternalThread
-public interface RemoteTransitions {
+public interface ShellTransitions {
+
+ /**
+ * Returns a binder that can be passed to an external process to manipulate remote transitions.
+ */
+ default IShellTransitions createExternalInterface() {
+ return null;
+ }
+
/**
* Registers a remote transition.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 677db10..ca1b53d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -23,6 +23,8 @@
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
@@ -51,6 +53,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread;
@@ -60,7 +63,7 @@
import java.util.Arrays;
/** Plays transition animations */
-public class Transitions {
+public class Transitions implements RemoteCallable<Transitions> {
static final String TAG = "ShellTransitions";
/** Set to {@code true} to enable shell transitions. */
@@ -73,7 +76,7 @@
private final ShellExecutor mAnimExecutor;
private final TransitionPlayerImpl mPlayerImpl;
private final RemoteTransitionHandler mRemoteTransitionHandler;
- private final RemoteTransitionImpl mImpl = new RemoteTransitionImpl();
+ private final ShellTransitionImpl mImpl = new ShellTransitionImpl();
/** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();
@@ -87,10 +90,6 @@
/** Keeps track of currently tracked transitions and all the animations associated with each */
private final ArrayMap<IBinder, ActiveTransition> mActiveTransitions = new ArrayMap<>();
- public static RemoteTransitions asRemoteTransitions(Transitions transitions) {
- return transitions.mImpl;
- }
-
public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
@NonNull Context context, @NonNull ShellExecutor mainExecutor,
@NonNull ShellExecutor animExecutor) {
@@ -126,6 +125,20 @@
mRemoteTransitionHandler = null;
}
+ public ShellTransitions asRemoteTransitions() {
+ return mImpl;
+ }
+
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mMainExecutor;
+ }
+
private void dispatchAnimScaleSetting(float scale) {
for (int i = mHandlers.size() - 1; i >= 0; --i) {
mHandlers.get(i).setAnimScaleSetting(scale);
@@ -134,8 +147,8 @@
/** Create an empty/non-registering transitions object for system-ui tests. */
@VisibleForTesting
- public static RemoteTransitions createEmptyForTesting() {
- return new RemoteTransitions() {
+ public static ShellTransitions createEmptyForTesting() {
+ return new ShellTransitions() {
@Override
public void registerRemote(@androidx.annotation.NonNull TransitionFilter filter,
@androidx.annotation.NonNull IRemoteTransition remoteTransition) {
@@ -426,24 +439,74 @@
}
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
@ExternalThread
- private class RemoteTransitionImpl implements RemoteTransitions {
+ private class ShellTransitionImpl implements ShellTransitions {
+ private IShellTransitionsImpl mIShellTransitions;
+
+ @Override
+ public IShellTransitions createExternalInterface() {
+ if (mIShellTransitions != null) {
+ mIShellTransitions.invalidate();
+ }
+ mIShellTransitions = new IShellTransitionsImpl(Transitions.this);
+ return mIShellTransitions;
+ }
+
@Override
public void registerRemote(@NonNull TransitionFilter filter,
@NonNull IRemoteTransition remoteTransition) {
mMainExecutor.execute(() -> {
- Transitions.this.registerRemote(filter, remoteTransition);
+ mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
});
}
@Override
public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
mMainExecutor.execute(() -> {
- Transitions.this.unregisterRemote(remoteTransition);
+ mRemoteTransitionHandler.removeFiltered(remoteTransition);
});
}
}
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class IShellTransitionsImpl extends IShellTransitions.Stub {
+ private Transitions mTransitions;
+
+ IShellTransitionsImpl(Transitions transitions) {
+ mTransitions = transitions;
+ }
+
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mTransitions = null;
+ }
+
+ @Override
+ public void registerRemote(@NonNull TransitionFilter filter,
+ @NonNull IRemoteTransition remoteTransition) {
+ executeRemoteCallWithTaskPermission(mTransitions, "registerRemote",
+ (transitions) -> {
+ transitions.mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
+ });
+ }
+
+ @Override
+ public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
+ executeRemoteCallWithTaskPermission(mTransitions, "unregisterRemote",
+ (transitions) -> {
+ transitions.mRemoteTransitionHandler.removeFiltered(remoteTransition);
+ });
+ }
+ }
+
private class SettingsObserver extends ContentObserver {
SettingsObserver() {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
index c1c4c6d..2f2bbba 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
@@ -205,7 +205,7 @@
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@@ -217,12 +217,12 @@
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@@ -234,12 +234,12 @@
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@@ -251,7 +251,7 @@
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@@ -263,7 +263,7 @@
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@@ -276,13 +276,13 @@
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@@ -295,13 +295,13 @@
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp
index d4fd105..9e4fb8f 100644
--- a/libs/hwui/effects/StretchEffect.cpp
+++ b/libs/hwui/effects/StretchEffect.cpp
@@ -33,7 +33,8 @@
uniform float uMaxStretchIntensity;
// Maximum percentage to stretch beyond bounds of target
- uniform float uStretchAffectedDist;
+ uniform float uStretchAffectedDistX;
+ uniform float uStretchAffectedDistY;
// Distance stretched as a function of the normalized overscroll times
// scale intensity
@@ -138,7 +139,7 @@
outU,
inU,
uOverscrollX,
- uStretchAffectedDist,
+ uStretchAffectedDistX,
uDistanceStretchedX,
uDistDiffX
);
@@ -146,7 +147,7 @@
outV,
inV,
uOverscrollY,
- uStretchAffectedDist,
+ uStretchAffectedDistY,
uDistanceStretchedY,
uDistDiffY
);
@@ -166,16 +167,14 @@
return mStretchFilter;
}
- float distanceNotStretchedX = maxStretchAmount / stretchArea.width();
- float distanceNotStretchedY = maxStretchAmount / stretchArea.height();
- float normOverScrollDistX = mStretchDirection.x();
- float normOverScrollDistY = mStretchDirection.y();
- float distanceStretchedX = maxStretchAmount / (1 + abs(normOverScrollDistX));
- float distanceStretchedY = maxStretchAmount / (1 + abs(normOverScrollDistY));
- float diffX = distanceStretchedX - distanceNotStretchedX;
- float diffY = distanceStretchedY - distanceNotStretchedY;
float viewportWidth = stretchArea.width();
float viewportHeight = stretchArea.height();
+ float normOverScrollDistX = mStretchDirection.x();
+ float normOverScrollDistY = mStretchDirection.y();
+ float distanceStretchedX = maxStretchAmountX / (1 + abs(normOverScrollDistX));
+ float distanceStretchedY = maxStretchAmountY / (1 + abs(normOverScrollDistY));
+ float diffX = distanceStretchedX;
+ float diffY = distanceStretchedY;
if (mBuilder == nullptr) {
mBuilder = std::make_unique<SkRuntimeShaderBuilder>(getStretchEffect());
@@ -183,7 +182,8 @@
mBuilder->child("uContentTexture") = snapshotImage->makeShader(
SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(SkFilterMode::kLinear));
- mBuilder->uniform("uStretchAffectedDist").set(&maxStretchAmount, 1);
+ mBuilder->uniform("uStretchAffectedDistX").set(&maxStretchAmountX, 1);
+ mBuilder->uniform("uStretchAffectedDistY").set(&maxStretchAmountY, 1);
mBuilder->uniform("uDistanceStretchedX").set(&distanceStretchedX, 1);
mBuilder->uniform("uDistanceStretchedY").set(&distanceStretchedY, 1);
mBuilder->uniform("uDistDiffX").set(&diffX, 1);
diff --git a/libs/hwui/effects/StretchEffect.h b/libs/hwui/effects/StretchEffect.h
index d2da06b..8221b41 100644
--- a/libs/hwui/effects/StretchEffect.h
+++ b/libs/hwui/effects/StretchEffect.h
@@ -33,8 +33,12 @@
SmoothStep,
};
- StretchEffect(const SkRect& area, const SkVector& direction, float maxStretchAmount)
- : stretchArea(area), maxStretchAmount(maxStretchAmount), mStretchDirection(direction) {}
+ StretchEffect(const SkRect& area, const SkVector& direction, float maxStretchAmountX,
+ float maxStretchAmountY)
+ : stretchArea(area)
+ , maxStretchAmountX(maxStretchAmountX)
+ , maxStretchAmountY(maxStretchAmountY)
+ , mStretchDirection(direction) {}
StretchEffect() {}
@@ -50,7 +54,8 @@
this->stretchArea = other.stretchArea;
this->mStretchDirection = other.mStretchDirection;
this->mStretchFilter = nullptr;
- this->maxStretchAmount = other.maxStretchAmount;
+ this->maxStretchAmountX = other.maxStretchAmountX;
+ this->maxStretchAmountY = other.maxStretchAmountY;
return *this;
}
@@ -67,13 +72,15 @@
return setEmpty();
}
stretchArea.join(other.stretchArea);
- maxStretchAmount = std::max(maxStretchAmount, other.maxStretchAmount);
+ maxStretchAmountX = std::max(maxStretchAmountX, other.maxStretchAmountX);
+ maxStretchAmountY = std::max(maxStretchAmountY, other.maxStretchAmountY);
}
sk_sp<SkImageFilter> getImageFilter(const sk_sp<SkImage>& snapshotImage) const;
SkRect stretchArea {0, 0, 0, 0};
- float maxStretchAmount = 0;
+ float maxStretchAmountX = 0;
+ float maxStretchAmountY = 0;
void setStretchDirection(const SkVector& direction) {
mStretchFilter = nullptr;
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index fc7d0d1..fffa806 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -181,9 +181,10 @@
static jboolean android_view_RenderNode_stretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr,
jfloat left, jfloat top, jfloat right,
- jfloat bottom, jfloat vX, jfloat vY, jfloat max) {
- StretchEffect effect =
- StretchEffect(SkRect::MakeLTRB(left, top, right, bottom), {.fX = vX, .fY = vY}, max);
+ jfloat bottom, jfloat vX, jfloat vY, jfloat maxX,
+ jfloat maxY) {
+ StretchEffect effect = StretchEffect(SkRect::MakeLTRB(left, top, right, bottom),
+ {.fX = vX, .fY = vY}, maxX, maxY);
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().mutateLayerProperties().mutableStretchEffect().mergeWith(
effect);
@@ -662,7 +663,7 @@
env->CallVoidMethod(localref, gPositionListener_ApplyStretchMethod,
info.canvasContext.getFrameNumber(), area.left, area.top,
area.right, area.bottom, stretchDirection.fX, stretchDirection.fY,
- effect->maxStretchAmount);
+ effect->maxStretchAmountX, effect->maxStretchAmountY);
#endif
env->DeleteLocalRef(localref);
}
@@ -738,7 +739,7 @@
{"nSetOutlineEmpty", "(J)Z", (void*)android_view_RenderNode_setOutlineEmpty},
{"nSetOutlineNone", "(J)Z", (void*)android_view_RenderNode_setOutlineNone},
{"nClearStretch", "(J)Z", (void*)android_view_RenderNode_clearStretch},
- {"nStretch", "(JFFFFFFF)Z", (void*)android_view_RenderNode_stretch},
+ {"nStretch", "(JFFFFFFFF)Z", (void*)android_view_RenderNode_stretch},
{"nHasShadow", "(J)Z", (void*)android_view_RenderNode_hasShadow},
{"nSetSpotShadowColor", "(JI)Z", (void*)android_view_RenderNode_setSpotShadowColor},
{"nGetSpotShadowColor", "(J)I", (void*)android_view_RenderNode_getSpotShadowColor},
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index d7112d6..0d61399 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -612,7 +612,9 @@
}
/**
- * Sets the context the record belongs to.
+ * Sets the context the record belongs to. This context will be used to pull information,
+ * such as attribution tags, which will be associated with the AudioRecord. However, the
+ * context itself will not be retained by the AudioRecord.
* @param context a non-null {@link Context} instance
* @return the same Builder instance.
*/
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 88731d2..bccefdf 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -2086,6 +2086,65 @@
}
/**
+ * Sets the streaming start threshold for an <code>AudioTrack</code>.
+ * <p> The streaming start threshold is the buffer level that the written audio
+ * data must reach for audio streaming to start after {@link #play()} is called.
+ * <p> For compressed streams, the size of a frame is considered to be exactly one byte.
+ *
+ * @param startThresholdInFrames the desired start threshold.
+ * @return the actual start threshold in frames value. This is
+ * an integer between 1 to the buffer capacity
+ * (see {@link #getBufferCapacityInFrames()}),
+ * and might change if the output sink changes after track creation.
+ * @throws IllegalStateException if the track is not initialized or the
+ * track transfer mode is not {@link #MODE_STREAM}.
+ * @throws IllegalArgumentException if startThresholdInFrames is not positive.
+ * @see #getStartThresholdInFrames()
+ */
+ public @IntRange(from = 1) int setStartThresholdInFrames(
+ @IntRange (from = 1) int startThresholdInFrames) {
+ if (mState != STATE_INITIALIZED) {
+ throw new IllegalStateException("AudioTrack is not initialized");
+ }
+ if (mDataLoadMode != MODE_STREAM) {
+ throw new IllegalStateException("AudioTrack must be a streaming track");
+ }
+ if (startThresholdInFrames < 1) {
+ throw new IllegalArgumentException("startThresholdInFrames "
+ + startThresholdInFrames + " must be positive");
+ }
+ return native_setStartThresholdInFrames(startThresholdInFrames);
+ }
+
+ /**
+ * Returns the streaming start threshold of the <code>AudioTrack</code>.
+ * <p> The streaming start threshold is the buffer level that the written audio
+ * data must reach for audio streaming to start after {@link #play()} is called.
+ * When an <code>AudioTrack</code> is created, the streaming start threshold
+ * is the buffer capacity in frames. If the buffer size in frames is reduced
+ * by {@link #setBufferSizeInFrames(int)} to a value smaller than the start threshold
+ * then that value will be used instead for the streaming start threshold.
+ * <p> For compressed streams, the size of a frame is considered to be exactly one byte.
+ *
+ * @return the current start threshold in frames value. This is
+ * an integer between 1 to the buffer capacity
+ * (see {@link #getBufferCapacityInFrames()}),
+ * and might change if the output sink changes after track creation.
+ * @throws IllegalStateException if the track is not initialized or the
+ * track is not {@link #MODE_STREAM}.
+ * @see #setStartThresholdInFrames(int)
+ */
+ public @IntRange (from = 1) int getStartThresholdInFrames() {
+ if (mState != STATE_INITIALIZED) {
+ throw new IllegalStateException("AudioTrack is not initialized");
+ }
+ if (mDataLoadMode != MODE_STREAM) {
+ throw new IllegalStateException("AudioTrack must be a streaming track");
+ }
+ return native_getStartThresholdInFrames();
+ }
+
+ /**
* Returns the frame count of the native <code>AudioTrack</code> buffer.
* @return current size in frames of the <code>AudioTrack</code> buffer.
* @throws IllegalStateException
@@ -4239,6 +4298,8 @@
private native int native_set_dual_mono_mode(int dualMonoMode);
private native int native_get_dual_mono_mode(int[] dualMonoMode);
private native void native_setLogSessionId(@Nullable String logSessionId);
+ private native int native_setStartThresholdInFrames(int startThresholdInFrames);
+ private native int native_getStartThresholdInFrames();
/**
* Sets the audio service Player Interface Id.
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index f09dcde..d49790e 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -19,6 +19,7 @@
name: "libmedia_jni",
defaults: ["libcodec2-internal-defaults"],
+ min_sdk_version: "",
srcs: [
"android_media_ImageWriter.cpp",
diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp
index 017ff51..657d5a3 100644
--- a/packages/Connectivity/framework/Android.bp
+++ b/packages/Connectivity/framework/Android.bp
@@ -25,6 +25,7 @@
java_library {
name: "framework-connectivity-protos",
+ sdk_version: "module_current",
proto: {
type: "nano",
},
@@ -82,8 +83,7 @@
name: "framework-connectivity",
api_only: true,
defaults: ["framework-module-defaults"],
- // TODO: build against module API
- platform_apis: true,
+ installable: true,
srcs: [
":framework-connectivity-sources",
],
@@ -100,18 +100,56 @@
libs: [
"unsupportedappusage",
],
- permitted_packages: ["android.net", "com.android.connectivity.aidl"],
+ permitted_packages: ["android.net"],
+}
+
+cc_defaults {
+ name: "libframework-connectivity-defaults",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libnativehelper",
+ "libnetd_client",
+ ],
+ header_libs: [
+ "dnsproxyd_protocol_headers",
+ ],
+}
+
+cc_library_static {
+ name: "libconnectivityframeworkutils",
+ defaults: ["libframework-connectivity-defaults"],
+ srcs: [
+ "jni/android_net_NetworkUtils.cpp",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.tethering",
+ ],
+}
+
+cc_library_shared {
+ name: "libframework-connectivity-jni",
+ defaults: ["libframework-connectivity-defaults"],
+ srcs: [
+ "jni/onload.cpp",
+ ],
+ static_libs: ["libconnectivityframeworkutils"],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.tethering",
+ ],
}
java_library {
name: "framework-connectivity.impl",
- // Instead of building against private API (framework.jar),
- // build against core_platform + framework-minus-apex + module
- // stub libs. This allows framework.jar to depend on this library,
- // so it can be part of the private API until all clients have been migrated.
- // TODO: just build against module_api, and remove this jar from
- // the private API.
- sdk_version: "core_platform",
+ sdk_version: "module_current",
srcs: [
":framework-connectivity-sources",
],
@@ -122,12 +160,11 @@
],
},
libs: [
- "framework-minus-apex",
- // TODO: just framework-tethering, framework-wifi when building against module_api
- "framework-tethering.stubs.module_lib",
- "framework-wifi.stubs.module_lib",
+ // TODO (b/183097033) remove once module_current includes core_current
+ "stable.core.platform.api.stubs",
+ "framework-tethering",
+ "framework-wifi",
"unsupportedappusage",
- "ServiceConnectivityResources",
],
static_libs: [
"framework-connectivity-protos",
@@ -136,5 +173,5 @@
jarjar_rules: "jarjar-rules.txt",
apex_available: ["com.android.tethering"],
installable: true,
- permitted_packages: ["android.net", "com.android.connectivity.aidl"],
+ permitted_packages: ["android.net"],
}
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt
index f22d4b7..e415e01 100644
--- a/packages/Connectivity/framework/api/current.txt
+++ b/packages/Connectivity/framework/api/current.txt
@@ -291,6 +291,7 @@
ctor public NetworkCapabilities();
ctor public NetworkCapabilities(android.net.NetworkCapabilities);
method public int describeContents();
+ method @NonNull public int[] getCapabilities();
method public int getLinkDownstreamBandwidthKbps();
method public int getLinkUpstreamBandwidthKbps();
method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index 7a91f64..5bd01a6 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -19,7 +19,11 @@
method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo);
method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network);
method public void systemReady();
+ field public static final String ACTION_PROMPT_LOST_VALIDATION = "android.net.action.PROMPT_LOST_VALIDATION";
+ field public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = "android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
+ field public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED";
field public static final String PRIVATE_DNS_MODE_OFF = "off";
field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic";
field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname";
@@ -36,9 +40,18 @@
}
public final class NetworkCapabilities implements android.os.Parcelable {
+ method @Nullable public java.util.Set<android.util.Range<java.lang.Integer>> getUids();
field public static final int TRANSPORT_TEST = 7; // 0x7
}
+ public static final class NetworkCapabilities.Builder {
+ method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
+ }
+
+ public static class NetworkRequest.Builder {
+ method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
+ }
+
public class ParseException extends java.lang.RuntimeException {
ctor public ParseException(@NonNull String);
ctor public ParseException(@NonNull String, @NonNull Throwable);
diff --git a/core/jni/android_net_NetworkUtils.cpp b/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp
similarity index 79%
rename from core/jni/android_net_NetworkUtils.cpp
rename to packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp
index a781a37..19ffe77 100644
--- a/core/jni/android_net_NetworkUtils.cpp
+++ b/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp
@@ -36,7 +36,6 @@
#include <utils/misc.h>
#include "NetdClient.h"
-#include "core_jni_helpers.h"
#include "jni.h"
extern "C" {
@@ -52,6 +51,48 @@
// FrameworkListener limits the size of commands to 4096 bytes.
constexpr int MAXCMDSIZE = 4096;
+static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
+ jclass clazz = env->FindClass(class_name);
+ LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name);
+ return clazz;
+}
+
+static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
+ const char* method_signature) {
+ jmethodID res = env->GetMethodID(clazz, method_name, method_signature);
+ LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s with signature %s", method_name,
+ method_signature);
+ return res;
+}
+
+template <typename T>
+static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) {
+ jobject res = env->NewGlobalRef(in);
+ LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference.");
+ return static_cast<T>(res);
+}
+
+static void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
+ ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
+ if (detailMessage.get() == NULL) {
+ // Not really much we can do here. We're probably dead in the water,
+ // but let's try to stumble on...
+ env->ExceptionClear();
+ }
+ static jclass errnoExceptionClass =
+ MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/system/ErrnoException"));
+
+ static jmethodID errnoExceptionCtor =
+ GetMethodIDOrDie(env, errnoExceptionClass,
+ "<init>", "(Ljava/lang/String;I)V");
+
+ jobject exception = env->NewObject(errnoExceptionClass,
+ errnoExceptionCtor,
+ detailMessage.get(),
+ error);
+ env->Throw(reinterpret_cast<jthrowable>(exception));
+}
+
static void android_net_utils_attachDropAllBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd)
{
struct sock_filter filter_code[] = {
@@ -129,7 +170,7 @@
int fd = resNetworkQuery(netId, queryname.data(), ns_class, ns_type, flags);
if (fd < 0) {
- jniThrowErrnoException(env, "resNetworkQuery", -fd);
+ throwErrnoException(env, "resNetworkQuery", -fd);
return nullptr;
}
@@ -144,7 +185,7 @@
int fd = resNetworkSend(netId, data, msgLen, flags);
if (fd < 0) {
- jniThrowErrnoException(env, "resNetworkSend", -fd);
+ throwErrnoException(env, "resNetworkSend", -fd);
return nullptr;
}
@@ -159,13 +200,13 @@
int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE);
jniSetFileDescriptorOfFD(env, javaFd, -1);
if (res < 0) {
- jniThrowErrnoException(env, "resNetworkResult", -res);
+ throwErrnoException(env, "resNetworkResult", -res);
return nullptr;
}
jbyteArray answer = env->NewByteArray(res);
if (answer == nullptr) {
- jniThrowErrnoException(env, "resNetworkResult", ENOMEM);
+ throwErrnoException(env, "resNetworkResult", ENOMEM);
return nullptr;
} else {
env->SetByteArrayRegion(answer, 0, res,
@@ -187,7 +228,7 @@
static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) {
unsigned dnsNetId = 0;
if (int res = getNetworkForDns(&dnsNetId) < 0) {
- jniThrowErrnoException(env, "getDnsNetId", -res);
+ throwErrnoException(env, "getDnsNetId", -res);
return nullptr;
}
bool privateDnsBypass = dnsNetId & NETID_USE_LOCAL_NAMESERVERS;
@@ -212,7 +253,7 @@
// Obtain the parameters of the TCP repair window.
int rc = getsockopt(fd, IPPROTO_TCP, TCP_REPAIR_WINDOW, &trw, &size);
if (rc == -1) {
- jniThrowErrnoException(env, "getsockopt : TCP_REPAIR_WINDOW", errno);
+ throwErrnoException(env, "getsockopt : TCP_REPAIR_WINDOW", errno);
return NULL;
}
@@ -223,7 +264,7 @@
// should be applied to the window size.
rc = getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpinfo, &tcpinfo_size);
if (rc == -1) {
- jniThrowErrnoException(env, "getsockopt : TCP_INFO", errno);
+ throwErrnoException(env, "getsockopt : TCP_INFO", errno);
return NULL;
}
@@ -260,8 +301,8 @@
int register_android_net_NetworkUtils(JNIEnv* env)
{
- return RegisterMethodsOrDie(env, NETUTILS_PKG_NAME, gNetworkUtilMethods,
- NELEM(gNetworkUtilMethods));
+ return jniRegisterNativeMethods(env, NETUTILS_PKG_NAME, gNetworkUtilMethods,
+ NELEM(gNetworkUtilMethods));
}
}; // namespace android
diff --git a/packages/Connectivity/framework/jni/onload.cpp b/packages/Connectivity/framework/jni/onload.cpp
new file mode 100644
index 0000000..435f434
--- /dev/null
+++ b/packages/Connectivity/framework/jni/onload.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include <nativehelper/JNIHelp.h>
+#include <log/log.h>
+
+namespace android {
+
+int register_android_net_NetworkUtils(JNIEnv* env);
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+ JNIEnv *env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ ALOGE("GetEnv failed");
+ return JNI_ERR;
+ }
+
+ if (register_android_net_NetworkUtils(env) < 0) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_6;
+}
+
+};
\ No newline at end of file
diff --git a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
index 82dbd0f..53aa1b9 100644
--- a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
+++ b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
@@ -42,7 +42,7 @@
private final long mByteLimit;
private final long mExpiryTimeMillis;
private final boolean mCaptive;
- private final CharSequence mVenueFriendlyName;
+ private final String mVenueFriendlyName;
private final int mVenueInfoUrlSource;
private final int mUserPortalUrlSource;
@@ -73,14 +73,14 @@
mByteLimit = byteLimit;
mExpiryTimeMillis = expiryTimeMillis;
mCaptive = captive;
- mVenueFriendlyName = venueFriendlyName;
+ mVenueFriendlyName = venueFriendlyName == null ? null : venueFriendlyName.toString();
mVenueInfoUrlSource = venueInfoUrlSource;
mUserPortalUrlSource = userPortalUrlSource;
}
private CaptivePortalData(Parcel p) {
this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(),
- p.readLong(), p.readLong(), p.readBoolean(), p.readCharSequence(), p.readInt(),
+ p.readLong(), p.readLong(), p.readBoolean(), p.readString(), p.readInt(),
p.readInt());
}
@@ -98,7 +98,7 @@
dest.writeLong(mByteLimit);
dest.writeLong(mExpiryTimeMillis);
dest.writeBoolean(mCaptive);
- dest.writeCharSequence(mVenueFriendlyName);
+ dest.writeString(mVenueFriendlyName);
dest.writeInt(mVenueInfoUrlSource);
dest.writeInt(mUserPortalUrlSource);
}
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index 9f63abf..f8a0e4e 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -73,7 +73,6 @@
import android.util.Range;
import android.util.SparseIntArray;
-import com.android.connectivity.aidl.INetworkAgent;
import com.android.internal.annotations.GuardedBy;
import libcore.net.event.NetworkEventDispatcher;
@@ -424,7 +423,8 @@
*
* @hide
*/
- public static final String ACTION_PROMPT_UNVALIDATED = "android.net.conn.PROMPT_UNVALIDATED";
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED";
/**
* Action used to display a dialog that asks the user whether to avoid a network that is no
@@ -432,8 +432,9 @@
*
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public static final String ACTION_PROMPT_LOST_VALIDATION =
- "android.net.conn.PROMPT_LOST_VALIDATION";
+ "android.net.action.PROMPT_LOST_VALIDATION";
/**
* Action used to display a dialog that asks the user whether to stay connected to a network
@@ -442,8 +443,9 @@
*
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY =
- "android.net.conn.PROMPT_PARTIAL_CONNECTIVITY";
+ "android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
/**
* Invalid tethering type.
@@ -4467,12 +4469,20 @@
/**
* Requests that the system open the captive portal app on the specified network.
*
+ * <p>This is to be used on networks where a captive portal was detected, as per
+ * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}.
+ *
* @param network The network to log into.
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
- public void startCaptivePortalApp(Network network) {
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_STACK,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+ })
+ public void startCaptivePortalApp(@NonNull Network network) {
try {
mService.startCaptivePortalApp(network);
} catch (RemoteException e) {
diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
index 98f3d40..3300fa8 100644
--- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
+++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
@@ -20,6 +20,7 @@
import android.net.ConnectionInfo;
import android.net.ConnectivityDiagnosticsManager;
import android.net.IConnectivityDiagnosticsCallback;
+import android.net.INetworkAgent;
import android.net.IOnCompleteListener;
import android.net.INetworkActivityListener;
import android.net.IQosCallback;
@@ -45,8 +46,6 @@
import android.os.ResultReceiver;
import android.os.UserHandle;
-import com.android.connectivity.aidl.INetworkAgent;
-
/**
* Interface that answers queries about, and allows changing, the
* state of network connectivity.
diff --git a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
similarity index 94%
rename from packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl
rename to packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
index 64b5567..1f66e18 100644
--- a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl
+++ b/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl
@@ -13,13 +13,13 @@
* See the License for the specific language governing perNmissions and
* limitations under the License.
*/
-package com.android.connectivity.aidl;
+package android.net;
import android.net.NattKeepalivePacketData;
import android.net.QosFilterParcelable;
import android.net.TcpKeepalivePacketData;
-import com.android.connectivity.aidl.INetworkAgentRegistry;
+import android.net.INetworkAgentRegistry;
/**
* Interface to notify NetworkAgent of connectivity events.
diff --git a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
similarity index 97%
rename from packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl
rename to packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
index 18d26a7..c5464d3 100644
--- a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl
+++ b/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl
@@ -13,7 +13,7 @@
* See the License for the specific language governing perNmissions and
* limitations under the License.
*/
-package com.android.connectivity.aidl;
+package android.net;
import android.net.LinkProperties;
import android.net.Network;
diff --git a/packages/Connectivity/framework/src/android/net/InetAddressCompat.java b/packages/Connectivity/framework/src/android/net/InetAddressCompat.java
index 8404441..6b7e75c 100644
--- a/packages/Connectivity/framework/src/android/net/InetAddressCompat.java
+++ b/packages/Connectivity/framework/src/android/net/InetAddressCompat.java
@@ -41,7 +41,12 @@
public static void clearDnsCache() {
try {
InetAddress.class.getMethod("clearDnsCache").invoke(null);
- } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof RuntimeException) {
+ throw (RuntimeException) e.getCause();
+ }
+ throw new IllegalStateException("Unknown InvocationTargetException", e.getCause());
+ } catch (IllegalAccessException | NoSuchMethodException e) {
Log.wtf(InetAddressCompat.class.getSimpleName(), "Error clearing DNS cache", e);
}
}
@@ -51,13 +56,7 @@
*/
public static InetAddress[] getAllByNameOnNet(String host, int netId) throws
UnknownHostException {
- try {
- return (InetAddress[]) InetAddress.class.getMethod("getAllByNameOnNet",
- String.class, int.class).invoke(null, host, netId);
- } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
- Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e);
- throw new IllegalStateException("Error querying via getAllNameOnNet", e);
- }
+ return (InetAddress[]) callGetByNameMethod("getAllByNameOnNet", host, netId);
}
/**
@@ -65,12 +64,25 @@
*/
public static InetAddress getByNameOnNet(String host, int netId) throws
UnknownHostException {
+ return (InetAddress) callGetByNameMethod("getByNameOnNet", host, netId);
+ }
+
+ private static Object callGetByNameMethod(String method, String host, int netId)
+ throws UnknownHostException {
try {
- return (InetAddress) InetAddress.class.getMethod("getByNameOnNet",
- String.class, int.class).invoke(null, host, netId);
- } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
- Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e);
- throw new IllegalStateException("Error querying via getByNameOnNet", e);
+ return InetAddress.class.getMethod(method, String.class, int.class)
+ .invoke(null, host, netId);
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof UnknownHostException) {
+ throw (UnknownHostException) e.getCause();
+ }
+ if (e.getCause() instanceof RuntimeException) {
+ throw (RuntimeException) e.getCause();
+ }
+ throw new IllegalStateException("Unknown InvocationTargetException", e.getCause());
+ } catch (IllegalAccessException | NoSuchMethodException e) {
+ Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling " + method, e);
+ throw new IllegalStateException("Error querying via " + method, e);
}
}
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgent.java b/packages/Connectivity/framework/src/android/net/NetworkAgent.java
index a127c6f..1416bb9 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkAgent.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkAgent.java
@@ -34,8 +34,6 @@
import android.telephony.data.EpsBearerQosSessionAttributes;
import android.util.Log;
-import com.android.connectivity.aidl.INetworkAgent;
-import com.android.connectivity.aidl.INetworkAgentRegistry;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
index 664c265..5e50a64 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
@@ -50,7 +50,8 @@
* ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to
* connect to a particular access point is also explicit, though this may change in the future
* as we want apps to use the multinetwork apis.
- *
+ * TODO : this is a bad name, because it sounds like the user just tapped on the network.
+ * It's not necessarily the case ; auto-reconnection to WiFi has this true for example.
* @hide
*/
public boolean explicitlySelected;
diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
index c6dfcee..1466629 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.ConnectivityManager.NetworkCallback;
@@ -32,6 +33,7 @@
import android.os.Process;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.Range;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
@@ -152,7 +154,7 @@
setTransportInfo(null);
}
mSignalStrength = nc.mSignalStrength;
- setUids(nc.mUids); // Will make the defensive copy
+ mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids);
setAdministratorUids(nc.getAdministratorUids());
mOwnerUid = nc.mOwnerUid;
mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
@@ -608,10 +610,8 @@
* Gets all the capabilities set on this {@code NetworkCapability} instance.
*
* @return an array of capability values for this instance.
- * @hide
*/
- @UnsupportedAppUsage
- public @NetCapability int[] getCapabilities() {
+ public @NonNull @NetCapability int[] getCapabilities() {
return NetworkCapabilitiesUtils.unpackBits(mNetworkCapabilities);
}
@@ -1457,9 +1457,8 @@
* @hide
*/
public @NonNull NetworkCapabilities setSingleUid(int uid) {
- final ArraySet<UidRange> identity = new ArraySet<>(1);
- identity.add(new UidRange(uid, uid));
- setUids(identity);
+ mUids = new ArraySet<>(1);
+ mUids.add(new UidRange(uid, uid));
return this;
}
@@ -1468,22 +1467,34 @@
* This makes a copy of the set so that callers can't modify it after the call.
* @hide
*/
- public @NonNull NetworkCapabilities setUids(Set<UidRange> uids) {
- if (null == uids) {
- mUids = null;
- } else {
- mUids = new ArraySet<>(uids);
- }
+ public @NonNull NetworkCapabilities setUids(@Nullable Set<Range<Integer>> uids) {
+ mUids = UidRange.fromIntRanges(uids);
return this;
}
/**
* Get the list of UIDs this network applies to.
* This returns a copy of the set so that callers can't modify the original object.
+ *
+ * @return the list of UIDs this network applies to. If {@code null}, then the network applies
+ * to all UIDs.
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("NullableCollection")
+ public @Nullable Set<Range<Integer>> getUids() {
+ return UidRange.toIntRanges(mUids);
+ }
+
+ /**
+ * Get the list of UIDs this network applies to.
+ * This returns a copy of the set so that callers can't modify the original object.
* @hide
*/
- public @Nullable Set<UidRange> getUids() {
- return null == mUids ? null : new ArraySet<>(mUids);
+ public @Nullable Set<UidRange> getUidRanges() {
+ if (mUids == null) return null;
+
+ return new ArraySet<>(mUids);
}
/**
@@ -2656,6 +2667,21 @@
}
/**
+ * Set the list of UIDs this network applies to.
+ *
+ * @param uids the list of UIDs this network applies to, or {@code null} if this network
+ * applies to all UIDs.
+ * @return this builder
+ * @hide
+ */
+ @NonNull
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public Builder setUids(@Nullable Set<Range<Integer>> uids) {
+ mCaps.setUids(uids);
+ return this;
+ }
+
+ /**
* Builds the instance of the capabilities.
*
* @return the built instance of NetworkCapabilities.
diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
index dbe3ecc..cf131f0 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -36,6 +36,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkCapabilities.NetCapability;
@@ -45,6 +46,7 @@
import android.os.Parcelable;
import android.os.Process;
import android.text.TextUtils;
+import android.util.Range;
import android.util.proto.ProtoOutputStream;
import java.util.Arrays;
@@ -277,11 +279,14 @@
* Set the watched UIDs for this request. This will be reset and wiped out unless
* the calling app holds the CHANGE_NETWORK_STATE permission.
*
- * @param uids The watched UIDs as a set of UidRanges, or null for everything.
+ * @param uids The watched UIDs as a set of {@code Range<Integer>}, or null for everything.
* @return The builder to facilitate chaining.
* @hide
*/
- public Builder setUids(Set<UidRange> uids) {
+ @NonNull
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public Builder setUids(@Nullable Set<Range<Integer>> uids) {
mNetworkCapabilities.setUids(uids);
return this;
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkScore.java b/packages/Connectivity/framework/src/android/net/NetworkScore.java
index f478010..eadcb2d 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkScore.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkScore.java
@@ -20,6 +20,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Object representing the quality of a network as perceived by the user.
*
@@ -33,19 +35,39 @@
// a migration.
private final int mLegacyInt;
+ // Agent-managed policies
+ // TODO : add them here, starting from 1
/** @hide */
- NetworkScore(final int legacyInt) {
- this.mLegacyInt = legacyInt;
+ public static final int MIN_AGENT_MANAGED_POLICY = 0;
+ /** @hide */
+ public static final int MAX_AGENT_MANAGED_POLICY = -1;
+
+ // Bitmask of all the policies applied to this score.
+ private final long mPolicies;
+
+ /** @hide */
+ NetworkScore(final int legacyInt, final long policies) {
+ mLegacyInt = legacyInt;
+ mPolicies = policies;
}
private NetworkScore(@NonNull final Parcel in) {
mLegacyInt = in.readInt();
+ mPolicies = in.readLong();
}
public int getLegacyInt() {
return mLegacyInt;
}
+ /**
+ * @return whether this score has a particular policy.
+ */
+ @VisibleForTesting
+ public boolean hasPolicy(final int policy) {
+ return 0 != (mPolicies & (1L << policy));
+ }
+
@Override
public String toString() {
return "Score(" + mLegacyInt + ")";
@@ -54,6 +76,7 @@
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
dest.writeInt(mLegacyInt);
+ dest.writeLong(mPolicies);
}
@Override
@@ -79,6 +102,7 @@
* A builder for NetworkScore.
*/
public static final class Builder {
+ private static final long POLICY_NONE = 0L;
private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE;
private int mLegacyInt = INVALID_LEGACY_INT;
@@ -102,7 +126,7 @@
*/
@NonNull
public NetworkScore build() {
- return new NetworkScore(mLegacyInt);
+ return new NetworkScore(mLegacyInt, POLICY_NONE);
}
}
}
diff --git a/packages/Connectivity/framework/src/android/net/UidRange.java b/packages/Connectivity/framework/src/android/net/UidRange.java
index 26518d3..bc67c74 100644
--- a/packages/Connectivity/framework/src/android/net/UidRange.java
+++ b/packages/Connectivity/framework/src/android/net/UidRange.java
@@ -20,8 +20,11 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Range;
import java.util.Collection;
+import java.util.Set;
/**
* An inclusive range of UIDs.
@@ -149,4 +152,32 @@
}
return false;
}
+
+ /**
+ * Convert a set of {@code Range<Integer>} to a set of {@link UidRange}.
+ */
+ @Nullable
+ public static ArraySet<UidRange> fromIntRanges(@Nullable Set<Range<Integer>> ranges) {
+ if (null == ranges) return null;
+
+ final ArraySet<UidRange> uids = new ArraySet<>();
+ for (Range<Integer> range : ranges) {
+ uids.add(new UidRange(range.getLower(), range.getUpper()));
+ }
+ return uids;
+ }
+
+ /**
+ * Convert a set of {@link UidRange} to a set of {@code Range<Integer>}.
+ */
+ @Nullable
+ public static ArraySet<Range<Integer>> toIntRanges(@Nullable Set<UidRange> ranges) {
+ if (null == ranges) return null;
+
+ final ArraySet<Range<Integer>> uids = new ArraySet<>();
+ for (UidRange range : ranges) {
+ uids.add(new Range<Integer>(range.start, range.stop));
+ }
+ return uids;
+ }
}
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png
new file mode 100644
index 0000000..74977e6
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png
new file mode 100644
index 0000000..62e4fe9
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png
new file mode 100644
index 0000000..c0586d8
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png
new file mode 100644
index 0000000..86c34ed
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml
new file mode 100644
index 0000000..a271ca5
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="26.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="26.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M19.1,14l-3.4,0l0,-1.5c0,-1.8 0.8,-2.8 1.5,-3.4C18.1,8.3 19.200001,8 20.6,8c1.2,0 2.3,0.3 3.1,0.8l1.9,-2.3C25.1,6.1 20.299999,2.1 13,2.1S0.9,6.1 0.4,6.5L13,22l0,0l0,0l0,0l0,0l6.5,-8.1L19.1,14z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19.5,17.799999c0,-0.8 0.1,-1.3 0.2,-1.6c0.2,-0.3 0.5,-0.7 1.1,-1.2c0.4,-0.4 0.7,-0.8 1,-1.1s0.4,-0.8 0.4,-1.2c0,-0.5 -0.1,-0.9 -0.4,-1.2c-0.3,-0.3 -0.7,-0.4 -1.2,-0.4c-0.4,0 -0.8,0.1 -1.1,0.3c-0.3,0.2 -0.4,0.6 -0.4,1.1l-1.9,0c0,-1 0.3,-1.7 1,-2.2c0.6,-0.5 1.5,-0.8 2.5,-0.8c1.1,0 2,0.3 2.6,0.8c0.6,0.5 0.9,1.3 0.9,2.3c0,0.7 -0.2,1.3 -0.6,1.8c-0.4,0.6 -0.9,1.1 -1.5,1.6c-0.3,0.3 -0.5,0.5 -0.6,0.7c-0.1,0.2 -0.1,0.6 -0.1,1L19.5,17.700001zM21.4,21l-1.9,0l0,-1.8l1.9,0L21.4,21z"/>
+</vector>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-af/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-af/strings.xml
new file mode 100644
index 0000000..68720d5
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-af/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Meld aan by Wi-Fi-netwerk"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Meld by netwerk aan"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> het geen internettoegang nie"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tik vir opsies"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Selnetwerk het nie internettoegang nie"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Netwerk het nie internettoegang nie"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Daar kan nie by private DNS-bediener ingegaan word nie"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> het beperkte konnektiwiteit"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tik om in elk geval te koppel"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Het oorgeskakel na <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Toestel gebruik <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wanneer <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> geen internettoegang het nie. Heffings kan geld."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Het oorgeskakel van <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"\'n onbekende netwerktipe"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobiele data"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-am/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-am/strings.xml
new file mode 100644
index 0000000..78d9283
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-am/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ወደ Wi-Fi አውታረ መረብ በመለያ ግባ"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ወደ አውታረ መረብ በመለያ ይግቡ"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ምንም የበይነ መረብ መዳረሻ የለም"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ለአማራጮች መታ ያድርጉ"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"የተንቀሳቃሽ ስልክ አውታረ መረብ የበይነመረብ መዳረሻ የለውም"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"አውታረ መረብ የበይነመረብ መዳረሻ የለውም"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"የግል ዲኤንኤስ አገልጋይ ሊደረስበት አይችልም"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> የተገደበ ግንኙነት አለው"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ለማንኛውም ለማገናኘት መታ ያድርጉ"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"ወደ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ተቀይሯል"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ምንም ዓይነት የበይነመረብ ግንኙነት በማይኖረው ጊዜ መሣሪያዎች <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ን ይጠቀማሉ። ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ።"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"ከ<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ወደ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ተቀይሯል"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"አንድ ያልታወቀ አውታረ መረብ ዓይነት"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"የተንቀሳቃሽ ስልክ ውሂብ"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"ብሉቱዝ"</item>
+ <item msgid="1616528372438698248">"ኤተርኔት"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ar/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ar/strings.xml
new file mode 100644
index 0000000..8698a7e
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ar/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"تسجيل الدخول إلى شبكة Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"تسجيل الدخول إلى الشبكة"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"لا يتوفّر في <xliff:g id="NETWORK_SSID">%1$s</xliff:g> إمكانية الاتصال بالإنترنت."</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"انقر للحصول على الخيارات."</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"شبكة الجوّال هذه غير متصلة بالإنترنت"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"الشبكة غير متصلة بالإنترنت"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"إمكانية اتصال <xliff:g id="NETWORK_SSID">%1$s</xliff:g> محدودة."</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"يمكنك النقر للاتصال على أي حال."</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"تم التبديل إلى <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"يستخدم الجهاز <xliff:g id="NEW_NETWORK">%1$s</xliff:g> عندما لا يتوفر اتصال بالإنترنت في شبكة <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>، ويمكن أن يتم فرض رسوم مقابل ذلك."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"تم التبديل من <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> إلى <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"نوع شبكة غير معروف"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"بيانات الجوّال"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"بلوتوث"</item>
+ <item msgid="1616528372438698248">"إيثرنت"</item>
+ <item msgid="9177085807664964627">"شبكة افتراضية خاصة (VPN)"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-as/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-as/strings.xml
new file mode 100644
index 0000000..10b234a
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-as/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ৱাই-ফাই নেটৱৰ্কত ছাইন ইন কৰক"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"নেটৱৰ্কত ছাইন ইন কৰক"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ৰ ইণ্টাৰনেটৰ এক্সেছ নাই"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"অধিক বিকল্পৰ বাবে টিপক"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"ম’বাইল নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ৰ সকলো সেৱাৰ এক্সেছ নাই"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"যিকোনো প্ৰকাৰে সংযোগ কৰিবলৈ টিপক"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>লৈ সলনি কৰা হ’ল"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"যেতিয়া <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>ত ইণ্টাৰনেট নাথাকে, তেতিয়া ডিভাইচে <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ক ব্যৱহাৰ কৰে। মাচুল প্ৰযোজ্য হ\'ব পাৰে।"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>ৰ পৰা <xliff:g id="NEW_NETWORK">%2$s</xliff:g> লৈ সলনি কৰা হ’ল"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"অজ্ঞাত প্ৰকাৰৰ নেটৱৰ্ক"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"ম’বাইল ডেটা"</item>
+ <item msgid="5520925862115353992">"ৱাই-ফাই"</item>
+ <item msgid="1055487873974272842">"ব্লুটুথ"</item>
+ <item msgid="1616528372438698248">"ইথাৰনেট"</item>
+ <item msgid="9177085807664964627">"ভিপিএন"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-az/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-az/strings.xml
new file mode 100644
index 0000000..d75a204
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-az/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi şəbəkəsinə daxil ol"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Şəbəkəyə daxil olun"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> üçün internet girişi əlçatan deyil"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Seçimlər üçün tıklayın"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobil şəbəkənin internetə girişi yoxdur"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Şəbəkənin internetə girişi yoxdur"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Özəl DNS serverinə giriş mümkün deyil"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> bağlantını məhdudlaşdırdı"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"İstənilən halda klikləyin"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> şəbəkə növünə keçirildi"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> şəbəkəsinin internetə girişi olmadıqda, cihaz <xliff:g id="NEW_NETWORK">%1$s</xliff:g> şəbəkəsini istifadə edir. Xidmət haqqı tutula bilər."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> şəbəkəsindən <xliff:g id="NEW_NETWORK">%2$s</xliff:g> şəbəkəsinə keçirildi"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"naməlum şəbəkə növü"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobil data"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..11e4957
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Prijavljivanje na WiFi mrežu"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Prijavite se na mrežu"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nema pristup internetu"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Dodirnite za opcije"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilna mreža nema pristup internetu"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Mreža nema pristup internetu"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Pristup privatnom DNS serveru nije uspeo"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ima ograničenu vezu"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Dodirnite da biste se ipak povezali"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Prešli ste na tip mreže <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Uređaj koristi tip mreže <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kada tip mreže <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu. Možda će se naplaćivati troškovi."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Prešli ste sa tipa mreže <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na tip mreže <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nepoznat tip mreže"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobilni podaci"</item>
+ <item msgid="5520925862115353992">"WiFi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Eternet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-be/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-be/strings.xml
new file mode 100644
index 0000000..6b0b1f1
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-be/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Уваход у сетку Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Увайдзіце ў сетку"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> не мае доступу ў інтэрнэт"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Дакраніцеся, каб убачыць параметры"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Мабільная сетка не мае доступу ў інтэрнэт"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Сетка не мае доступу ў інтэрнэт"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Не ўдалося атрымаць доступ да прыватнага DNS-сервера"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> мае абмежаваную магчымасць падключэння"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Націсніце, каб падключыцца"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Выкананы пераход да <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Прылада выкарыстоўвае сетку <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, калі ў сетцы <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> няма доступу да інтэрнэту. Можа спаганяцца плата."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Выкананы пераход з <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> да <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"невядомы тып сеткі"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"мабільная перадача даных"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bg/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bg/strings.xml
new file mode 100644
index 0000000..6427bd0
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bg/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Влизане в Wi-Fi мрежа"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Вход в мрежата"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> няма достъп до интернет"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Докоснете за опции"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Мобилната мрежа няма достъп до интернет"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Мрежата няма достъп до интернет"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Не може да се осъществи достъп до частния DNS сървър"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> има ограничена свързаност"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Докоснете, за да се свържете въпреки това"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Превключи се към <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Устройството използва <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, когато <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> няма достъп до интернет. Възможно е да бъдете таксувани."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Превключи се от <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> към <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"неизвестен тип мрежа"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"мобилни данни"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"виртуална частна мрежа (VPN)"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bn/strings.xml
new file mode 100644
index 0000000..74d4cd6
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bn/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ওয়াই-ফাই নেটওয়ার্কে সাইন-ইন করুন"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"নেটওয়ার্কে সাইন-ইন করুন"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-এর ইন্টারনেটে অ্যাক্সেস নেই"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"বিকল্পগুলির জন্য আলতো চাপুন"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"মোবাইল নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ব্যক্তিগত ডিএনএস সার্ভার অ্যাক্সেস করা যাবে না"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-এর সীমিত কানেক্টিভিটি আছে"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"তবুও কানেক্ট করতে ট্যাপ করুন"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> এ পাল্টানো হয়েছে"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> এ ইন্টারনেট অ্যাক্সেস না থাকলে <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ব্যবহার করা হয়৷ ডেটা চার্জ প্রযোজ্য৷"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> থেকে <xliff:g id="NEW_NETWORK">%2$s</xliff:g> এ পাল্টানো হয়েছে"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"এই নেটওয়ার্কের প্রকার অজানা"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"মোবাইল ডেটা"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"ব্লুটুথ"</item>
+ <item msgid="1616528372438698248">"ইথারনেট"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bs/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bs/strings.xml
new file mode 100644
index 0000000..19f6e1a
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bs/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Prijavljivanje na WiFi mrežu"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Prijava na mrežu"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Mreža <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nema pristup internetu"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Dodirnite za opcije"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilna mreža nema pristup internetu"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Mreža nema pristup internetu"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Nije moguće pristupiti privatnom DNS serveru"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Mreža <xliff:g id="NETWORK_SSID">%1$s</xliff:g> ima ograničenu povezivost"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Dodirnite da se ipak povežete"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Prebačeno na: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Kada <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu, uređaj koristi mrežu <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Moguća je naplata usluge."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Prebačeno iz mreže <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> u <xliff:g id="NEW_NETWORK">%2$s</xliff:g> mrežu"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nepoznata vrsta mreže"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"prijenos podataka na mobilnoj mreži"</item>
+ <item msgid="5520925862115353992">"WiFi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ca/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ca/strings.xml
new file mode 100644
index 0000000..c55684d
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ca/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Inicia la sessió a la xarxa Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Inicia la sessió a la xarxa"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> no té accés a Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toca per veure les opcions"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"La xarxa mòbil no té accés a Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"La xarxa no té accés a Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"No es pot accedir al servidor DNS privat"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> té una connectivitat limitada"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toca per connectar igualment"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Actualment en ús: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"El dispositiu utilitza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> en cas que <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tingui accés a Internet. És possible que s\'hi apliquin càrrecs."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Abans es feia servir la xarxa <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>; ara s\'utilitza <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"una tipus de xarxa desconegut"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"dades mòbils"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-cs/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-cs/strings.xml
new file mode 100644
index 0000000..fa8c411
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-cs/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Přihlásit se k síti Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Přihlásit se k síti"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Síť <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nemá přístup k internetu"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Klepnutím zobrazíte možnosti"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilní síť nemá přístup k internetu"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Síť nemá přístup k internetu"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Nelze získat přístup k soukromému serveru DNS"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Síť <xliff:g id="NETWORK_SSID">%1$s</xliff:g> umožňuje jen omezené připojení"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Klepnutím se i přesto připojíte"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Přechod na síť <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Když síť <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nebude mít přístup k internetu, zařízení použije síť <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Mohou být účtovány poplatky."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Přechod ze sítě <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na síť <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"neznámý typ sítě"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobilní data"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-da/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-da/strings.xml
new file mode 100644
index 0000000..f7be6df
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-da/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Log ind på Wi-Fi-netværk"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Log ind på netværk"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har ingen internetforbindelse"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tryk for at se valgmuligheder"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilnetværket har ingen internetadgang"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Netværket har ingen internetadgang"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Der er ikke adgang til den private DNS-server"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har begrænset forbindelse"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tryk for at oprette forbindelse alligevel"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Der blev skiftet til <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Enheden benytter <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, når der ikke er internetadgang via <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>. Der opkræves muligvis betaling."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Der blev skiftet fra <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> til <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"en ukendt netværkstype"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobildata"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-de/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-de/strings.xml
new file mode 100644
index 0000000..1e7b80c
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-de/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"In WLAN anmelden"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Im Netzwerk anmelden"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> hat keinen Internetzugriff"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Für Optionen tippen"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiles Netzwerk hat keinen Internetzugriff"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Netzwerk hat keinen Internetzugriff"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Auf den privaten DNS-Server kann nicht zugegriffen werden"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Schlechte Verbindung mit <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tippen, um die Verbindung trotzdem herzustellen"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Zu <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> gewechselt"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Auf dem Gerät werden <xliff:g id="NEW_NETWORK">%1$s</xliff:g> genutzt, wenn über <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> kein Internet verfügbar ist. Eventuell fallen Gebühren an."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Von \"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>\" zu \"<xliff:g id="NEW_NETWORK">%2$s</xliff:g>\" gewechselt"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ein unbekannter Netzwerktyp"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"Mobile Daten"</item>
+ <item msgid="5520925862115353992">"WLAN"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-el/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-el/strings.xml
new file mode 100644
index 0000000..89647fdb
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-el/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Συνδεθείτε στο δίκτυο Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Σύνδεση στο δίκτυο"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Η εφαρμογή <xliff:g id="NETWORK_SSID">%1$s</xliff:g> δεν έχει πρόσβαση στο διαδίκτυο"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Πατήστε για να δείτε τις επιλογές"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Το δίκτυο κινητής τηλεφωνίας δεν έχει πρόσβαση στο διαδίκτυο."</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Το δίκτυο δεν έχει πρόσβαση στο διαδίκτυο."</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Δεν είναι δυνατή η πρόσβαση στον ιδιωτικό διακομιστή DNS."</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Το δίκτυο <xliff:g id="NETWORK_SSID">%1$s</xliff:g> έχει περιορισμένη συνδεσιμότητα"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Πατήστε για σύνδεση ούτως ή άλλως"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Μετάβαση σε δίκτυο <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Η συσκευή χρησιμοποιεί το δίκτυο <xliff:g id="NEW_NETWORK">%1$s</xliff:g> όταν το δίκτυο <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> δεν έχει πρόσβαση στο διαδίκτυο. Μπορεί να ισχύουν χρεώσεις."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Μετάβαση από το δίκτυο <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> στο δίκτυο <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"άγνωστος τύπος δικτύου"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"δεδομένα κινητής τηλεφωνίας"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..d29e2ec
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to a Wi-Fi network"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no Internet access"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no Internet access"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no Internet access"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobile data"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..d29e2ec
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to a Wi-Fi network"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no Internet access"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no Internet access"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no Internet access"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobile data"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..d29e2ec
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to a Wi-Fi network"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no Internet access"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no Internet access"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no Internet access"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobile data"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..d29e2ec
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to a Wi-Fi network"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no Internet access"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no Internet access"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no Internet access"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobile data"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..cd69133
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Sign in to Wi-Fi network"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Sign in to network"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has no internet access"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tap for options"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobile network has no internet access"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Network has no internet access"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Private DNS server cannot be accessed"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> has limited connectivity"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tap to connect anyway"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no internet access. Charges may apply."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"an unknown network type"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobile data"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..9102dc0
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Accede a una red Wi-Fi."</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Acceder a la red"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>no tiene acceso a Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Presiona para ver opciones"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"La red móvil no tiene acceso a Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"La red no tiene acceso a Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"No se puede acceder al servidor DNS privado"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tiene conectividad limitada"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Presiona para conectarte de todas formas"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Se cambió a <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"El dispositivo usa <xliff:g id="NEW_NETWORK">%1$s</xliff:g> cuando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tiene acceso a Internet. Es posible que se apliquen cargos."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Se cambió de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"un tipo de red desconocido"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"Datos móviles"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-es/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es/strings.xml
new file mode 100644
index 0000000..4c15566
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Iniciar sesión en red Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Iniciar sesión en la red"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> no tiene acceso a Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toca para ver opciones"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"La red móvil no tiene acceso a Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"La red no tiene acceso a Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"No se ha podido acceder al servidor DNS privado"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tiene una conectividad limitada"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toca para conectarte de todas formas"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Se ha cambiado a <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"El dispositivo utiliza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> cuando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tiene acceso a Internet. Es posible que se apliquen cargos."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Se ha cambiado de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"tipo de red desconocido"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"datos móviles"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-et/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-et/strings.xml
new file mode 100644
index 0000000..398223a
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-et/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Logi sisse WiFi-võrku"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Võrku sisselogimine"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Võrgul <xliff:g id="NETWORK_SSID">%1$s</xliff:g> puudub Interneti-ühendus"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Puudutage valikute nägemiseks"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiilsidevõrgul puudub Interneti-ühendus"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Võrgul puudub Interneti-ühendus"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Privaatsele DNS-serverile ei pääse juurde"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Võrgu <xliff:g id="NETWORK_SSID">%1$s</xliff:g> ühendus on piiratud"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Puudutage, kui soovite siiski ühenduse luua"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Lülitati võrgule <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Seade kasutab võrku <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, kui võrgul <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> puudub juurdepääs Internetile. Rakenduda võivad tasud."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Lülitati võrgult <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> võrgule <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"tundmatu võrgutüüp"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobiilne andmeside"</item>
+ <item msgid="5520925862115353992">"WiFi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-eu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-eu/strings.xml
new file mode 100644
index 0000000..dd70316
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-eu/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Hasi saioa Wi-Fi sarean"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Hasi saioa sarean"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Ezin da konektatu Internetera <xliff:g id="NETWORK_SSID">%1$s</xliff:g> sarearen bidez"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Sakatu aukerak ikusteko"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Sare mugikorra ezin da konektatu Internetera"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Sarea ezin da konektatu Internetera"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Ezin da atzitu DNS zerbitzari pribatua"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> sareak konektagarritasun murriztua du"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Sakatu hala ere konektatzeko"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> erabiltzen ari zara orain"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> Internetera konektatzeko gauza ez denean, <xliff:g id="NEW_NETWORK">%1$s</xliff:g> erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> erabiltzen ari zinen, baina <xliff:g id="NEW_NETWORK">%2$s</xliff:g> erabiltzen ari zara orain"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"sare mota ezezaguna"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"datu-konexioa"</item>
+ <item msgid="5520925862115353992">"Wifia"</item>
+ <item msgid="1055487873974272842">"Bluetooth-a"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fa/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fa/strings.xml
new file mode 100644
index 0000000..46a946c
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fa/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ورود به شبکه Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ورود به سیستم شبکه"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> به اینترنت دسترسی ندارد"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"برای گزینهها ضربه بزنید"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"شبکه تلفن همراه به اینترنت دسترسی ندارد"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"شبکه به اینترنت دسترسی ندارد"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"سرور DNS خصوصی قابل دسترسی نیست"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> اتصال محدودی دارد"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"بههرصورت، برای اتصال ضربه بزنید"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"به <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> تغییر کرد"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"وقتی <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> به اینترنت دسترسی نداشته باشد، دستگاه از <xliff:g id="NEW_NETWORK">%1$s</xliff:g> استفاده میکند. ممکن است هزینههایی اعمال شود."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"از <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> به <xliff:g id="NEW_NETWORK">%2$s</xliff:g> تغییر کرد"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"نوع شبکه نامشخص"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"داده تلفن همراه"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"بلوتوث"</item>
+ <item msgid="1616528372438698248">"اترنت"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fi/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fi/strings.xml
new file mode 100644
index 0000000..dd94441
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fi/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Kirjaudu Wi-Fi-verkkoon"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Kirjaudu verkkoon"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ei ole yhteydessä internetiin"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Näytä vaihtoehdot napauttamalla."</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiiliverkko ei ole yhteydessä internetiin"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Verkko ei ole yhteydessä internetiin"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Ei pääsyä yksityiselle DNS-palvelimelle"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> toimii rajoitetulla yhteydellä"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Yhdistä napauttamalla"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> otettiin käyttöön"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="NEW_NETWORK">%1$s</xliff:g> otetaan käyttöön, kun <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ei voi muodostaa yhteyttä internetiin. Veloitukset ovat mahdollisia."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> poistettiin käytöstä ja <xliff:g id="NEW_NETWORK">%2$s</xliff:g> otettiin käyttöön."</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"tuntematon verkon tyyppi"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobiilidata"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..02ef50b
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Connectez-vous au réseau Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Connectez-vous au réseau"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Le réseau <xliff:g id="NETWORK_SSID">%1$s</xliff:g> n\'offre aucun accès à Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Touchez pour afficher les options"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Le réseau cellulaire n\'offre aucun accès à Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Le réseau n\'offre aucun accès à Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Impossible d\'accéder au serveur DNS privé"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Le réseau <xliff:g id="NETWORK_SSID">%1$s</xliff:g> offre une connectivité limitée"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Touchez pour vous connecter quand même"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Passé au réseau <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"L\'appareil utilise <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quand <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> n\'a pas d\'accès à Internet. Des frais peuvent s\'appliquer."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Passé du réseau <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> au <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"un type de réseau inconnu"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"données cellulaires"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"RPV"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr/strings.xml
new file mode 100644
index 0000000..08c9d81
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Connectez-vous au réseau Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Se connecter au réseau"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Aucune connexion à Internet pour <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Appuyez ici pour afficher des options."</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Le réseau mobile ne dispose d\'aucun accès à Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Le réseau ne dispose d\'aucun accès à Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Impossible d\'accéder au serveur DNS privé"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"La connectivité de <xliff:g id="NETWORK_SSID">%1$s</xliff:g> est limitée"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Appuyer pour se connecter quand même"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Nouveau réseau : <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"L\'appareil utilise <xliff:g id="NEW_NETWORK">%1$s</xliff:g> lorsque <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> n\'a pas de connexion Internet. Des frais peuvent s\'appliquer."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Ancien réseau : <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>. Nouveau réseau : <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"type de réseau inconnu"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"données mobiles"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-gl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gl/strings.xml
new file mode 100644
index 0000000..9f98055
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gl/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Inicia sesión na rede wifi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Inicia sesión na rede"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> non ten acceso a Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toca para ver opcións."</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"A rede de telefonía móbil non ten acceso a Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"A rede non ten acceso a Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Non se puido acceder ao servidor DNS privado"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"A conectividade de <xliff:g id="NETWORK_SSID">%1$s</xliff:g> é limitada"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toca para conectarte de todas formas"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Cambiouse a: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"O dispositivo utiliza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> cando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> non ten acceso a Internet. Pódense aplicar cargos."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Cambiouse de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"un tipo de rede descoñecido"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"datos móbiles"</item>
+ <item msgid="5520925862115353992">"wifi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-gu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gu/strings.xml
new file mode 100644
index 0000000..4ae5a2c
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gu/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"નેટવર્ક પર સાઇન ઇન કરો"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"વિકલ્પો માટે ટૅપ કરો"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"મોબાઇલ નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ખાનગી DNS સર્વર ઍક્સેસ કરી શકાતા નથી"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> મર્યાદિત કનેક્ટિવિટી ધરાવે છે"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"છતાં કનેક્ટ કરવા માટે ટૅપ કરો"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> પર સ્વિચ કર્યું"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"જ્યારે <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ <xliff:g id="NEW_NETWORK">%1$s</xliff:g>નો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> પરથી <xliff:g id="NEW_NETWORK">%2$s</xliff:g> પર સ્વિચ કર્યું"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"અજાણ્યો નેટવર્ક પ્રકાર"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"મોબાઇલ ડેટા"</item>
+ <item msgid="5520925862115353992">"વાઇ-ફાઇ"</item>
+ <item msgid="1055487873974272842">"બ્લૂટૂથ"</item>
+ <item msgid="1616528372438698248">"ઇથરનેટ"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hi/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hi/strings.xml
new file mode 100644
index 0000000..eff1b60
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hi/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"वाई-फ़ाई नेटवर्क में साइन इन करें"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"नेटवर्क में साइन इन करें"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> का इंटरनेट नहीं चल रहा है"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"विकल्पों के लिए टैप करें"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"मोबाइल नेटवर्क पर इंटरनेट ऐक्सेस नहीं है"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"इस नेटवर्क पर इंटरनेट ऐक्सेस नहीं है"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"निजी डीएनएस सर्वर को ऐक्सेस नहीं किया जा सकता"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> की कनेक्टिविटी सीमित है"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"फिर भी कनेक्ट करने के लिए टैप करें"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> पर ले जाया गया"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> में इंटरनेट की सुविधा नहीं होने पर डिवाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> का इस्तेमाल करता है. इसके लिए शुल्क लिया जा सकता है."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> से <xliff:g id="NEW_NETWORK">%2$s</xliff:g> पर ले जाया गया"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"अज्ञात नेटवर्क प्रकार"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"मोबाइल डेटा"</item>
+ <item msgid="5520925862115353992">"वाई-फ़ाई"</item>
+ <item msgid="1055487873974272842">"ब्लूटूथ"</item>
+ <item msgid="1616528372438698248">"ईथरनेट"</item>
+ <item msgid="9177085807664964627">"वीपीएन"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hr/strings.xml
new file mode 100644
index 0000000..52bfb93
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hr/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Prijava na Wi-Fi mrežu"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Prijava na mrežu"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nema pristup internetu"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Dodirnite za opcije"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilna mreža nema pristup internetu"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Mreža nema pristup internetu"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Nije moguće pristupiti privatnom DNS poslužitelju"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ima ograničenu povezivost"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Dodirnite da biste se ipak povezali"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Prelazak na drugu mrežu: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Kada <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu, na uređaju se upotrebljava <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Moguća je naplata naknade."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Mreža je promijenjena: <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> > <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nepoznata vrsta mreže"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobilni podaci"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hu/strings.xml
new file mode 100644
index 0000000..2ff59b5
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hu/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Bejelentkezés Wi-Fi hálózatba"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Bejelentkezés a hálózatba"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"A(z) <xliff:g id="NETWORK_SSID">%1$s</xliff:g> hálózaton nincs internet-hozzáférés"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Koppintson a beállítások megjelenítéséhez"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"A mobilhálózaton nincs internet-hozzáférés"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"A hálózaton nincs internet-hozzáférés"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"A privát DNS-kiszolgálóhoz nem lehet hozzáférni"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"A(z) <xliff:g id="NETWORK_SSID">%1$s</xliff:g> hálózat korlátozott kapcsolatot biztosít"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Koppintson, ha mindenképpen csatlakozni szeretne"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Átváltva erre: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="NEW_NETWORK">%1$s</xliff:g> használata, ha nincs internet-hozzáférés <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>-kapcsolaton keresztül. A szolgáltató díjat számíthat fel."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Átváltva <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>-hálózatról erre: <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ismeretlen hálózati típus"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobiladatok"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hy/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hy/strings.xml
new file mode 100644
index 0000000..b35d31c
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hy/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Մուտք գործեք Wi-Fi ցանց"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Մուտք գործեք ցանց"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ցանցը չունի մուտք ինտերնետին"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Հպեք՝ ընտրանքները տեսնելու համար"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Բջջային ցանցը չի ապահովում ինտերնետ կապ"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Ցանցը միացված չէ ինտերնետին"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Մասնավոր DNS սերվերն անհասանելի է"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ցանցի կապը սահմանափակ է"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Հպեք՝ միանալու համար"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Անցել է <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ցանցի"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Երբ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ցանցում ինտերնետ կապ չի լինում, սարքն անցնում է <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ցանցի: Նման դեպքում կարող են վճարներ գանձվել:"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ցանցից անցել է <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ցանցի"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ցանցի անհայտ տեսակ"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"բջջային ինտերնետ"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-in/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-in/strings.xml
new file mode 100644
index 0000000..27d7d89
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-in/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Login ke jaringan Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Login ke jaringan"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tidak memiliki akses internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Ketuk untuk melihat opsi"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Jaringan seluler tidak memiliki akses internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Jaringan tidak memiliki akses internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Server DNS pribadi tidak dapat diakses"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> memiliki konektivitas terbatas"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ketuk untuk tetap menyambungkan"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Dialihkan ke <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Perangkat menggunakan <xliff:g id="NEW_NETWORK">%1$s</xliff:g> jika <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tidak memiliki akses internet. Tarif mungkin berlaku."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Dialihkan dari <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ke <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"jenis jaringan yang tidak dikenal"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"data seluler"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-is/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-is/strings.xml
new file mode 100644
index 0000000..97f42dc
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-is/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Skrá inn á Wi-Fi net"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Skrá inn á net"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> er ekki með internetaðgang"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Ýttu til að sjá valkosti"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Farsímakerfið er ekki tengt við internetið"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Netkerfið er ekki tengt við internetið"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Ekki næst í DNS-einkaþjón"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Tengigeta <xliff:g id="NETWORK_SSID">%1$s</xliff:g> er takmörkuð"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ýttu til að tengjast samt"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Skipt yfir á <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Tækið notar <xliff:g id="NEW_NETWORK">%1$s</xliff:g> þegar <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> er ekki með internetaðgang. Gjöld kunna að eiga við."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Skipt úr <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> yfir í <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"óþekkt tegund netkerfis"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"farsímagögn"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-it/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-it/strings.xml
new file mode 100644
index 0000000..7836101
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-it/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Accedi a rete Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Accedi alla rete"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> non ha accesso a Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tocca per le opzioni"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"La rete mobile non ha accesso a Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"La rete non ha accesso a Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Non è possibile accedere al server DNS privato"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ha una connettività limitata"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tocca per connettere comunque"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Passato a <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Il dispositivo utilizza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> non ha accesso a Internet. Potrebbero essere applicati costi."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Passato da <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"tipo di rete sconosciuto"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"dati mobili"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-iw/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-iw/strings.xml
new file mode 100644
index 0000000..f322b99
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-iw/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"היכנס לרשת Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"היכנס לרשת"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"ל-<xliff:g id="NETWORK_SSID">%1$s</xliff:g> אין גישה לאינטרנט"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"הקש לקבלת אפשרויות"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"לרשת הסלולרית אין גישה לאינטרנט"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"לרשת אין גישה לאינטרנט"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"לא ניתן לגשת לשרת DNS הפרטי"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"הקישוריות של <xliff:g id="NETWORK_SSID">%1$s</xliff:g> מוגבלת"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"כדי להתחבר למרות זאת יש להקיש"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"מעבר אל <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"המכשיר משתמש ברשת <xliff:g id="NEW_NETWORK">%1$s</xliff:g> כשלרשת <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> אין גישה לאינטרנט. עשויים לחול חיובים."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"עבר מרשת <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> לרשת <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"סוג רשת לא מזוהה"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"חבילת גלישה"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ja/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ja/strings.xml
new file mode 100644
index 0000000..1aa3216
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ja/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fiネットワークにログイン"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ネットワークにログインしてください"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> はインターネットにアクセスできません"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"タップしてその他のオプションを表示"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"モバイル ネットワークがインターネットに接続されていません"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"ネットワークがインターネットに接続されていません"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"プライベート DNS サーバーにアクセスできません"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> の接続が制限されています"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"接続するにはタップしてください"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"「<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>」に切り替えました"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"デバイスで「<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>」によるインターネット接続ができない場合に「<xliff:g id="NEW_NETWORK">%1$s</xliff:g>」を使用します。通信料が発生することがあります。"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"「<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>」から「<xliff:g id="NEW_NETWORK">%2$s</xliff:g>」に切り替えました"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"不明なネットワーク タイプ"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"モバイルデータ"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"イーサネット"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ka/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ka/strings.xml
new file mode 100644
index 0000000..61d21b5
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ka/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi ქსელთან დაკავშირება"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ქსელში შესვლა"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-ს არ აქვს ინტერნეტზე წვდომა"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"შეეხეთ ვარიანტების სანახავად"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"მობილურ ქსელს არ აქვს ინტერნეტზე წვდომა"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"ქსელს არ აქვს ინტერნეტზე წვდომა"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"პირად DNS სერვერზე წვდომა შეუძლებელია"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-ის კავშირები შეზღუდულია"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"შეეხეთ, თუ მაინც გსურთ დაკავშირება"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"ახლა გამოიყენება <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"თუ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ინტერნეტთან კავშირს დაკარგავს, მოწყობილობის მიერ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> იქნება გამოყენებული, რამაც შეიძლება დამატებითი ხარჯები გამოიწვიოს."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"ახლა გამოიყენება <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> (გამოიყენებოდა <xliff:g id="NEW_NETWORK">%2$s</xliff:g>)"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"უცნობი ტიპის ქსელი"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"მობილური ინტერნეტი"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-kk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kk/strings.xml
new file mode 100644
index 0000000..969aaef
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kk/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi желісіне кіру"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Желіге кіру"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> желісінің интернетті пайдалану мүмкіндігі шектеулі."</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Опциялар үшін түртіңіз"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Мобильдік желі интернетке қосылмаған."</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Желі интернетке қосылмаған."</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Жеке DNS серверіне кіру мүмкін емес."</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> желісінің қосылу мүмкіндігі шектеулі."</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Бәрібір жалғау үшін түртіңіз."</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> желісіне ауысты"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Құрылғы <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> желісінде интернетпен байланыс жоғалған жағдайда <xliff:g id="NEW_NETWORK">%1$s</xliff:g> желісін пайдаланады. Деректер ақысы алынуы мүмкін."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> желісінен <xliff:g id="NEW_NETWORK">%2$s</xliff:g> желісіне ауысты"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"желі түрі белгісіз"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"мобильдік деректер"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-km/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-km/strings.xml
new file mode 100644
index 0000000..da3c337
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-km/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ចូលបណ្ដាញវ៉ាយហ្វាយ"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ចូលទៅបណ្តាញ"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> មិនមានការតភ្ជាប់អ៊ីនធឺណិតទេ"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ប៉ះសម្រាប់ជម្រើស"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"បណ្ដាញទូរសព្ទចល័តមិនមានការតភ្ជាប់អ៊ីនធឺណិតទេ"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"បណ្ដាញមិនមានការតភ្ជាប់អ៊ីនធឺណិតទេ"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"មិនអាចចូលប្រើម៉ាស៊ីនមេ DNS ឯកជនបានទេ"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> មានការតភ្ជាប់មានកម្រិត"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"មិនអីទេ ចុចភ្ជាប់ចុះ"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"បានប្តូរទៅ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"ឧបករណ៍ប្រើ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> នៅពេលដែល <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> មិនមានការតភ្ជាប់អ៊ីនធឺណិត។ អាចគិតថ្លៃលើការប្រើប្រាស់ទិន្នន័យ។"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"បានប្តូរពី <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ទៅ <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ប្រភេទបណ្តាញមិនស្គាល់"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"ទិន្នន័យទូរសព្ទចល័ត"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"ប៊្លូធូស"</item>
+ <item msgid="1616528372438698248">"អ៊ីសឺរណិត"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-kn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kn/strings.xml
new file mode 100644
index 0000000..3b5e047
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kn/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ನೆಟ್ವರ್ಕ್ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಲ್ಲ"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"ನೆಟ್ವರ್ಕ್ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ಸೀಮಿತ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿದೆ"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ಹೇಗಾದರೂ ಸಂಪರ್ಕಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ ಹೊಂದಿಲ್ಲದಿರುವಾಗ, ಸಾಧನವು <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ಬಳಸುತ್ತದೆ. ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ರಿಂದ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ಅಪರಿಚಿತ ನೆಟ್ವರ್ಕ್ ಪ್ರಕಾರ"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"ಮೊಬೈಲ್ ಡೇಟಾ"</item>
+ <item msgid="5520925862115353992">"ವೈ-ಫೈ"</item>
+ <item msgid="1055487873974272842">"ಬ್ಲೂಟೂತ್"</item>
+ <item msgid="1616528372438698248">"ಇಥರ್ನೆಟ್"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ko/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ko/strings.xml
new file mode 100644
index 0000000..874bd75
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ko/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi 네트워크에 로그인"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"네트워크에 로그인"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>이(가) 인터넷에 액세스할 수 없습니다."</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"탭하여 옵션 보기"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"모바일 네트워크에 인터넷이 연결되어 있지 않습니다."</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"네트워크에 인터넷이 연결되어 있지 않습니다."</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"비공개 DNS 서버에 액세스할 수 없습니다."</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>에서 연결을 제한했습니다."</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"계속 연결하려면 탭하세요."</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>(으)로 전환"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>(으)로 인터넷에 연결할 수 없는 경우 기기에서 <xliff:g id="NEW_NETWORK">%1$s</xliff:g>이(가) 사용됩니다. 요금이 부과될 수 있습니다."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>에서 <xliff:g id="NEW_NETWORK">%2$s</xliff:g>(으)로 전환"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"알 수 없는 네트워크 유형"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"모바일 데이터"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"블루투스"</item>
+ <item msgid="1616528372438698248">"이더넷"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ky/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ky/strings.xml
new file mode 100644
index 0000000..1ace4dc
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ky/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi түйүнүнө кирүү"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Тармакка кирүү"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> Интернетке туташуусу жок"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Параметрлерди ачуу үчүн таптап коюңуз"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Мобилдик Интернет жок"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Тармактын Интернет жок"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Жеке DNS сервери жеткиликсиз"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> байланышы чектелген"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Баары бир туташуу үчүн таптаңыз"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> тармагына которуштурулду"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> тармагы Интернетке туташпай турганда, түзмөгүңүз <xliff:g id="NEW_NETWORK">%1$s</xliff:g> тармагын колдонот. Акы алынышы мүмкүн."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> дегенден <xliff:g id="NEW_NETWORK">%2$s</xliff:g> тармагына которуштурулду"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"белгисиз тармак түрү"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"мобилдик трафик"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lo/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lo/strings.xml
new file mode 100644
index 0000000..3db497e
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lo/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ລົງຊື່ເຂົ້າເຄືອຂ່າຍ"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ແຕະເພື່ອເບິ່ງຕົວເລືອກ"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"ເຄືອຂ່າຍມືຖືບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"ເຄືອຂ່າຍບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ບໍ່ສາມາດເຂົ້າເຖິງເຊີບເວີ DNS ສ່ວນຕົວໄດ້"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ມີການເຊື່ອມຕໍ່ທີ່ຈຳກັດ"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ແຕະເພື່ອຢືນຢັນການເຊື່ອມຕໍ່"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"ສະຫຼັບໄປໃຊ້ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ແລ້ວ"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"ອຸປະກອນຈະໃຊ້ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ເມື່ອ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ. ອາດມີການຮຽກເກັບຄ່າບໍລິການ."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"ສະຫຼັບຈາກ <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ໄປໃຊ້ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ແລ້ວ"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ບໍ່ຮູ້ຈັກປະເພດເຄືອຂ່າຍ"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"ອິນເຕີເນັດມືຖື"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"ອີເທີເນັດ"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lt/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lt/strings.xml
new file mode 100644
index 0000000..c639c1f
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lt/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Prisijungti prie „Wi-Fi“ tinklo"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Prisijungti prie tinklo"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"„<xliff:g id="NETWORK_SSID">%1$s</xliff:g>“ negali pasiekti interneto"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Palieskite, kad būtų rodomos parinktys."</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiliojo ryšio tinkle nėra prieigos prie interneto"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Tinkle nėra prieigos prie interneto"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Privataus DNS serverio negalima pasiekti"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"„<xliff:g id="NETWORK_SSID">%1$s</xliff:g>“ ryšys apribotas"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Palieskite, jei vis tiek norite prisijungti"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Perjungta į tinklą <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Įrenginyje naudojamas kitas tinklas (<xliff:g id="NEW_NETWORK">%1$s</xliff:g>), kai dabartiniame tinkle (<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>) nėra interneto ryšio. Gali būti taikomi mokesčiai."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Perjungta iš tinklo <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> į tinklą <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nežinomas tinklo tipas"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobiliojo ryšio duomenys"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Eternetas"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lv/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lv/strings.xml
new file mode 100644
index 0000000..5774603
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lv/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Pierakstieties Wi-Fi tīklā"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Pierakstīšanās tīklā"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Tīklā <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nav piekļuves internetam"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Pieskarieties, lai skatītu iespējas."</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilajā tīklā nav piekļuves internetam."</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Tīklā nav piekļuves internetam."</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Nevar piekļūt privātam DNS serverim."</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Tīklā <xliff:g id="NETWORK_SSID">%1$s</xliff:g> ir ierobežota savienojamība"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Lai tik un tā izveidotu savienojumu, pieskarieties"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Pārslēdzās uz tīklu <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Kad vienā tīklā (<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>) nav piekļuves internetam, ierīcē tiek izmantots cits tīkls (<xliff:g id="NEW_NETWORK">%1$s</xliff:g>). Var tikt piemērota maksa."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Pārslēdzās no tīkla <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> uz tīklu <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nezināms tīkla veids"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobilie dati"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mk/strings.xml
new file mode 100644
index 0000000..053c7cf
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mk/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Најавете се на мрежа на Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Најавете се на мрежа"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> нема интернет-пристап"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Допрете за опции"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Мобилната мрежа нема интернет-пристап"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Мрежата нема интернет-пристап"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Не може да се пристапи до приватниот DNS-сервер"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> има ограничена поврзливост"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Допрете за да се поврзете и покрај тоа"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Префрлено на <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Уредот користи <xliff:g id="NEW_NETWORK">%1$s</xliff:g> кога <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> нема пристап до интернет. Може да се наплатат трошоци."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Префрлено од <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> на <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"непознат тип мрежа"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"мобилен интернет"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Етернет"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ml/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ml/strings.xml
new file mode 100644
index 0000000..3e80cf1
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ml/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"വൈഫൈ നെറ്റ്വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"നെറ്റ്വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> എന്നതിന് ഇന്റർനെറ്റ് ആക്സസ് ഇല്ല"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"മൊബെെൽ നെറ്റ്വർക്കിന് ഇന്റർനെറ്റ് ആക്സസ് ഇല്ല"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"നെറ്റ്വർക്കിന് ഇന്റർനെറ്റ് ആക്സസ് ഇല്ല"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"സ്വകാര്യ DNS സെർവർ ആക്സസ് ചെയ്യാനാവില്ല"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> എന്നതിന് പരിമിതമായ കണക്റ്റിവിറ്റി ഉണ്ട്"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ഏതുവിധേനയും കണക്റ്റ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> എന്നതിലേക്ക് മാറി"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>-ന് ഇന്റർനെറ്റ് ആക്സസ് ഇല്ലാത്തപ്പോൾ ഉപകരണം <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ഉപയോഗിക്കുന്നു. നിരക്കുകൾ ബാധകമായേക്കാം."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> നെറ്റ്വർക്കിൽ നിന്ന് <xliff:g id="NEW_NETWORK">%2$s</xliff:g> നെറ്റ്വർക്കിലേക്ക് മാറി"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"തിരിച്ചറിയാനാകാത്ത ഒരു നെറ്റ്വർക്ക് തരം"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"മൊബൈൽ ഡാറ്റ"</item>
+ <item msgid="5520925862115353992">"വൈഫൈ"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"ഇതര്നെറ്റ്"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mn/strings.xml
new file mode 100644
index 0000000..214fc0c
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mn/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi сүлжээнд нэвтэрнэ үү"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Сүлжээнд нэвтэрнэ үү"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>-д интернэтийн хандалт алга"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Сонголт хийхийн тулд товшино уу"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Мобайл сүлжээнд интернэт хандалт байхгүй байна"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Сүлжээнд интернэт хандалт байхгүй байна"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Хувийн DNS серверт хандах боломжгүй байна"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> зарим үйлчилгээнд хандах боломжгүй байна"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ямар ч тохиолдолд холбогдохын тулд товших"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> руу шилжүүлсэн"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> интернет холболтгүй үед төхөөрөмж <xliff:g id="NEW_NETWORK">%1$s</xliff:g>-г ашигладаг. Төлбөр гарч болзошгүй."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>-с <xliff:g id="NEW_NETWORK">%2$s</xliff:g> руу шилжүүлсэн"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"сүлжээний тодорхойгүй төрөл"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"мобайл дата"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Этернэт"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mr/strings.xml
new file mode 100644
index 0000000..c4b1998
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mr/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"वाय-फाय नेटवर्कमध्ये साइन इन करा"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"नेटवर्कवर साइन इन करा"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ला इंटरनेट अॅक्सेस नाही"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"पर्यायांसाठी टॅप करा"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"मोबाइल नेटवर्कला इंटरनेट ॲक्सेस नाही"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"नेटवर्कला इंटरनेट ॲक्सेस नाही"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"खाजगी DNS सर्व्हर ॲक्सेस करू शकत नाही"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ला मर्यादित कनेक्टिव्हिटी आहे"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"तरीही कनेक्ट करण्यासाठी टॅप करा"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> वर स्विच केले"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> कडे इंटरनेटचा अॅक्सेस नसताना डिव्हाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> वापरते. शुल्क लागू शकते."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> वरून <xliff:g id="NEW_NETWORK">%2$s</xliff:g> वर स्विच केले"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"अज्ञात नेटवर्क प्रकार"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"मोबाइल डेटा"</item>
+ <item msgid="5520925862115353992">"वाय-फाय"</item>
+ <item msgid="1055487873974272842">"ब्लूटूथ"</item>
+ <item msgid="1616528372438698248">"इथरनेट"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ms/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ms/strings.xml
new file mode 100644
index 0000000..529d0bd
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ms/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Log masuk ke rangkaian Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Log masuk ke rangkaian"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tiada akses Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Ketik untuk mendapatkan pilihan"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Rangkaian mudah alih tiada akses Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Rangkaian tiada akses Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Pelayan DNS peribadi tidak boleh diakses"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> mempunyai kesambungan terhad"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ketik untuk menyambung juga"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Beralih kepada <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Peranti menggunakan <xliff:g id="NEW_NETWORK">%1$s</xliff:g> apabila <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tiada akses Internet. Bayaran mungkin dikenakan."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Beralih daripada <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> kepada <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"jenis rangkaian tidak diketahui"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"data mudah alih"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-my/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-my/strings.xml
new file mode 100644
index 0000000..50590fa
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-my/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"အခြားရွေးချယ်စရာများကိုကြည့်ရန် တို့ပါ"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"မိုဘိုင်းကွန်ရက်တွင် အင်တာနက်ချိတ်ဆက်မှု မရှိပါ"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"ကွန်ရက်တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"သီးသန့် ဒီအန်အက်စ် (DNS) ဆာဗာကို သုံး၍မရပါ။"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> တွင် ချိတ်ဆက်မှုကို ကန့်သတ်ထားသည်"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"မည်သို့ပင်ဖြစ်စေ ချိတ်ဆက်ရန် တို့ပါ"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> သို့ ပြောင်းလိုက်ပြီ"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ဖြင့် အင်တာနက် အသုံးမပြုနိုင်သည့်အချိန်တွင် စက်ပစ္စည်းသည် <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ကို သုံးပါသည်။ ဒေတာသုံးစွဲခ ကျသင့်နိုင်ပါသည်။"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> မှ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> သို့ ပြောင်းလိုက်ပြီ"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"အမည်မသိကွန်ရက်အမျိုးအစား"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"မိုဘိုင်းဒေတာ"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"ဘလူးတုသ်"</item>
+ <item msgid="1616528372438698248">"အီသာနက်"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-nb/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nb/strings.xml
new file mode 100644
index 0000000..b89d198
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nb/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Logg på Wi-Fi-nettverket"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Logg på nettverk"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har ingen internettilkobling"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Trykk for å få alternativer"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilnettverket har ingen internettilgang"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Nettverket har ingen internettilgang"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Den private DNS-tjeneren kan ikke nås"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har begrenset tilkobling"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Trykk for å koble til likevel"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Byttet til <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Enheten bruker <xliff:g id="NEW_NETWORK">%1$s</xliff:g> når <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ikke har Internett-tilgang. Avgifter kan påløpe."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Byttet fra <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> til <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"en ukjent nettverkstype"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobildata"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ne/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ne/strings.xml
new file mode 100644
index 0000000..bdcfa3b
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ne/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"सञ्जालमा साइन इन गर्नुहोस्"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> को इन्टरनेटमाथि पहुँच छैन"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"विकल्पहरूका लागि ट्याप गर्नुहोस्"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"मोबाइल नेटवर्कको इन्टरनेटमाथि पहुँच छैन"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"नेटवर्कको इन्टरनेटमाथि पहुँच छैन"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"निजी DNS सर्भरमाथि पहुँच प्राप्त गर्न सकिँदैन"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> को जडान सीमित छ"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"जसरी भए पनि जडान गर्न ट्याप गर्नुहोस्"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> मा बदल्नुहोस्"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> मार्फत इन्टरनेटमाथि पहुँच राख्न नसकेको अवस्थामा यन्त्रले <xliff:g id="NEW_NETWORK">%1$s</xliff:g> प्रयोग गर्दछ। शुल्क लाग्न सक्छ।"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> बाट <xliff:g id="NEW_NETWORK">%2$s</xliff:g> मा परिवर्तन गरियो"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"नेटवर्कको कुनै अज्ञात प्रकार"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"मोबाइल डेटा"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"ब्लुटुथ"</item>
+ <item msgid="1616528372438698248">"इथरनेट"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-nl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nl/strings.xml
new file mode 100644
index 0000000..8ecff6e
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nl/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Inloggen bij wifi-netwerk"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Inloggen bij netwerk"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> heeft geen internettoegang"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tik voor opties"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobiel netwerk heeft geen internettoegang"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Netwerk heeft geen internettoegang"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Geen toegang tot privé-DNS-server"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> heeft beperkte connectiviteit"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tik om toch verbinding te maken"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Overgeschakeld naar <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Apparaat gebruikt <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wanneer <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> geen internetverbinding heeft. Er kunnen kosten in rekening worden gebracht."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Overgeschakeld van <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> naar <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"een onbekend netwerktype"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobiele data"</item>
+ <item msgid="5520925862115353992">"Wifi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-or/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-or/strings.xml
new file mode 100644
index 0000000..6ec1f9d
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-or/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ୱାଇ-ଫାଇ ନେଟୱର୍କରେ ସାଇନ୍-ଇନ୍ କରନ୍ତୁ"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ନେଟ୍ୱର୍କରେ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ର ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ବିକଳ୍ପ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"ମୋବାଇଲ୍ ନେଟ୍ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"ନେଟ୍ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ର ସୀମିତ ସଂଯୋଗ ଅଛି"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ତଥାପି ଯୋଗାଯୋଗ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>କୁ ବଦଳାଗଲା"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>ର ଇଣ୍ଟରନେଟ୍ ଆକ୍ସେସ୍ ନଥିବାବେଳେ ଡିଭାଇସ୍ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ବ୍ୟବହାର କରିଥାଏ। ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ।"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ରୁ <xliff:g id="NEW_NETWORK">%2$s</xliff:g>କୁ ବଦଳାଗଲା"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ଏକ ଅଜଣା ନେଟ୍ୱର୍କ ପ୍ରକାର"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"ମୋବାଇଲ୍ ଡାଟା"</item>
+ <item msgid="5520925862115353992">"ୱାଇ-ଫାଇ"</item>
+ <item msgid="1055487873974272842">"ବ୍ଲୁଟୁଥ"</item>
+ <item msgid="1616528372438698248">"ଇଥରନେଟ୍"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pa/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pa/strings.xml
new file mode 100644
index 0000000..e948193
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pa/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ਨਿੱਜੀ ਡੋਮੇਨ ਨਾਮ ਪ੍ਰਣਾਲੀ (DNS) ਸਰਵਰ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ਕੋਲ ਸੀਮਤ ਕਨੈਕਟੀਵਿਟੀ ਹੈ"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ਫਿਰ ਵੀ ਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"ਬਦਲਕੇ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ਲਿਆਂਦਾ ਗਿਆ"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ਤੋਂ ਬਦਲਕੇ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> \'ਤੇ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ਇੱਕ ਅਗਿਆਤ ਨੈੱਟਵਰਕ ਕਿਸਮ"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"ਮੋਬਾਈਲ ਡਾਟਾ"</item>
+ <item msgid="5520925862115353992">"ਵਾਈ-ਫਾਈ"</item>
+ <item msgid="1055487873974272842">"ਬਲੂਟੁੱਥ"</item>
+ <item msgid="1616528372438698248">"ਈਥਰਨੈੱਟ"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pl/strings.xml
new file mode 100644
index 0000000..038328f
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pl/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Zaloguj się w sieci Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Zaloguj się do sieci"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nie ma dostępu do internetu"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Kliknij, by wyświetlić opcje"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Sieć komórkowa nie ma dostępu do internetu"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Sieć nie ma dostępu do internetu"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Brak dostępu do prywatnego serwera DNS"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ma ograniczoną łączność"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Kliknij, by mimo to nawiązać połączenie"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Zmieniono na połączenie typu <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Urządzenie korzysta z połączenia typu <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, gdy <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nie dostępu do internetu. Mogą zostać naliczone opłaty."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Przełączono z połączenia typu <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na <xliff:g id="NEW_NETWORK">%2$s</xliff:g>."</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nieznany typ sieci"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobilna transmisja danych"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..fe37405
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Fazer login na rede Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Fazer login na rede"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> não tem acesso à Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toque para ver opções"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"A rede móvel não tem acesso à Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"A rede não tem acesso à Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Não é possível acessar o servidor DNS privado"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tem conectividade limitada"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toque para conectar mesmo assim"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Alternado para <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"O dispositivo usa <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> não tem acesso à Internet. Esse serviço pode ser cobrado."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Alternado de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> para <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"um tipo de rede desconhecido"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"dados móveis"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..69060f7
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Iniciar sessão na rede Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Início de sessão na rede"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> não tem acesso à Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toque para obter mais opções"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"A rede móvel não tem acesso à Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"A rede não tem acesso à Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Não é possível aceder ao servidor DNS."</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tem conetividade limitada."</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toque para ligar mesmo assim."</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Mudou para <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"O dispositivo utiliza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> não tem acesso à Internet. Podem aplicar-se custos."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Mudou de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> para <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"um tipo de rede desconhecido"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"dados móveis"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt/strings.xml
new file mode 100644
index 0000000..fe37405
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Fazer login na rede Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Fazer login na rede"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> não tem acesso à Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Toque para ver opções"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"A rede móvel não tem acesso à Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"A rede não tem acesso à Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Não é possível acessar o servidor DNS privado"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> tem conectividade limitada"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Toque para conectar mesmo assim"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Alternado para <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"O dispositivo usa <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> não tem acesso à Internet. Esse serviço pode ser cobrado."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Alternado de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> para <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"um tipo de rede desconhecido"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"dados móveis"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ro/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ro/strings.xml
new file mode 100644
index 0000000..227b7be
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ro/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Conectați-vă la rețeaua Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Conectați-vă la rețea"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nu are acces la internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Atingeți pentru opțiuni"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Rețeaua mobilă nu are acces la internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Rețeaua nu are acces la internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Serverul DNS privat nu poate fi accesat"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> are conectivitate limitată"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Atingeți pentru a vă conecta oricum"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"S-a comutat la <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Dispozitivul folosește <xliff:g id="NEW_NETWORK">%1$s</xliff:g> când <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nu are acces la internet. Se pot aplica taxe."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"S-a comutat de la <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> la <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"un tip de rețea necunoscut"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"date mobile"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ru/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ru/strings.xml
new file mode 100644
index 0000000..18acf81
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ru/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Подключение к Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Регистрация в сети"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Сеть \"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>\" не подключена к Интернету"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Нажмите, чтобы показать варианты."</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Мобильная сеть не подключена к Интернету"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Сеть не подключена к Интернету"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Доступа к частному DNS-серверу нет."</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Подключение к сети \"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>\" ограничено"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Нажмите, чтобы подключиться"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Новое подключение: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Устройство использует <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, если подключение к сети <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> недоступно. Может взиматься плата за передачу данных."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Устройство отключено от сети <xliff:g id="NEW_NETWORK">%2$s</xliff:g> и теперь использует <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"неизвестный тип сети"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"мобильный Интернет"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-si/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-si/strings.xml
new file mode 100644
index 0000000..6307c2b
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-si/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi ජාලයට පුරනය වන්න"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ජාලයට පුරනය වන්න"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> හට අන්තර්ජාල ප්රවේශය නැත"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"විකල්ප සඳහා තට්ටු කරන්න"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"ජංගම ජාලවලට අන්තර්ජාල ප්රවේශය නැත"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"ජාලයට අන්තර්ජාල ප්රවේශය නැත"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"පුද්ගලික DNS සේවාදායකයට ප්රවේශ වීමට නොහැකිය"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> හට සීමිත සබැඳුම් හැකියාවක් ඇත"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"කෙසේ වෙතත් ඉදිරියට යාමට තට්ටු කරන්න"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> වෙත මාරු විය"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"උපාංගය <xliff:g id="NEW_NETWORK">%1$s</xliff:g> <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> සඳහා අන්තර්ජාල ප්රවේශය නැති විට භාවිත කරයි. ගාස්තු අදාළ විය හැකිය."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> සිට <xliff:g id="NEW_NETWORK">%2$s</xliff:g> වෙත මාරු විය"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"නොදන්නා ජාල වර්ගයකි"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"ජංගම දත්ත"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"බ්ලූටූත්"</item>
+ <item msgid="1616528372438698248">"ඊතර්නෙට්"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sk/strings.xml
new file mode 100644
index 0000000..e894fef
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sk/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Prihlásiť sa do siete Wi‑Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Prihlásenie do siete"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nemá prístup k internetu"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Klepnutím získate možnosti"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilná sieť nemá prístup k internetu"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Sieť nemá prístup k internetu"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"K súkromnému serveru DNS sa nepodarilo získať prístup"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> má obmedzené pripojenie"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Ak sa chcete aj napriek tomu pripojiť, klepnite"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Prepnuté na sieť: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Keď <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nemá prístup k internetu, zariadenie používa <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Môžu sa účtovať poplatky."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Prepnuté zo siete <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na sieť <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"neznámy typ siete"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobilné dáta"</item>
+ <item msgid="5520925862115353992">"Wi‑Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sl/strings.xml
new file mode 100644
index 0000000..954b324
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sl/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Prijavite se v omrežje Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Prijava v omrežje"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Omrežje <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nima dostopa do interneta"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Dotaknite se za možnosti"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilno omrežje nima dostopa do interneta"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Omrežje nima dostopa do interneta"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Do zasebnega strežnika DNS ni mogoče dostopati"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Povezljivost omrežja <xliff:g id="NETWORK_SSID">%1$s</xliff:g> je omejena"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Dotaknite se, da kljub temu vzpostavite povezavo"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Preklopljeno na omrežje vrste <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Naprava uporabi omrežje vrste <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, ko omrežje vrste <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nima dostopa do interneta. Prenos podatkov se lahko zaračuna."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Preklopljeno z omrežja vrste <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na omrežje vrste <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"neznana vrsta omrežja"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"prenos podatkov v mobilnem omrežju"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sq/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sq/strings.xml
new file mode 100644
index 0000000..bd5d052
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sq/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Identifikohu në rrjetin Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Identifikohu në rrjet"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nuk ka qasje në internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Trokit për opsionet"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Rrjeti celular nuk ka qasje në internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Rrjeti nuk ka qasje në internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Serveri privat DNS nuk mund të qaset"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ka lidhshmëri të kufizuar"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Trokit për t\'u lidhur gjithsesi"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Kaloi te <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Pajisja përdor <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kur <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nuk ka qasje në internet. Mund të zbatohen tarifa."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Kaloi nga <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> te <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"një lloj rrjeti i panjohur"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"të dhënat celulare"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Eternet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sr/strings.xml
new file mode 100644
index 0000000..8bedbff
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sr/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Пријављивање на WiFi мрежу"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Пријавите се на мрежу"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> нема приступ интернету"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Додирните за опције"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Мобилна мрежа нема приступ интернету"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Мрежа нема приступ интернету"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Приступ приватном DNS серверу није успео"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> има ограничену везу"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Додирните да бисте се ипак повезали"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Прешли сте на тип мреже <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Уређај користи тип мреже <xliff:g id="NEW_NETWORK">%1$s</xliff:g> када тип мреже <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> нема приступ интернету. Можда ће се наплаћивати трошкови."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Прешли сте са типа мреже <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> на тип мреже <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"непознат тип мреже"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"мобилни подаци"</item>
+ <item msgid="5520925862115353992">"WiFi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Етернет"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml
new file mode 100644
index 0000000..b3f1763
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Logga in på ett Wi-Fi-nätverk"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Logga in på nätverket"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har ingen internetanslutning"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Tryck för alternativ"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobilnätverket har ingen internetanslutning"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Nätverket har ingen internetanslutning"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Det går inte att komma åt den privata DNS-servern."</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> har begränsad anslutning"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Tryck för att ansluta ändå"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Byte av nätverk till <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="NEW_NETWORK">%1$s</xliff:g> används på enheten när det inte finns internetåtkomst via <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>. Avgifter kan tillkomma."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Byte av nätverk från <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> till <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"en okänd nätverkstyp"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobildata"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sw/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sw/strings.xml
new file mode 100644
index 0000000..9674654
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sw/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Ingia kwa mtandao wa Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Ingia katika mtandao"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> haina uwezo wa kufikia intaneti"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Gusa ili upate chaguo"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mtandao wa simu hauna uwezo wa kufikia intaneti"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Mtandao hauna uwezo wa kufikia intaneti"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Seva ya faragha ya DNS haiwezi kufikiwa"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ina muunganisho unaofikia huduma chache."</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Gusa ili uunganishe tu"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Sasa inatumia <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Kifaa hutumia <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wakati <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> haina intaneti. Huenda ukalipishwa."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Imebadilisha mtandao kutoka <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na sasa inatumia <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"aina ya mtandao isiyojulikana"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"data ya simu"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethaneti"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ta/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ta/strings.xml
new file mode 100644
index 0000000..12604cb
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ta/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"வைஃபை நெட்வொர்க்கில் உள்நுழையவும்"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"நெட்வொர்க்கில் உள்நுழையவும்"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"விருப்பங்களுக்கு, தட்டவும்"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"மொபைல் நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"தனிப்பட்ட DNS சேவையகத்தை அணுக இயலாது"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> வரம்பிற்கு உட்பட்ட இணைப்புநிலையைக் கொண்டுள்ளது"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"எப்படியேனும் இணைப்பதற்குத் தட்டவும்"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>க்கு மாற்றப்பட்டது"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> நெட்வொர்க்கில் இண்டர்நெட் அணுகல் இல்லாததால், சாதனமானது <xliff:g id="NEW_NETWORK">%1$s</xliff:g> நெட்வொர்க்கைப் பயன்படுத்துகிறது. கட்டணங்கள் விதிக்கப்படலாம்."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> இலிருந்து <xliff:g id="NEW_NETWORK">%2$s</xliff:g>க்கு மாற்றப்பட்டது"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"தெரியாத நெட்வொர்க் வகை"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"மொபைல் டேட்டா"</item>
+ <item msgid="5520925862115353992">"வைஃபை"</item>
+ <item msgid="1055487873974272842">"புளூடூத்"</item>
+ <item msgid="1616528372438698248">"ஈத்தர்நெட்"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-te/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-te/strings.xml
new file mode 100644
index 0000000..84a8640
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-te/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi నెట్వర్క్కి సైన్ ఇన్ చేయండి"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"నెట్వర్క్కి సైన్ ఇన్ చేయండి"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>కి ఇంటర్నెట్ యాక్సెస్ లేదు"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"ఎంపికల కోసం నొక్కండి"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"మొబైల్ నెట్వర్క్కు ఇంటర్నెట్ యాక్సెస్ లేదు"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"నెట్వర్క్కు ఇంటర్నెట్ యాక్సెస్ లేదు"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"ప్రైవేట్ DNS సర్వర్ను యాక్సెస్ చేయడం సాధ్యపడదు"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> పరిమిత కనెక్టివిటీని కలిగి ఉంది"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"ఏదేమైనా కనెక్ట్ చేయడానికి నొక్కండి"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>కి మార్చబడింది"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"పరికరం <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>కి ఇంటర్నెట్ యాక్సెస్ లేనప్పుడు <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> నుండి <xliff:g id="NEW_NETWORK">%2$s</xliff:g>కి మార్చబడింది"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"తెలియని నెట్వర్క్ రకం"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"మొబైల్ డేటా"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"బ్లూటూత్"</item>
+ <item msgid="1616528372438698248">"ఈథర్నెట్"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-th/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-th/strings.xml
new file mode 100644
index 0000000..1616e51
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-th/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"ลงชื่อเข้าใช้เครือข่าย WiFi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"ลงชื่อเข้าใช้เครือข่าย"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> เข้าถึงอินเทอร์เน็ตไม่ได้"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"แตะเพื่อดูตัวเลือก"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"เครือข่ายมือถือไม่มีการเข้าถึงอินเทอร์เน็ต"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"เครือข่ายไม่มีการเข้าถึงอินเทอร์เน็ต"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"เข้าถึงเซิร์ฟเวอร์ DNS ไม่ได้"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> มีการเชื่อมต่อจำกัด"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"แตะเพื่อเชื่อมต่อ"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"เปลี่ยนเป็น <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"อุปกรณ์จะใช้ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> เมื่อ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> เข้าถึงอินเทอร์เน็ตไม่ได้ โดยอาจมีค่าบริการ"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"เปลี่ยนจาก <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> เป็น <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"ประเภทเครือข่ายที่ไม่รู้จัก"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"เน็ตมือถือ"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"บลูทูธ"</item>
+ <item msgid="1616528372438698248">"อีเทอร์เน็ต"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-tl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tl/strings.xml
new file mode 100644
index 0000000..3bf1ce4
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tl/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Mag-sign in sa Wi-Fi network"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Mag-sign in sa network"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Walang access sa internet ang <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"I-tap para sa mga opsyon"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Walang access sa internet ang mobile network"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Walang access sa internet ang network"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Hindi ma-access ang pribadong DNS server"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Limitado ang koneksyon ng <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"I-tap para kumonekta pa rin"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Lumipat sa <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Ginagamit ng device ang <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kapag walang access sa internet ang <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>. Maaaring may mga malapat na singilin."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Lumipat sa <xliff:g id="NEW_NETWORK">%2$s</xliff:g> mula sa <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"isang hindi kilalang uri ng network"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobile data"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-tr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tr/strings.xml
new file mode 100644
index 0000000..5c326e5
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tr/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Kablosuz ağda oturum açın"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Ağda oturum açın"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ağının internet bağlantısı yok"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Seçenekler için dokunun"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobil ağın internet bağlantısı yok"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Ağın internet bağlantısı yok"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Gizli DNS sunucusuna erişilemiyor"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> sınırlı bağlantıya sahip"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Yine de bağlanmak için dokunun"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ağına geçildi"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ağının internet erişimi olmadığında cihaz <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ağını kullanır. Bunun için ödeme alınabilir."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ağından <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ağına geçildi"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"bilinmeyen ağ türü"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobil veri"</item>
+ <item msgid="5520925862115353992">"Kablosuz"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-uk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uk/strings.xml
new file mode 100644
index 0000000..d1382da
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uk/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Вхід у мережу Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Вхід у мережу"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"Мережа <xliff:g id="NETWORK_SSID">%1$s</xliff:g> не має доступу до Інтернету"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Торкніться, щоб відкрити опції"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Мобільна мережа не має доступу до Інтернету"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Мережа не має доступу до Інтернету"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Немає доступу до приватного DNS-сервера"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"Підключення до мережі <xliff:g id="NETWORK_SSID">%1$s</xliff:g> обмежено"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Натисніть, щоб усе одно підключитися"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Пристрій перейшов на мережу <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Коли мережа <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> не має доступу до Інтернету, використовується <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Може стягуватися плата."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Пристрій перейшов з мережі <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> на мережу <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"невідомий тип мережі"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"мобільне передавання даних"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"Мережа VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ur/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ur/strings.xml
new file mode 100644
index 0000000..3c031ad
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ur/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi نیٹ ورک میں سائن ان کریں"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"نیٹ ورک میں سائن ان کریں"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> کو انٹرنیٹ تک رسائی حاصل نہیں ہے"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"اختیارات کیلئے تھپتھپائیں"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"موبائل نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> کی کنیکٹوٹی محدود ہے"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"بہر حال منسلک کرنے کے لیے تھپتھپائیں"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> پر سوئچ ہو گیا"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"جب <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> کو انٹرنیٹ تک رسائی نہیں ہوتی ہے تو آلہ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> کا استعمال کرتا ہے۔ چارجز لاگو ہو سکتے ہیں۔"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> سے <xliff:g id="NEW_NETWORK">%2$s</xliff:g> پر سوئچ ہو گیا"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"نیٹ ورک کی نامعلوم قسم"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"موبائل ڈیٹا"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"بلوٹوتھ"</item>
+ <item msgid="1616528372438698248">"ایتھرنیٹ"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-uz/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uz/strings.xml
new file mode 100644
index 0000000..7518db3
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uz/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Wi-Fi tarmoqqa kirish"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Tarmoqqa kirish"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nomli tarmoqda internetga ruxsati yoʻq"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Variantlarni ko‘rsatish uchun bosing"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mobil tarmoq internetga ulanmagan"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Tarmoq internetga ulanmagan"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Xususiy DNS server ishlamayapti"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nomli tarmoqda aloqa cheklangan"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Baribir ulash uchun bosing"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Yangi ulanish: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Agar <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tarmoqda internet uzilsa, qurilma <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ga ulanadi. Sarflangan trafik uchun haq olinishi mumkin."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> tarmog‘idan <xliff:g id="NEW_NETWORK">%2$s</xliff:g> tarmog‘iga o‘tildi"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"noma’lum tarmoq turi"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"mobil internet"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-vi/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-vi/strings.xml
new file mode 100644
index 0000000..d2284d4
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-vi/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Đăng nhập vào mạng Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Đăng nhập vào mạng"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> không có quyền truy cập Internet"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Nhấn để biết tùy chọn"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Mạng di động không có quyền truy cập Internet"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Mạng không có quyền truy cập Internet"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Không thể truy cập máy chủ DNS riêng tư"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> có khả năng kết nối giới hạn"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Nhấn để tiếp tục kết nối"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Đã chuyển sang <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Thiết bị sử dụng <xliff:g id="NEW_NETWORK">%1$s</xliff:g> khi <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> không có quyền truy cập Internet. Bạn có thể phải trả phí."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Đã chuyển từ <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> sang <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"loại mạng không xác định"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"dữ liệu di động"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"Bluetooth"</item>
+ <item msgid="1616528372438698248">"Ethernet"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..813482b
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"登录到WLAN网络"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"登录到网络"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> 无法访问互联网"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"点按即可查看相关选项"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"此移动网络无法访问互联网"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"此网络无法访问互联网"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"无法访问私人 DNS 服务器"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> 的连接受限"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"点按即可继续连接"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"已切换至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"设备会在<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>无法访问互联网时使用<xliff:g id="NEW_NETWORK">%1$s</xliff:g>(可能需要支付相应的费用)。"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"已从<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>切换至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"未知网络类型"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"移动数据"</item>
+ <item msgid="5520925862115353992">"WLAN"</item>
+ <item msgid="1055487873974272842">"蓝牙"</item>
+ <item msgid="1616528372438698248">"以太网"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..676404f
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"登入 Wi-Fi 網絡"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"登入網絡"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>未有連接至互聯網"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"輕按即可查看選項"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"流動網絡並未連接互聯網"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"網絡並未連接互聯網"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"無法存取私人 DNS 伺服器"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>連線受限"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"仍要輕按以連結至此網絡"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"已切換至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"裝置會在 <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> 無法連線至互聯網時使用<xliff:g id="NEW_NETWORK">%1$s</xliff:g> (可能需要支付相關費用)。"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"已從<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>切換至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"不明網絡類型"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"流動數據"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"藍牙"</item>
+ <item msgid="1616528372438698248">"以太網"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..f355138
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"登入 Wi-Fi 網路"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"登入網路"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> 沒有網際網路連線"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"輕觸即可查看選項"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"這個行動網路沒有網際網路連線"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"這個網路沒有網際網路連線"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"無法存取私人 DNS 伺服器"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> 的連線能力受限"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"輕觸即可繼續連線"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"已切換至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"裝置會在無法連上「<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>」時切換至「<xliff:g id="NEW_NETWORK">%1$s</xliff:g>」(可能需要支付相關費用)。"</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"已從 <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> 切換至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"不明的網路類型"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"行動數據"</item>
+ <item msgid="5520925862115353992">"Wi-Fi"</item>
+ <item msgid="1055487873974272842">"藍牙"</item>
+ <item msgid="1616528372438698248">"乙太網路"</item>
+ <item msgid="9177085807664964627">"VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zu/strings.xml
new file mode 100644
index 0000000..55fefb7
--- /dev/null
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zu/strings.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="wifi_available_sign_in" msgid="381054692557675237">"Ngena ngemvume kunethiwekhi ye-Wi-Fi"</string>
+ <string name="network_available_sign_in" msgid="1520342291829283114">"Ngena ngemvume kunethiwekhi"</string>
+ <!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
+ <string name="wifi_no_internet" msgid="1386911698276448061">"I-<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ayinakho ukufinyelela kwe-inthanethi"</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Thepha ukuze uthole izinketho"</string>
+ <string name="mobile_no_internet" msgid="4014455157529909781">"Inethiwekhi yeselula ayinakho ukufinyelela kwe-inthanethi"</string>
+ <string name="other_networks_no_internet" msgid="6698711684200067033">"Inethiwekhi ayinakho ukufinyelela kwenethiwekhi"</string>
+ <string name="private_dns_broken_detailed" msgid="3709388271074611847">"Iseva eyimfihlo ye-DNS ayikwazi ukufinyelelwa"</string>
+ <string name="network_partial_connectivity" msgid="4791024923851432291">"I-<xliff:g id="NETWORK_SSID">%1$s</xliff:g> inokuxhumeka okukhawulelwe"</string>
+ <string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Thepha ukuze uxhume noma kunjalo"</string>
+ <string name="network_switch_metered" msgid="1531869544142283384">"Kushintshelwe ku-<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"Idivayisi isebenzisa i-<xliff:g id="NEW_NETWORK">%1$s</xliff:g> uma i-<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> inganakho ukufinyelela kwe-inthanethi. Kungasebenza izindleko."</string>
+ <string name="network_switch_metered_toast" msgid="501662047275723743">"Kushintshelewe kusuka ku-<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> kuya ku-<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"uhlobo olungaziwa lwenethiwekhi"</string>
+ <string-array name="network_switch_type_name">
+ <item msgid="2255670471736226365">"idatha yeselula"</item>
+ <item msgid="5520925862115353992">"I-Wi-Fi"</item>
+ <item msgid="1055487873974272842">"I-Bluetooth"</item>
+ <item msgid="1616528372438698248">"I-Ethernet"</item>
+ <item msgid="9177085807664964627">"I-VPN"</item>
+ </string-array>
+</resources>
diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml
index 2c7b992..b2fa5f5 100644
--- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml
+++ b/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml
@@ -14,9 +14,61 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<resources>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- The System Connectivity Resources package is an internal system package that provides
configuration values for system networking that were pre-configured in the device. This
is the name of the package to display in the list of system apps. [CHAR LIMIT=40] -->
<string name="connectivityResourcesAppLabel">System Connectivity Resources</string>
-</resources>
\ No newline at end of file
+
+ <!-- A notification is shown when a wifi captive portal network is detected. This is the notification's title. -->
+ <string name="wifi_available_sign_in">Sign in to Wi-Fi network</string>
+
+ <!-- A notification is shown when a captive portal network is detected. This is the notification's title. -->
+ <string name="network_available_sign_in">Sign in to network</string>
+
+ <!-- A notification is shown when a captive portal network is detected. This is the notification's message. -->
+ <string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string>
+
+ <!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's title. -->
+ <string name="wifi_no_internet"><xliff:g id="network_ssid" example="GoogleGuest">%1$s</xliff:g> has no internet access</string>
+
+ <!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's message. -->
+ <string name="wifi_no_internet_detailed">Tap for options</string>
+
+ <!-- A notification is shown when the user connects to a mobile network without internet access. This is the notification's title. -->
+ <string name="mobile_no_internet">Mobile network has no internet access</string>
+
+ <!-- A notification is shown when the user connects to a non-mobile and non-wifi network without internet access. This is the notification's title. -->
+ <string name="other_networks_no_internet">Network has no internet access</string>
+
+ <!-- A notification is shown when connected network without internet due to private dns validation failed. This is the notification's message. [CHAR LIMIT=NONE] -->
+ <string name="private_dns_broken_detailed">Private DNS server cannot be accessed</string>
+
+ <!-- A notification is shown when the user connects to a network that doesn't have access to some services (e.g. Push notifications may not work). This is the notification's title. [CHAR LIMIT=50] -->
+ <string name="network_partial_connectivity"><xliff:g id="network_ssid" example="GoogleGuest">%1$s</xliff:g> has limited connectivity</string>
+
+ <!-- A notification is shown when the user connects to a network that doesn't have access to some services (e.g. Push notifications may not work). This is the notification's message. [CHAR LIMIT=50] -->
+ <string name="network_partial_connectivity_detailed">Tap to connect anyway</string>
+
+ <!-- A notification might be shown if the device switches to another network type (e.g., mobile data) because it detects that the network it was using (e.g., Wi-Fi) has lost Internet connectivity. This is the notification's title. %1$s is the network type that the device switched to, e.g., cellular data. It is one of the strings in the network_switch_type_name array. -->
+ <string name="network_switch_metered">Switched to <xliff:g id="network_type">%1$s</xliff:g></string>
+
+ <!-- A notification might be shown if the device switches to another network type (e.g., mobile data) because it detects that the network it was using (e.g., Wi-Fi) has lost Internet connectivity. This is the notification's message. %1$s is the network that the device switched to, e.g., cellular data. %2$s is the network type the device switched from, e.g., Wi-Fi. Both are strings in the network_switch_type_name array. -->
+ <string name="network_switch_metered_detail">Device uses <xliff:g id="new_network">%1$s</xliff:g> when <xliff:g id="previous_network">%2$s</xliff:g> has no internet access. Charges may apply.</string>
+
+ <!-- A toast might be shown if the device switches to another network type (e.g., mobile data) because it detects that the network it was using (e.g., Wi-Fi) has lost Internet connectivity. This is the text of the toast. %1$s is the network that the device switched from, e.g., Wi-Fi. %2$s is the network type the device switched from, e.g., cellular data. Both are strings in the network_switch_type_name array. -->
+ <string name="network_switch_metered_toast">Switched from <xliff:g id="previous_network">%1$s</xliff:g> to <xliff:g id="new_network">%2$s</xliff:g></string>
+
+ <!-- Network type names used in the network_switch_metered and network_switch_metered_detail strings. These must be kept in the sync with the values NetworkCapabilities.TRANSPORT_xxx values, and in the same order. -->
+ <string-array name="network_switch_type_name">
+ <item>mobile data</item>
+ <item>Wi-Fi</item>
+ <item>Bluetooth</item>
+ <item>Ethernet</item>
+ <item>VPN</item>
+ </string-array>
+
+ <!-- Network type name displayed if one of the types is not found in network_switch_type_name. -->
+ <string name="network_switch_type_name_unknown">an unknown network type</string>
+
+</resources>
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 68ce7d9..d6c66b5 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -17,8 +17,8 @@
// TODO(b/149540986): revert this change.
static_libs: [
- // All other dependent components should be put in
- // "SettingsLibDependenciesWithoutWifiTracker".
+ // All other dependent components should be put in
+ // "SettingsLibDependenciesWithoutWifiTracker".
"WifiTrackerLib",
],
@@ -27,10 +27,7 @@
resource_dirs: ["res"],
- srcs: [
- "src/**/*.java",
- "src/**/*.kt",
- ],
+ srcs: ["src/**/*.java", "src/**/*.kt"],
min_sdk_version: "21",
diff --git a/packages/SettingsLib/TwoTargetPreference/Android.bp b/packages/SettingsLib/TwoTargetPreference/Android.bp
index f2e79b9..078e8c3 100644
--- a/packages/SettingsLib/TwoTargetPreference/Android.bp
+++ b/packages/SettingsLib/TwoTargetPreference/Android.bp
@@ -1,3 +1,12 @@
+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"],
+}
+
android_library {
name: "SettingsLibTwoTargetPreference",
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 0ee44f8..7cf8cda 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rooi-groen)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blou-geel)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurregstelling"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Verstel hoe kleure op jou toestel vertoon. Dit kan nuttig wees wanneer jy:<br/><br/> <ol> <li> Kleure meer akkuraat wil sien</li> <li> Kleure wil verwyder om jou te help fokus</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Verstel hoe kleure op jou toestel vertoon. Dit kan nuttig wees wanneer jy:<br/><br/> <ol> <li>&nbsp;Kleure meer akkuraat wil sien</li> <li>&nbsp;Kleure wil verwyder om jou te help fokus</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 9fb676f..d3e4d1c 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ፕሮታኖማሊ (ቀይ-አረንጓዴ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ትራይታኖማሊ (ሰማያዊ-ቢጫ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"የቀለም ማስተካከያ"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ቀለሞች በመሣሪያዎ ላይ እንዴት እንደሚታዩ ያስተካክሉ። የሚከተሉትን ለማድረግ በሚፈልጉበት ጊዜ ይህ ጠቃሚ ሊሆን ይችላል፦<br/><br/> <ol> <li> ቀለሞችን የበለጠ ትክክለኛ በሆነ መልኩ ለመመልከት</li> <li> ትኩረት ለማድረግ እንዲረዳዎ ቀለሞችን ለማስወገድ</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"ቀለሞች በመሣሪያዎ ላይ እንዴት እንደሚታዩ ያስተካክሉ። የሚከተሉትን ለማድረግ በሚፈልጉበት ጊዜ ይህ ጠቃሚ ሊሆን ይችላል፦<br/><br/> <ol> <li>&nbsp;ቀለሞችን የበለጠ ትክክለኛ በሆነ መልኩ ለመመልከት</li> <li>&nbsp;ትኩረት ለማድረግ እንዲረዳዎ ቀለሞችን ለማስወገድ</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ገደማ ቀርቷል"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index cdb418a..ca613f9 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"غطش الأحمر (الأحمر والأخضر)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"غمش الأزرق (الأزرق والأصفر)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"تصحيح الألوان"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"يمكنك تعديل كيفية عرض الألوان على جهازك. يساعدك هذا الخيار عندما تريد تنفيذ ما يلي:<br/><br/> <ol> <li> عرض الألوان بمزيد من الدقة</li> <li> إزالة الألوان لمساعدتك على التركيز</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"يمكنك تعديل كيفية عرض الألوان على جهازك. يساعدك هذا الخيار عندما تريد تنفيذ ما يلي:<br/><br/> <ol> <li>&nbsp;عرض الألوان بمزيد من الدقة</li> <li>&nbsp;إزالة الألوان لمساعدتك على التركيز</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا"</string>
@@ -570,7 +570,7 @@
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"مفعّل"</string>
<string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"يجب إعادة تشغيل جهازك ليتم تطبيق هذا التغيير. يمكنك إعادة التشغيل الآن أو إلغاء التغيير."</string>
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"سمّاعة سلكية"</string>
- <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"تفعيل"</string>
+ <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"مفعّلة"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"إيقاف"</string>
<string name="carrier_network_change_mode" msgid="4257621815706644026">"جارٍ تغيير شبكة مشغِّل شبكة الجوّال."</string>
<string name="data_connection_3g" msgid="931852552688157407">"شبكة الجيل الثالث"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 442a19d..6037557 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"প্ৰ’টানোমালি (ৰঙা-সেউজীয়া)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ট্ৰাইটান\'মেলী (নীলা-হালধীয়া)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ৰং শুধৰণী"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"আপোনাৰ ডিভাইচত ৰংবোৰ কেনেকৈ প্ৰদৰ্শিত হয় সেয়া মিলাওক। এইটো আপুনি এই কাৰ্য কৰিবলৈ বিচাৰিলে সহায়ক হ\'ব পাৰে:<br/><br/> <ol> <li> ৰং অধিক সঠিককৈ চাবলৈ বিচৰা</li> <li> আপোনাক মনোযোগ দিয়াত সহায় কৰিবলৈ ৰং আঁতৰোৱা</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"আপোনাৰ ডিভাইচত ৰংবোৰ কেনেকৈ প্ৰদৰ্শিত হয় সেয়া মিলাওক। আপুনি এয়া কৰিবলৈ বিচাৰিলে এইটো সহায়ক হ’ব পাৰে:<br/><br/> <ol> <li>&nbsp;ৰংবোৰ অধিক সঠিকভাৱে চোৱা</li> <li>&nbsp;আপোনাক মনোনিৱেশ কৰাৰ ক্ষেত্ৰত সহায় কৰিবলৈ ৰং আঁতৰোৱা</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>ৰ দ্বাৰা অগ্ৰাহ্য কৰা হৈছে"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"প্রায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 2b0fa86..97ae192 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qırmızı-yaşıl)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (göy-sarı)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rəng düzəlişi"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Cihazınızda rənglərin necə göstərilməsini tənzimləyin. Bu, aşağıdakıları etmək istədikdə faydalı ola bilər:<br/><br/> <ol> <li> Rəngləri daha dəqiq görmək</li> <li> Fokuslanmaq üçün rəngləri ləğv etmək</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Cihazınızda rənglərin necə göstərilməsini tənzimləyin. Bu, aşağıdakıları etmək istədikdə faydalı ola bilər:<br/><br/> <ol> <li>&nbsp;Rəngləri daha dəqiq görmək</li> <li>&nbsp;Fokuslanmaq üçün rəngləri ləğv etmək</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index b318637..6bed4057 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boja"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Prilagodite način na koji se boje prikazuju na uređaju. To može da bude korisno kada želite:<br/><br/> <ol> <li> da vam se boje tačnije prikazuju</li> <li> da uklonite boje kako biste se fokusirali</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Prilagodite način na koji se boje prikazuju na uređaju. To može da bude korisno kada želite:<br/><br/> <ol> <li>&nbsp;da vam se boje tačnije prikazuju</li> <li>&nbsp;da uklonite boje kako biste se fokusirali</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 950a5ae..029d355 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Пратанамалія (чырвоны-зялёны)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Трытанамалія (сіні-жоўты)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Карэкцыя колеру"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Наладзьце адлюстраванне колераў на экране прылады. Гэта налада можа быць карыснай, калі вы захочаце:<br/><br/> <ol> <li> бачыць колеры больш дакладна;</li> <li> выдаліць колеры, якія перашкаджаюць вам сканцэнтравацца</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Наладзьце адлюстраванне колераў на экране прылады. Гэта налада можа быць карыснай, калі вы захочаце:<br/><br/> <ol> <li>&nbsp;бачыць колеры больш дакладна;</li> <li>&nbsp;выдаліць колеры, якія перашкаджаюць вам сканцэнтравацца</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Зараду хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 9ff2531..032b433 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (червено – зелено)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синьо – жълто)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекция на цветове"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Коригирайте как цветовете се показват на устройството ви. Това може да бъде полезно, когато искате да:<br/><br/> <ol> <li> видите цветовете по-ясно;</li> <li> премахнете цветовете, за да се фокусирате.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Коригирайте как цветовете се показват на устройството ви. Това може да бъде полезно, когато искате:<br/><br/> <ol> <li>&nbsp;да видите цветовете по-ясно;</li> <li>&nbsp;да премахнете цветовете, за да се фокусирате.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 4cc9abf..331dfee 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"প্রোটানোম্যালি (লাল-সবুজ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ট্রিট্যানোম্যালি (নীল-হলুদ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"রঙ সংশোধন"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"আপনার ডিভাইসে রঙগুলি কেমন দেখাবে তা অ্যাডজাস্ট করুন। যেক্ষেত্রে এটি আপনাকে সহায়তা করতে পারে:<br/><br/> <ol> <li> আরও নির্ভুলভাবে রঙ দেখতে</li> <li> রঙ সরিয়ে দিলে ফোকাস করতে সহায়তা করবে</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"আপনার ডিভাইসে রঙগুলি কেমন দেখাবে তা অ্যাডজাস্ট করুন। যেক্ষেত্রে এটি আপনাকে সহায়তা করতে পারে:<br/><br/> <ol> <li>&nbsp;আরও নির্ভুলভাবে রঙ দেখতে</li> <li>&nbsp;রঙ সরিয়ে দিয়ে ফোকাস করতে সহায়তা করবে</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index e4bc5a1..08c31ba 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ispravka boje"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Podešavanje načina na koji se boje prikazuju na uređaju. To može biti korisno kada želite:<br/><br/> <ol> <li> tačnije prikazati boje</li> <li> ukloniti boje da se lakše fokusirate</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Podešavanje načina na koji se boje prikazuju na uređaju. To može biti korisno kada želite:<br/><br/> <ol> <li>&nbsp;preciznije prikazati boje</li> <li>&nbsp;ukloniti boje da se lakše fokusirate</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index fa441a2..13a90c3 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermell-verd)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (blau-groc)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correcció de color"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ajusta com es mostren els colors al teu dispositiu. Això pot ser útil quan vulguis:<br/><br/> <ol> <li> Veure els colors amb més claredat.</li> <li> Suprimir colors per poder enfocar més fàcilment.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajusta com es mostren els colors al teu dispositiu. Això pot ser útil quan vulguis:<br/><br/> <ol> <li>&nbsp;Veure els colors amb més claredat.</li> <li>&nbsp;Suprimir colors per poder concentrar-te.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant aproximat: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 717b681..8598ecc 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomálie (červená a zelená)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomálie (modrá a žlutá)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekce barev"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Upravte zobrazování barev na svém zařízení. To se může hodit, když chcete:<br/><br/> <ol> <li> Aby se barvy zobrazovaly přesněji</li> <li> Odstranit barvy, abyste se mohli lépe soustředit</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Upravte zobrazování barev na svém zařízení. To se může hodit, když chcete:<br/><br/> <ol> <li>&nbsp;Zobrazovat barvy přesněji</li> <li>&nbsp;Odstranit barvy, abyste se mohli lépe soustředit</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 6b17db1..d17924f 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopi (rød-grøn)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopi (blå-gul)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korriger farver"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Juster, hvordan farverne vises på skærmen. Dette kan være nyttigt, når du vil:<br/><br/> <ol> <li> Se farver mere nøjagtigt</li> <li> Fjerne farver, så du bedre kan fokusere</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Juster, hvordan farverne vises på din enhed. Dette kan være nyttigt, når du vil:<br/><br/> <ol> <li>&nbsp;Se farver mere nøjagtigt</li> <li>&nbsp;Fjerne farver, så du bedre kan fokusere</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index bb11ed1..a0bf4b1 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -424,7 +424,8 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (Rot-Grün-Sehschwäche)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (Blau-Gelb-Sehschwäche)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Farbkorrektur"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Hier kannst du anpassen, wie Farben auf deinem Gerät dargestellt werden sollen. Das kann in folgenden Fällen hilfreich sein:<br/><br/> <ol> <li> Wenn Farben genauer dargestellt werden sollen</li> <li> Wenn du Farben entfernen möchtest, um dich besser konzentrieren zu können</li> </ol>"</string>
+ <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (2333641630205214702) -->
+ <skip />
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 76faa4c..5e4d52e 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Πρωτανοπία (κόκκινο-πράσινο)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Τριτανοπία (μπλε-κίτρινο)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Διόρθωση χρωμάτων"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Προσαρμόστε πώς θα εμφανίζονται τα χρώματα στη συσκευή σας. Αυτό μπορεί να είναι χρήσιμο όταν θέλετε:<br/><br/> <ol> <li> Να βλέπετε τα χρώματα με μεγαλύτερη ακρίβεια</li> <li> Να καταργήσετε τα χρώματα για να συγκεντρωθείτε</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Προσαρμόστε πώς θα εμφανίζονται τα χρώματα στη συσκευή σας. Αυτό μπορεί να είναι χρήσιμο όταν θέλετε:<br/><br/> <ol> <li>&nbsp;Να βλέπετε τα χρώματα με μεγαλύτερη ακρίβεια</li> <li>&nbsp;Να καταργήσετε τα χρώματα για να συγκεντρωθείτε</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 9a63404..8dfcb40 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colours more accurately</li> <li> Remove colours to help you focus</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li>&nbsp;See colours more accurately</li> <li>&nbsp;Remove colours to help you focus</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 49271db..17c7934 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colours more accurately</li> <li> Remove colours to help you focus</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li>&nbsp;See colours more accurately</li> <li>&nbsp;Remove colours to help you focus</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 9a63404..8dfcb40 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colours more accurately</li> <li> Remove colours to help you focus</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li>&nbsp;See colours more accurately</li> <li>&nbsp;Remove colours to help you focus</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 9a63404..8dfcb40 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colours more accurately</li> <li> Remove colours to help you focus</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Adjust how colours display on your device. This can be helpful when you want to:<br/><br/> <ol> <li>&nbsp;See colours more accurately</li> <li>&nbsp;Remove colours to help you focus</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 3476b97..2e7e628 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Color correction"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Adjust how colors display on your device. This can be helpful when you want to:<br/><br/> <ol> <li> See colors more accurately</li> <li> Remove colors to help you focus</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Adjust how colors display on your device. This can be helpful when you want to:<br/><br/> <ol> <li>&nbsp;See colors more accurately</li> <li>&nbsp;Remove colors to help you focus</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index fb294c8..d4f2162 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ajusta cómo se muestran los colores en tu dispositivo. Esto puede ser útil cuando quieres:<br/><br/> <ol> <li> Ver colores con más exactitud</li> <li> Quitar colores para mejorar tu concentración</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajusta cómo se muestran los colores en tu dispositivo. Esto puede ser útil cuando quieres:<br/><br/> <ol> <li> Ver colores con más exactitud</li> <li> Quitar colores para tener un enfoque más claro</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 2c5eff2..1a1e84c 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ajusta el modo en que se muestran los colores en tu dispositivo. Esto puede ser útil cuando quieras hacer lo siguiente:<br/><br/> <ol> <li> Ver los colores con más precisión</li> <li> Eliminar colores para ayudarte a mantener la concentración</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajusta el modo en que se muestran los colores en tu dispositivo. Esto puede ser útil cuando quieras hacer lo siguiente:<br/><br/> <ol> <li>&nbsp;Ver los colores con más precisión</li> <li>&nbsp;Quitar colores para ayudarte a mantener la concentración</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 116faad..34e3138 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaalia (punane-roheline)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaalia (sinine-kollane)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värvide korrigeerimine"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Kohandage seadmes värvide kuvamist. Sellest võib olla kasu, kui soovite:<br/><br/> <ol> <li> värve täpsemalt näha;</li> <li> värve eemaldada, et paremini keskenduda.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Kohandage seadmes värvide kuvamist. Sellest võib olla kasu, kui soovite:<br/><br/> <ol> <li>&nbsp;värve täpsemalt näha;</li> <li>&nbsp;värve eemaldada, et paremini keskenduda.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäänud"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index bfb4efc..a18c0f1 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -424,7 +424,8 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopia (gorri-berdeak)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopia (urdin-horia)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koloreen zuzenketa"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Doitu nola bistaratzen diren koloreak gailuan. Kasu hauetan izan daiteke lagungarria:<br/><br/> <ol> <li> Koloreak zehatzago ikusi nahi dituzunean.</li> <li> Hobeto fokuratzeko, koloreak kendu nahi dituzunean.</li> </ol>"</string>
+ <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (2333641630205214702) -->
+ <skip />
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index f3018ba..6b55e89 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"قرمزدشواربینی (قرمز-سبز)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"آبیدشواربینی (آبی-زرد)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"تصحیح رنگ"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"نحوه نمایش رنگها را در دستگاهتان تنظیم میکند. این ویژگی میتواند در موارد زیر مفید باشد:<br/><br/> <ol> <li> وقتی میخواهید رنگها را با دقت بیشتری ببینید</li> <li> وقتی میخواهید رنگها را حذف کنید تا تمرکز بیشتری داشته باشید"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"نحوه نمایش رنگها را در دستگاهتان تنظیم میکند. این ویژگی میتواند در موارد زیر مفید باشد:<br/><br/> <ol> <li>&nbsp; وقتی میخواهید رنگها را با دقت بیشتری ببینید</li> <li>&nbsp;وقتی میخواهید رنگها را حذف کنید تا تمرکز بیشتری داشته باشید</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 7089937..b0519bb 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (puna-vihersokeus)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (sini-keltasokeus)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värinkorjaus"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Muuta värien näkymistä laitteellasi. Tästä voi olla hyötyä, kun haluat<br/><br/> <ol> <li> nähdä värit tarkemmin</li> <li> poistaa värejä voidaksesi keskittyä paremmin</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Muuta värien näkymistä laitteellasi. Tästä voi olla hyötyä, kun haluat<br/><br/> <ol> <li>&nbsp;nähdä värit tarkemmin</li> <li>&nbsp;poistaa värejä voidaksesi keskittyä paremmin</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ac8adde..513b7d2 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu/jaune)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction des couleurs"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ajustez l\'affichage des couleurs sur votre appareil. Ce paramètre peut être utile si vous voulez :<br/><br/> <ol> <li> Mieux distinguer les couleurs</li> <li> Enlever les couleurs pour vous aider à vous concentrer</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajustez l\'affichage des couleurs sur votre appareil. Ce paramètre peut être utile si vous voulez :<br/><br/> <ol> <li>&nbsp;Mieux distinguer les couleurs</li> <li>&nbsp;Enlever les couleurs pour vous aider à vous concentrer</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> : <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index e4e4293..fc788b6 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -424,7 +424,8 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu-jaune)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction des couleurs"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ajustez l\'affichage des couleurs sur votre appareil. Cette option peut vous être utile pour :<br/><br/> <ol> <li> accentuer la précision des couleurs ;</li> <li> supprimer les couleurs pour mieux vous concentrer.</li> </ol>"</string>
+ <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (2333641630205214702) -->
+ <skip />
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 062b7b3..521251f 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (vermello-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección da cor"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Axusta a maneira en que se mostran as cores no teu dispositivo. Esta opción pode resultarche útil se queres:<br/><br/> <ol> <li> Ver mellor as cores</li> <li> Quitar as cores para concentrarte mellor</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Axusta a maneira en que se mostran as cores no teu dispositivo. Esta opción pode resultarche útil se queres:<br/><br/> <ol> <li>&nbsp;Ver mellor as cores</li> <li>&nbsp;Quitar as cores para concentrarte mellor</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 174d0a1..dd0e452 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"પ્રોટેનોમલી (લાલ-લીલો)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ટ્રાઇટેનોમલી(વાદળી-પીળો)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"રંગ સુધારણા"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"તમારા ડિવાઇસ પર રંગો કેવી રીતે બતાવવામાં આવે તેની ગોઠવણી કરો. આ ત્યારે સહાયરૂપ થઈ શકે છે જ્યારે તમારે:<br/><br/> <ol> <li> રંગો વધુ યોગ્ય રીતે જોવા હોય</li> <li> તમને ફોકસ કરવામાં સહાયતા રહે તે માટે રંગો કાઢી નાખવા હોય</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"તમારા ડિવાઇસ પર રંગો કેવી રીતે બતાવવામાં આવે તેની ગોઠવણી કરો. આ ત્યારે સહાયરૂપ થઈ શકે છે જ્યારે તમારે:<br/><br/> <ol> <li>&nbsp;રંગો વધુ યોગ્ય રીતે જોવા હોય</li> <li>&nbsp;તમને ફોકસ કરવામાં સહાયતા રહે તે માટે રંગો કાઢી નાખવા હોય</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"લગભગ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 835e760..4e6ccbb 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"लाल रंग पहचान न पाना (लाल-हरा)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"नीला रंग पहचान न पाना (नीला-पीला)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रंग में सुधार करने की सुविधा"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"आपके डिवाइस पर रंगों के दिखने के तरीके में बदलाव करें. इससे, आपको इनमें मदद मिलेगी:<br/><br/> <ol> <li> रंगों को बेहतर तरीके से देखने में</li> <li> आसानी से फ़ोकस करने के लिए, रंग हटाने में</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"आपके डिवाइस पर रंगों के दिखने के तरीके में बदलाव करें. इससे, आपको इन कामों में मदद मिलेगी:<br/><br/> <ol> <li>&nbsp;रंगों को बेहतर तरीके से देखने में</li> <li>&nbsp;आसानी से फ़ोकस के लिए, रंग हटाने में</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"बैटरी करीब <xliff:g id="TIME_REMAINING">%1$s</xliff:g> में खत्म हो जाएगी"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 3d06baa..0f2c684 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno – zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo – žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boje"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Prilagodite način prikazivanja boja na svojem uređaju. To može biti korisno kad želite:<br/><br/> <ol> <li> vidjeti boje točnije</li> <li> ukloniti boje kako biste se lakše usredotočili</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Prilagodite način prikazivanja boja na svojem uređaju. To može biti korisno kad želite:<br/><br/> <ol> <li>&nbsp;vidjeti boje točnije</li> <li>&nbsp;ukloniti boje kako biste se lakše usredotočili.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 546a038..fd24084 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomália (piros– zöld)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomália (kék–sárga)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Színkorrekció"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Korrigálhatja a színek megjelenítését az eszközén. Ez a következő esetekben lehet hasznos:<br/><br/> <ol> <li> ha pontosabb színeket szeretne látni;</li> <li> ha szeretné eltávolítani a színeket, hogy jobban tudjon koncentrálni.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Korrigálhatja a színek megjelenítését az eszközén. Ez a következő esetekben lehet hasznos:<br/><br/> <ol> <li>&nbsp;ha pontosabb színeket szeretne látni;</li> <li>&nbsp;ha szeretné eltávolítani a színeket, hogy jobban tudjon koncentrálni.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 7c0963d..1201b10 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Պրոտանոմալիա (կարմիր-կանաչ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Տրիտանոմալիա (կապույտ-դեղին)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Գունաշտկում"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Կարգավորեք գույների ցուցադրումը ձեր սարքում։ Դա կարող է օգտակար լինել, երբ դուք ուզում եք՝<br/><br/> <ol> <li> Ավելի հստակ տեսնել գույները</li> <li> Հեռացնել գույները՝ կենտրոնանալու համար</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Կարգավորեք գույների ցուցադրումը ձեր սարքում։ Դա կարող է օգտակար լինել, երբ դուք ուզում եք՝<br/><br/> <ol> <li>&nbsp;Ավելի հստակ տեսնել գույները</li> <li>&nbsp;Հեռացնել գույները՝ կենտրոնանալու համար</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Լիցքը կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 2f8bb46..3c658ad 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (merah-hijau)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (biru-kuning)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koreksi warna"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Sesuaikan cara warna ditampilkan di perangkat Anda. Ini dapat bermanfaat saat Anda ingin:<br/><br/> <ol> <li> Melihat warna dengan lebih akurat</li> <li> Menghapus warna untuk membantu Anda fokus</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Sesuaikan cara warna ditampilkan di perangkat Anda. Ini dapat bermanfaat saat Anda ingin:<br/><br/> <ol> <li>&nbsp;Melihat warna dengan lebih akurat</li> <li>&nbsp;Menghapus warna untuk membantu Anda fokus</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index ea29258..b36adc8 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Litblinda (rauðgræn)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Litblinda (blágul)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Litaleiðrétting"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Stilltu litabirtingu í tækinu þínu. Þetta getur gagnast þegar þú vilt:<br/><br/> <ol> <li> Sjá liti skýrar</li> <li> Fjarlægja liti til að fókusa betur</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Stilltu litabirtingu í tækinu þínu. Þetta getur gagnast þegar þú vilt:<br/><br/> <ol> <li>&nbsp;Sjá liti skýrar</li> <li>&nbsp;Fjarlægja liti til að fókusa betur</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 5dd7a52..31e9d36 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalìa (rosso-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalìa (blu-giallo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correzione del colore"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Regola la modalità di visualizzazione dei colori sul tuo dispositivo. Può essere utile se vuoi:<br/><br/> <ol> <li> Vedere i colori con più precisione</li> <li> Rimuovere colori per mettere a fuoco più facilmente</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Regola la modalità di visualizzazione dei colori sul tuo dispositivo. Può essere utile se vuoi:<br/><br/> <ol> <li>&nbsp;Vedere i colori con più precisione</li> <li>&nbsp;Rimuovere colori per mettere a fuoco più facilmente</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo rimanente: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 20d1e1b..90df3b1 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"פרוטנומליה (אדום-ירוק)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"טריטנומליה (כחול-צהוב)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"תיקון צבע"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ניתן לשנות את האופן שבו צבעים מוצגים במכשיר. שינוי כזה עשוי לעזור:<br/><br/> <ol> <li> להבחין בצבעים בצורה יותר מדויקת</li> <li> להסיר צבעים מסוימים כדי להתמקד</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"ניתן לשנות את האופן שבו צבעים מוצגים במכשיר. שינוי כזה עשוי לעזור:<br/><br/> <ol> <li> להבחין בצבעים בצורה יותר מדויקת</li> <li> להסיר צבעים מסוימים כדי להתמקד</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 4a9126f..9421991 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"第一色弱(赤緑)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"第三色弱(青黄)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色補正"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"デバイスで色をどのように表示するかを調整できます。この設定は以下の場合に役立ちます。<br/><br/> <ol> <li> 色をより正確に表示したい場合</li> <li> はっきり読み取れるよう色を取り除きたい場合</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"デバイスで色をどのように表示するかを調整できます。この設定は以下の場合に役立ちます。<br/><br/> <ol> <li>&nbsp;色をより正確に表示したい場合</li> <li>&nbsp;はっきり読み取れるよう色を取り除きたい場合</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 37db15c..9371a1a 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"პროტოანომალია (წითელი-მწვანე)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ტრიტანომალია (ლურჯი-ყვითელი)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ფერის კორექცია"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"დააკორექტირეთ, როგორ გამოჩნდება ფერები თქვენს მოწყობილობაზე. ეს შეიძლება დაგეხმაროთ, როდესაც გსურთ:<br/><br/> <ol> <li> ფერების მეტი სიზუსტით დანახვა</li> <li> ფერების მოცილება, რომ უკეთ კონცენტრირდეთ</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"დააკორექტირეთ, როგორ გამოჩნდება ფერები თქვენს მოწყობილობაზე. ეს შეიძლება დაგეხმაროთ, როდესაც გსურთ:<br/><br/> <ol> <li>&nbsp;ფერების მეტი სიზუსტით დანახვა</li> <li>&nbsp;ფერების მოცილება, რომ უკეთ კონცენტრირდეთ</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 878966d..22f6001 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (қызыл-жасыл)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (көк-сары)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Түсті түзету"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Құрылғыңызда түстер қалай көрсетілетінін реттеңіз. Бұл мыналар үшін пайдалы болуы мүмкін:<br/><br/> <ol> <li> түстерді анығырақ көру</li> <li> зейініңізді жақсарту үшін түстерді өшіру</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Құрылғыңызда түстердің қалай көрсетілетінін реттеңіз. Бұл мыналар үшін пайдалы болуы мүмкін:<br/><br/> <ol> <li>&nbsp;түстерді анығырақ көру</li> <li>&nbsp;зейініңізді жақсарту үшін түстерді өшіру</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 708879a..cace862 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ក្រហមពណ៌បៃតង)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ពណ៌ខៀវ-លឿង)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ការកែពណ៌"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"កែតម្រូវរបៀបដែលពណ៌បង្ហាញនៅលើឧបករណ៍របស់អ្នក។ ចំណុចនេះអាចមានប្រយោជន៍ នៅពេលដែលអ្នកចង់៖<br/><br/> <ol> <li> មើលឃើញពណ៌កាន់តែត្រឹមត្រូវ</li> <li> លុបពណ៌ ដើម្បីជួយអ្នកក្នុងការផ្ដោត</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"កែតម្រូវរបៀបដែលពណ៌បង្ហាញនៅលើឧបករណ៍របស់អ្នក។ ចំណុចនេះអាចមានប្រយោជន៍ នៅពេលដែលអ្នកចង់៖<br/><br/> <ol> <li>&nbsp;មើលឃើញពណ៌កាន់តែត្រឹមត្រូវ</li> <li>&nbsp;លុបពណ៌ ដើម្បីជួយអ្នកក្នុងការផ្ដោតអារម្មណ៍</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"បដិសេធដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"នៅសល់ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index daf7b6f..e2b62a4 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -424,7 +424,8 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ಪ್ರೊಟನೋಮಲಿ (ಕೆಂಪು-ಹಸಿರು)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ಟ್ರಿಟನೋಮಲಿ (ನೀಲಿ-ಹಳದಿ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಬಣ್ಣಗಳು ಹೇಗೆ ಡಿಸ್ಪ್ಲೇ ಆಗುತ್ತವೆ ಎಂಬುದನ್ನು ಹೊಂದಿಸಿ. ನೀವು ಬಣ್ಣಗಳನ್ನು ಹೆಚ್ಚು ನಿಖರವಾಗಿ ನೋಡಲು ಬಯಸಿದಾಗ:<br/><br/> <ol> <li> ಇದು ಸಹಾಯಕವಾಗಿರುತ್ತದೆ</li> <li> ನಿಮಗೆ ಗಮನಹರಿಸಲು ಸಹಾಯ ಮಾಡಲು ಬಣ್ಣಗಳನ್ನು ತೆಗೆದುಹಾಕಿ</li> </ol>"</string>
+ <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (2333641630205214702) -->
+ <skip />
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index c9960c4..7d49dd9 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"적색약(적녹)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"청색약(청황)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"색상 보정"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"기기에 색상이 표시되는 방식을 조정합니다. 색상을 더 정확하게 보고 싶거나 집중을 위해 일부 색상을 제거할 때 유용합니다."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"기기에 색상이 표시되는 방식을 조정합니다. 다음과 같은 상황에서 유용합니다.<br/><br/> <ol> <li>&nbsp;색상을 더욱 정확하게 보고 싶을 때</li> <li>&nbsp;집중을 위해 색상을 제거하고 싶을 때</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>, <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"남은 시간 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 834200d..1120fe3 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (кызыл-жашыл)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (көк-сары)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Түсүн тууралоо"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Түзмөгүңүздө түстөр кантип көрүнөрүн тууралаңыз. Бул төмөнкү учурларда пайдалуу болот:<br/><br/> <ol> <li> Түстөрдү даана көрүү</li> <li> Ынтаа коюу үчүн түстөрдү өчүрүү</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Түзмөгүңүздө түстөр кантип көрүнөрүн тууралаңыз. Бул төмөнкү учурларда пайдалуу болот:<br/><br/> <ol> <li>&nbsp;Түстөрдү даана көрүү</li> <li>&nbsp;Ынтаа коюу үчүн түстөрдү өчүрүү</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 0dcf1627..043dd99 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ສີແດງ-ສີຂຽວ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ສີຟ້າ-ສີເຫຼືອງ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ການປັບແຕ່ງສີ"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ປັບແກ້ການສະແດງສີຢູ່ອຸປະກອນຂອງທ່ານ. ນີ້ອາດມີປະໂຫຍດໃນເວລາທີ່ທ່ານຕ້ອງການ:<br/><br/> <ol> <li> ເບິ່ງເຫັນສີໄດ້ຖືກຕ້ອງຍິ່ງຂຶ້ນ</li> <li> ລຶບສີອອກເພື່ອຊ່ວຍໃຫ້ທ່ານມີສະມາທິ</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"ປັບແກ້ການສະແດງສີຢູ່ອຸປະກອນຂອງທ່ານ. ນີ້ອາດມີປະໂຫຍດໃນເວລາທີ່ທ່ານຕ້ອງການ:<br/><br/> <ol> <li>&nbsp;ເບິ່ງເຫັນສີໄດ້ຖືກຕ້ອງຍິ່ງຂຶ້ນ</li> <li>&nbsp;ລຶບສີອອກເພື່ອຊ່ວຍໃຫ້ທ່ານມີສະມາທິ</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index c3f9202..e31da9e 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (raudona, žalia)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (mėlyna, geltona)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Spalvų taisymas"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Koreguokite, kaip spalvos rodomos jūsų įrenginyje. Tai gali būti naudinga, kai norite:<br/><br/> <ol> <li> matyti tikslesnes spalvas;</li> <li> pašalinti spalvas, kad būtų lengviau susitelkti.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Koreguokite, kaip spalvos rodomos jūsų įrenginyje. Tai gali būti naudinga, kai norite:<br/><br/> <ol> <li>&nbsp;matyti tikslesnes spalvas;</li> <li>&nbsp;pašalinti spalvas, kad būtų lengviau susitelkti.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 5090df0..aa747be 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomālija (sarkans/zaļš)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomālija (zils/dzeltens)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Krāsu korekcija"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Pielāgojiet krāsu attēlojumu jūsu ierīcē. Izmantojiet šo funkciju, lai:<br/><br/> <ol> <li> skatītu precīzāku krāsu attēlojumu;</li> <li> noņemtu krāsas, kad jāpievēršas kādam uzdevumam.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Pielāgojiet krāsu attēlojumu savā ierīcē. Izmantojot šo iestatījumu, varat:<br/><br/> <ol> <li>&nbsp;skatīt precīzāku krāsu attēlojumu;</li> <li>&nbsp;noņemt krāsas, lai būtu vieglāk koncentrēties.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> — <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index c4890d4..fc22362 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалија (слепило за црвена и зелена)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалија (слепило за сина и жолта)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција на бои"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Приспособете го приказот на боите на уредот. Ова е корисно кога сакате:<br/><br/> <ol> <li> да гледате попрецизни бои</li> <li> да отстраните бои за подобра концентрација</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Приспособете го приказот на боите на уредот. Ова е корисно кога сакате:<br/><br/> <ol> <li>&nbsp;да гледате попрецизни бои</li> <li>&nbsp;да отстраните бои за подобра концентрација</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 829d474..15b91df 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"പ്രോട്ടാനോമലി (ചുവപ്പ്-പച്ച)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ട്രിട്ടാനോമലി (നീല-മഞ്ഞ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"നിറം ക്രമീകരിക്കൽ"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"നിങ്ങളുടെ ഉപകരണത്തിൽ നിറങ്ങൾ എങ്ങനെ പ്രദർശിപ്പിക്കണമെന്ന് ക്രമീകരിക്കുക. ഇനിപ്പറയുന്ന കാര്യങ്ങൾ ചെയ്യാൻ ആഗ്രഹിക്കുമ്പോൾ ഇത് സഹായകരമാകും:<br/><br/> <ol> <li> നിറങ്ങൾ കൂടുതൽ കൃത്യമായി കാണാൻ</li> <li> ഫോക്കസ് ചെയ്യാൻ നിങ്ങളെ സഹായിക്കുന്നതിന് നിറങ്ങൾ നീക്കം ചെയ്യാൻ</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"നിങ്ങളുടെ ഉപകരണത്തിൽ നിറങ്ങൾ എങ്ങനെ പ്രദർശിപ്പിക്കണമെന്ന് ക്രമീകരിക്കുക. ഇനിപ്പറയുന്ന കാര്യങ്ങൾ ചെയ്യാൻ ആഗ്രഹിക്കുമ്പോൾ ഇത് സഹായകരമാകും:<br/><br/> <ol> <li>&nbsp;നിറങ്ങൾ കൂടുതൽ കൃത്യമായി കാണാൻ</li> <li>&nbsp;ഫോക്കസ് ചെയ്യാൻ നിങ്ങളെ സഹായിക്കുന്നതിന് നിറങ്ങൾ നീക്കം ചെയ്യാൻ</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"ഏതാണ്ട് <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 7c833f7..2d2289e 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномаль (улаан-ногоон)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомаль (цэнхэр-шар)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Өнгө тохируулах"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Таны төхөөрөмж дээр өнгийг хэрхэн үзүүлэхийг тохируулна уу. Энэ нь таныг дараахыг хийхийг хүссэн үед хэрэгтэй байж болно:<br/><br/> <ol> <li> Өнгийг илүү оновчтой харах</li> <li> Төвлөрөхийн тулд өнгийг хасах</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Таны төхөөрөмж дээр өнгийг хэрхэн үзүүлэхийг тохируулна уу. Энэ нь танд дараахыг хийхийг хүссэн үед хэрэг болж магадгүй:<br/><br/> <ol> <li>Өнгийг илүү оновчтой харах</li> <li>Танд төвлөрөхөд туслахын тулд өнгийг хасах</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index e9fe1dd..979a685 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -424,7 +424,8 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"क्षीण रक्तवर्णांधता (लाल-हिरवा)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"रंग दृष्टी कमतरता (निळा-पिवळा)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रंग सुधारणा"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"तुमच्या डिव्हाइसवर रंग कसे प्रदर्शित केले जातात ते अॅडजस्ट करा. तुम्हाला </br><br> </br><br> </br><br>अधिक स्पष्टपणे रंग पाहणे </br><br> </br><br> तुम्हाला फोकस करण्यात मदत करण्यासाठी रंग काढून टाकणे</br><br> </br><br> हे करायचे असते तेव्हा उपयुक्त असू शकते."</string>
+ <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (2333641630205214702) -->
+ <skip />
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 4df3855..31ba5af 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (merah-hijau)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (biru-kuning)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Pembetulan warna"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Laraskan cara warna dipaparkan pada peranti anda. Ini boleh membantu apabila anda ingin:<br/><br/> <ol> <li> Lihat warna dengan lebih tepat</li> <li> Alih keluar warna untuk membantu anda fokus</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Laraskan cara warna dipaparkan pada peranti anda. Ini boleh membantu apabila anda ingin:<br/><br/> <ol> <li>&nbsp;Lihat warna dengan lebih tepat</li> <li>&nbsp;Alih keluar warna untuk membantu anda fokus</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index d80242ef..a3fa9c7 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (အနီ-အစိမ်း)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (အပြာ-အဝါ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"အရောင်ပြင်ဆင်မှု"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"သင့်စက်ပစ္စည်းတွင် အရောင်များပြသပုံကို ချိန်ညှိပါ။ ၎င်းက အောက်ပါတို့တွင် အသုံးဝင်နိုင်သည်-<br/><br/> <ol> <li> အရောင်များကို ပိုမိုတိကျစွာ မြင်လိုခြင်း</li> <li> သင်အာရုံစိုက်နိုင်ရန် အရောင်များကို ဖယ်ရှားခြင်း</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"သင့်စက်ပစ္စည်းတွင် အရောင်များပြသပုံကို ချိန်ညှိပါ။ ၎င်းက အောက်ပါတို့တွင် အသုံးဝင်နိုင်သည်-<br/><br/> <ol> <li>&nbsp;အရောင်များကို ပိုမိုတိကျစွာ မြင်လိုခြင်း</li> <li>&nbsp;သင်အာရုံစိုက်နိုင်ရန် အရောင်များကို ဖယ်ရှားခြင်း</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 7b49b40..42a59cb 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rød-grønn)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blå-gul)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Fargekorrigering"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Juster hvordan farger vises på enheten. Dette kan være nyttig når du vil<br/><br/> <ol> <li> se farger mer nøyaktig</li> <li> fjerne farger for å gjøre det enklere å fokusere</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Juster hvordan farger vises på enheten. Dette kan være nyttig når du vil<br/><br/> <ol> <li>&nbsp;se farger mer nøyaktig</li> <li>&nbsp;fjerne farger for å gjøre det enklere å fokusere</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 4d380a5..2b351bc 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -424,7 +424,8 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"प्रोटानेमली (रातो, हरियो)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ट्रिटानोमेली (निलो-पंहेलो)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रङ्ग सुधार"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"तपाईंको यन्त्रमा रङहरू कस्ता देखिन्छन् भन्ने कुरा मिलाउनुहोस्। यो सुविधा निम्न अवस्थामा उपयोगी हुन सक्छ:<br/><br/> <ol> <li> तपाईं अझ सटीक रूपमा रङहरू देख्न चाहनुहुन्छ भने</li> <li> तपाईं कुनै कुरामा ध्यान केन्द्रित गर्न रङहरू हटाउन चाहनुहुन्छ भने</li> </ol>"</string>
+ <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (2333641630205214702) -->
+ <skip />
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 518aaa9..a3a490d 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -236,7 +236,7 @@
<string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Maak verbinding met een wifi-netwerk"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, foutopsporing, ontwikkeling"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Snelle link naar bugrapport"</string>
- <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Een knop in het aan/uit-menu weergeven om een bugrapport te maken"</string>
+ <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Een knop in het aan/uit-menu tonen om een bugrapport te maken"</string>
<string name="keep_screen_on" msgid="1187161672348797558">"Stand-by"</string>
<string name="keep_screen_on_summary" msgid="1510731514101925829">"Scherm gaat nooit uit tijdens het opladen"</string>
<string name="bt_hci_snoop_log" msgid="7291287955649081448">"Snoop-logbestand voor Bluetooth-HCI inschakelen"</string>
@@ -255,7 +255,7 @@
<string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Via wifi ondersteunde MAC-herschikking"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"Mobiele data altijd actief"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardwareversnelling voor tethering"</string>
- <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Bluetooth-apparaten zonder namen weergeven"</string>
+ <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Bluetooth-apparaten zonder naam tonen"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Absoluut volume uitschakelen"</string>
<string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche inschakelen"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth-AVRCP-versie"</string>
@@ -281,8 +281,8 @@
<string name="private_dns_mode_provider" msgid="3619040641762557028">"Hostnaam van privé-DNS-provider"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"Geef hostnaam van DNS-provider op"</string>
<string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"Kan geen verbinding maken"</string>
- <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Opties weergeven voor certificering van draadloze weergave"</string>
- <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Logniveau voor wifi verhogen, weergeven per SSID RSSI in wifi-kiezer"</string>
+ <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Opties tonen voor certificering van draadloze weergave"</string>
+ <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Logniveau voor wifi verhogen, tonen per SSID RSSI in wifi-kiezer"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Verlaagt het batterijverbruik en verbetert de netwerkprestaties"</string>
<string name="wifi_enhanced_mac_randomization_summary" msgid="1210663439867489931">"Als deze modus is ingeschakeld, kan het MAC-adres van dit apparaat elke keer wijzigen als het verbinding maakt met een netwerk waarvoor MAC-herschikking is ingeschakeld."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"Met datalimiet"</string>
@@ -297,7 +297,7 @@
<string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB-configuratie selecteren"</string>
<string name="allow_mock_location" msgid="2102650981552527884">"Neplocaties toestaan"</string>
<string name="allow_mock_location_summary" msgid="179780881081354579">"Neplocaties toestaan"</string>
- <string name="debug_view_attributes" msgid="3539609843984208216">"Inspectie van weergavekenmerk inschakelen"</string>
+ <string name="debug_view_attributes" msgid="3539609843984208216">"Inspectie van weergavekenmerk aanzetten"</string>
<string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Mobiele data altijd actief houden, ook als wifi actief is (voor sneller schakelen tussen netwerken)."</string>
<string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Hardwareversnelling voor tethering gebruiken indien beschikbaar"</string>
<string name="adb_warning_title" msgid="7708653449506485728">"USB-foutopsporing toestaan?"</string>
@@ -334,12 +334,12 @@
<string name="strict_mode_summary" msgid="1838248687233554654">"Knipperend scherm bij lange bewerkingen door apps"</string>
<string name="pointer_location" msgid="7516929526199520173">"Cursorlocatie"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"Schermoverlay met huidige aanraakgegevens"</string>
- <string name="show_touches" msgid="8437666942161289025">"Tikken weergeven"</string>
- <string name="show_touches_summary" msgid="3692861665994502193">"Visuele feedback weergeven voor tikken"</string>
- <string name="show_screen_updates" msgid="2078782895825535494">"Oppervlakupdates weergeven"</string>
+ <string name="show_touches" msgid="8437666942161289025">"Tikken tonen"</string>
+ <string name="show_touches_summary" msgid="3692861665994502193">"Visuele feedback tonen voor tikken"</string>
+ <string name="show_screen_updates" msgid="2078782895825535494">"Oppervlakupdates tonen"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"Volledige vensteroppervlakken flashen bij updates"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"Weergave-updates tonen"</string>
- <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Flash-weergave in vensters bij update"</string>
+ <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Flash-weergaven in vensters bij update"</string>
<string name="show_hw_layers_updates" msgid="5268370750002509767">"Hardwarelayer-upd. tonen"</string>
<string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Hardwarelagen knipperen groen bij updates"</string>
<string name="debug_hw_overdraw" msgid="8944851091008756796">"Foutopsporing GPU-overbelasting"</string>
@@ -349,8 +349,8 @@
<string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL-sporen inschakelen"</string>
<string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB-audiorouting uitsch."</string>
<string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Autom. routing naar USB-randapparatuur uitsch."</string>
- <string name="debug_layout" msgid="1659216803043339741">"Indelingsgrenzen weergeven"</string>
- <string name="debug_layout_summary" msgid="8825829038287321978">"Clipgrenzen, marges en meer weergeven"</string>
+ <string name="debug_layout" msgid="1659216803043339741">"Indelingsgrenzen tonen"</string>
+ <string name="debug_layout_summary" msgid="8825829038287321978">"Clipgrenzen, marges en meer tonen"</string>
<string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"V.r.n.l.-indelingsrichting afdwingen"</string>
<string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Schermindelingsrichting geforceerd instellen op v.r.n.l. voor alle talen"</string>
<string name="force_msaa" msgid="4081288296137775550">"4x MSAA forceren"</string>
@@ -404,9 +404,9 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Standaardwaarden voor transcodering overschrijven"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Transcodering inschakelen"</string>
<string name="transcode_default" msgid="3784803084573509491">"Aannemen dat apps moderne indelingen ondersteunen"</string>
- <string name="transcode_notification" msgid="5560515979793436168">"Transcoderingsmeldingen laten zien"</string>
+ <string name="transcode_notification" msgid="5560515979793436168">"Transcoderingsmeldingen tonen"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Actieve services"</string>
- <string name="runningservices_settings_summary" msgid="1046080643262665743">"Services die momenteel actief zijn, weergeven en beheren"</string>
+ <string name="runningservices_settings_summary" msgid="1046080643262665743">"Services die momenteel actief zijn, bekijken en beheren"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementatie"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView-implementatie instellen"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Deze keuze is niet meer geldig. Probeer het opnieuw."</string>
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rood-groen)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blauw-geel)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurcorrectie"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Aanpassen hoe kleuren worden getoond op je apparaat. In de volgende gevallen kan dit handig zijn:<br/><br/> <ol> <li> Je wilt kleuren duidelijker zien.</li> <li> Je wilt kleuren verwijderen zodat je je beter kunt focussen.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Aanpassen hoe kleuren worden getoond op je apparaat. In de volgende gevallen kan dit handig zijn:<br/><br/> <ol> <li>&nbsp;Je wilt kleuren duidelijker zien.</li> <li>&nbsp;Je wilt kleuren verwijderen zodat je je beter kunt focussen.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Nog ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index b0fff21..b7a6819 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ପ୍ରୋଟାନୋମାଲି (ଲାଲ୍-ସବୁଜ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ନୀଳ-ହଳଦିଆ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ଆପଣଙ୍କ ଡିଭାଇସରେ ରଙ୍ଗଗୁଡ଼ିକ କିପରି ଡିସପ୍ଲେ ହୁଏ ତାହା ଆଡଜଷ୍ଟ କରନ୍ତୁ। ଆପଣ ଏହା କରିବାକୁ ଚାହିଁଲେ ଏହା ଉପଯୋଗୀ ହୋଇପାରେ:<br/><br/> <ol> <li> ଆହୁରି ସଠିକ୍ ଭାବେ ରଙ୍ଗଗୁଡ଼ିକୁ ଦେଖିବା</li> <li> ଆପଣଙ୍କୁ ଫୋକସ୍ କରିବାରେ ସାହାଯ୍ୟ କରିବାକୁ ରଙ୍ଗଗୁଡ଼ିକୁ କାଢ଼ିବା</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"ଆପଣଙ୍କ ଡିଭାଇସରେ ରଙ୍ଗଗୁଡ଼ିକ କିପରି ଡିସପ୍ଲେ ହୁଏ ତାହା ଆଡଜଷ୍ଟ କରନ୍ତୁ। ଆପଣ ଏହା କରିବାକୁ ଚାହିଁଲେ ଏହା ଉପଯୋଗୀ ହୋଇପାରେ:<br/><br/> <ol> <li>&nbsp;ଆହୁରି ସଠିକ୍ ଭାବେ ରଙ୍ଗଗୁଡ଼ିକୁ ଦେଖିବା</li> <li>&nbsp;ଆପଣଙ୍କୁ ଫୋକସ୍ କରିବାରେ ସାହାଯ୍ୟ କରିବାକୁ ରଙ୍ଗଗୁଡ଼ିକୁ କାଢ଼ିବା</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ଦ୍ୱାରା ଓଭର୍ରାଇଡ୍ କରାଯାଇଛି"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ବଳକା ଅଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 71e2dba..f1d4a8a 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -424,7 +424,8 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ਲਾਲ-ਹਰਾ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ਨੀਲਾ-ਪੀਲਾ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ਰੰਗ ਸੁਧਾਈ"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਰੰਗਾਂ ਨੂੰ ਦਿਖਾਉਣ ਦੇ ਤਰੀਕੇ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ। ਇਹ ਉਦੋਂ ਲਾਹੇਵੰਦ ਹੋ ਸਕਦਾ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਇਹ ਕਰਨਾ ਚਾਹੋਗੇ:<br/><br/> <ol> <li> ਰੰਗਾਂ ਨੂੰ ਹੋਰ ਸਟੀਕਤਾ ਨਾਲ ਦੇਖਣਾ</li> <li> ਫੋਕਸ ਕਰਨ ਵਿੱਚ ਤੁਹਾਡੀ ਮਦਦ ਲਈ ਰੰਗਾਂ ਨੂੰ ਹਟਾਉਣਾ</li> </ol>"</string>
+ <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (2333641630205214702) -->
+ <skip />
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index c8d7287..cae9f4e 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (czerwony-zielony)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (niebieski-żółty)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcja kolorów"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Dostosuj sposób wyświetlania kolorów na ekranie urządzenia. Może to być pomocne, gdy chcesz:<br/><br/> <ol> <li> dokładniej widzieć kolory;,</li> <li> usunąć wybrane kolory, aby móc skuteczniej się skupić.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Dostosuj sposób wyświetlania kolorów na ekranie urządzenia. Może to być pomocne, gdy chcesz:<br/><br/> <ol> <li>&nbsp;dokładniej widzieć kolory;</li> <li>&nbsp;usunąć wybrane kolory, aby móc skuteczniej się skupić.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 1d6624d..4efdbe2 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ajuste as cores exibidas no seu dispositivo. Esta opção pode ser útil quando você quer:<br/><br/> <ol> <li> ver cores com mais precisão;</li> <li> remover cores para se concentrar melhor.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajuste as cores exibidas no seu dispositivo. Essa opção pode ser útil quando você quer:<br/><br/> <ol> <li>&nbsp;ver cores com mais precisão;</li> <li>&nbsp;remover cores para se concentrar melhor.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 66d4b23..5988a12 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção da cor"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ajuste a visualização das cores no dispositivo. Isto pode ser útil quando pretender:<br/><br/> <ol> <li> Ver cores com maior precisão</li> <li> Remover cores para melhorar a sua concentração</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajuste a visualização das cores no dispositivo. Isto pode ser útil quando pretender:<br/><br/> <ol> <li>&nbsp;Ver cores com maior precisão</li> <li>&nbsp;Remover cores para melhorar a sua concentração</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 1d6624d..4efdbe2 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ajuste as cores exibidas no seu dispositivo. Esta opção pode ser útil quando você quer:<br/><br/> <ol> <li> ver cores com mais precisão;</li> <li> remover cores para se concentrar melhor.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajuste as cores exibidas no seu dispositivo. Essa opção pode ser útil quando você quer:<br/><br/> <ol> <li>&nbsp;ver cores com mais precisão;</li> <li>&nbsp;remover cores para se concentrar melhor.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 3e77ab6..7d2ef6a 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (roșu-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (albastru-galben)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corecția culorii"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ajustați modul în care se afișează culorile pe dispozitiv. Acest lucru poate fi util când doriți să:<br/><br/> <ol> <li> vedeți culorile mai bine</li> <li> eliminați culorile pentru a vă ajuta să vă concentrați</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajustați modul în care se afișează culorile pe dispozitiv. Acest lucru poate fi util când doriți să:<br/><br/> <ol> <li>&nbsp;vedeți culorile mai bine;</li> <li>&nbsp; eliminați culorile pentru a vă ajuta să vă concentrați.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Timp aproximativ rămas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index b342287..02ed8eb 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (красный/зеленый)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синий/желтый)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Коррекция цвета"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Настройте цветопередачу на экране устройства. Эта функция может помочь:<br/><br/> <ol> <li> сделать цвета более четкими;</li> <li> убрать цвета, чтобы вам проще было сфокусироваться.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Настройте цветопередачу на экране устройства. Эта функция может помочь:<br/><br/> <ol> <li>&nbsp;сделать цвета более четкими;</li> <li>&nbsp;убрать цвета, чтобы вам проще было сфокусироваться.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"Уровень заряда – <xliff:g id="PERCENTAGE">%1$s</xliff:g>. <xliff:g id="TIME_STRING">%2$s</xliff:g>."</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Заряда хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 035a159..b5d77c0 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"වර්ණ දුර්වලතාවය (රතු-කොළ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"වර්ණ අන්ධතාවය (නිල්-කහ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"වර්ණ නිවැරදි කිරීම"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ඔබගේ උපාංගයේ වර්ණ සංදර්ශනය වන ආකාරය සීරුමාරු කරන්න. මෙය ඔබට පහත දේවල් සිදු කිරීමට අවශ්ය විට ප්රයෝජනවත් විය හැකිය:<br/><br/> <ol> <li> වර්ණ වඩාත් නිවැරදිව බැලීම</li> <li> ඔබට අවධානය යොමු කිරීමට උදව් වීමට වර්ණ ඉවත් කිරීම</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"ඔබගේ උපාංගයේ වර්ණ සංදර්ශනය වන ආකාරය සීරුමාරු කරන්න. මෙය ඔබට පහත දේවල් සිදු කිරීමට අවශ්ය විට ප්රයෝජනවත් විය හැකිය:<br/><br/> <ol> <li>&nbsp;වර්ණ වඩාත් නිවැරදිව බැලීම</li> <li>&nbsp;ඔබට අවධානය යොමු කිරීමට උදව් වීමට වර්ණ ඉවත් කිරීම</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ක් පමණ ඉතිරියි"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index b24ac8e..4d42623 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomália (červená a zelená)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomália (modrá a žltá)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Úprava farieb"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Upravte si zobrazovanie farieb v zariadení. Môže to byť užitočné, ak chcete:<br/><br/> <ol> <li> zobraziť presnejšie viac farieb;y</li> <li> odstrániť farby, aby ste sa mohli lepšie sústrediť.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Upravte si zobrazovanie farieb v zariadení. Môže to byť užitočné, ak chcete:<br/><br/> <ol> <li>&nbsp;presnejšie zobrazovať farby;</li> <li>&nbsp;odstrániť farby, aby ste sa mohli sústrediť.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Zostáva približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 626402a..b8fb2c4 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (rdeča – zelena)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (modra – rumena)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Popravljanje barv"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Prilagodite prikaz barv v napravi. To je uporabno, ko želite:<br/><br/> <ol> <li> videti bolj prave barve;</li> <li> odstraniti barve, da se lažje osredotočite.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Prilagodite prikaz barv v napravi. To je uporabno, ko želite:<br/><br/> <ol> <li>&nbsp;videti bolj prave barve;</li> <li>&nbsp;odstraniti barve, da se lažje osredotočite.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 4f22348..95ba023 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -424,7 +424,8 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (e kuqe - e gjelbër)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (e kaltër - e verdhë)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korrigjimi i ngjyrës"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Rregullo mënyrën se si ngjyrat afishohen në pajisjen tënde. Kjo mund të jetë e dobishme kur dëshiron që:<br/><br/> <ol> <li> T\'i shikosh ngjyrat me më shumë saktësi</li> <li> T\'i heqësh ngjyrat për të të ndihmuar të fokusohesh</li> </ol>"</string>
+ <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (2333641630205214702) -->
+ <skip />
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 4f37180c..ab49d94 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалија (црвено-зелено)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалија (плаво-жуто)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција боја"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Прилагодите начин на који се боје приказују на уређају. То може да буде корисно када желите:<br/><br/> <ol> <li> да вам се боје тачније приказују</li> <li> да уклоните боје како бисте се фокусирали</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Прилагодите начин на који се боје приказују на уређају. То може да буде корисно када желите:<br/><br/> <ol> <li>&nbsp;да вам се боје тачније приказују</li> <li>&nbsp;да уклоните боје како бисте се фокусирали</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 069b6a5..a630706 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rött-grönt)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blått-gult)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Färgkorrigering"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Ändra hur färger visas på enheten. Det kan vara ett bra hjälpmedel när du vill<br/><br/> <ol> <li> att färger ska visas mer exakt</li> <li> ta bort färger för att fokusera bättre</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ändra hur färger visas på enheten. Det kan vara ett bra hjälpmedel när du vill<br/><br/> <ol> <li>&nbsp;att färger ska visas mer exakt</li> <li>&nbsp;ta bort färger för att fokusera bättre.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 0fb620c..ef68434 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (nyekundu-kijani)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (samawati-manjano)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Usahihishaji wa rangi"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Badilisha jinsi rangi zinavyoonekana kwenye kifaa chako. Hali hii inaweza kuwa muhimu unapotaka:<br/><br/> <ol> <li> Kuona rangi kwa usahihi zaidi</li> <li> Kuondoa rangi ili kukusaidia kuwa makini</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Badilisha jinsi rangi zinavyoonekana kwenye kifaa chako. Hali hii inaweza kuwa muhimu unapotaka:<br/><br/> <ol> <li>&nbsp;Kuona rangi kwa usahihi zaidi</li> <li>&nbsp;Kuondoa rangi ili kukusaidia kuwa makini</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 3106a69..931b43f 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"நிறம் அடையாளங்காண முடியாமை (சிவப்பு-பச்சை)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"நிறம் அடையாளங்காண முடியாமை (நீலம்-மஞ்சள்)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"வண்ணத்திருத்தம்"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"சாதனத்தில் வண்ணங்கள் காண்பிக்கப்படும் விதத்தைச் சரிசெய்யலாம். இதன் மூலம் நீங்கள் விரும்பும்போதெல்லாம்:<br/><br/> <ol> <li> வண்ணங்களை மிகத் தெளிவாகப் பார்க்கலாம்</li> <li> கவனம் சிதறாமல் இருக்க வண்ணங்களை நீக்கலாம்</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"சாதனத்தில் வண்ணங்கள் காண்பிக்கப்படும் விதத்தைச் சரிசெய்யலாம். இதன் மூலம் நீங்கள் விரும்பும்போதெல்லாம்:<br/><br/> <ol> <li>&nbsp;வண்ணங்களை மிகத் தெளிவாகப் பார்க்கலாம்</li> <li>கவனம் சிதறாமல் இருக்க வண்ணங்களை நீக்கலாம்</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 1f78c0c..987ff78a 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -424,7 +424,8 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ప్రొటానోమలీ (ఎరుపు-ఆకుపచ్చ రంగు)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ట్రైటనోమలీ (నీలం-పసుపు రంగు)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"కలర్ సరిచేయడం"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"మీ పరికరంపై రంగులు కనిపించే విధానాన్ని అడ్జస్ట్ చేయండి. మీకు కావలసినప్పుడు, ఇది సహాయకరంగా ఉంటుంది:<br/><br/> <ol> <li> మరింత ఖచ్చితంగా రంగులను చూడండి</li> <li> మీరు ఫోకస్ చేయడంలో సహాయపడటానికి రంగులను తీసివేయండి</li> </ol>"</string>
+ <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (2333641630205214702) -->
+ <skip />
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 4bd7b6d..53a9605 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ตาบอดจางสีแดง (สีแดง/เขียว)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ตาบอดจางสีน้ำเงิน (สีน้ำเงิน/เหลือง)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"การแก้สี"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"ปรับวิธีแสดงสีในอุปกรณ์ การดำเนินการนี้จะเป็นประโยชน์เมื่อคุณต้องการดังนี้<br/><br/> <ol> <li> เห็นสีได้ถูกต้องยิ่งขึ้น</li> <li> นำสีออกเพื่อช่วยให้เห็นชัดเจนยิ่งขึ้น</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"ปรับวิธีแสดงสีในอุปกรณ์ การดำเนินการนี้จะเป็นประโยชน์เมื่อคุณต้องการดังนี้<br/><br/> <ol> <li>&nbsp;เห็นสีได้ถูกต้องยิ่งขึ้น</li> <li>&nbsp;นำสีออกเพื่อช่วยให้เห็นชัดเจนยิ่งขึ้น</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index e56e5b9..f36d691 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (pula-berde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (asul-dilaw)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Pagtatama ng kulay"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Isaayos kung paano ipinapakita ang mga kulay sa iyong device. Makakatulong ito kapag gusto mong:<br/><br/> <ol> <li> Makakita ng mas tumpak na mga kulay</li> <li> Mag-alis ng mga kulay para matulungan kang mag-focus</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Isaayos kung paano ipinapakita ang mga kulay sa iyong device. Makakatulong ito kapag gusto mong:<br/><br/> <ol> <li>&nbsp;Makakita ng mas tumpak na mga kulay</li> <li>&nbsp;Mag-alis ng mga kulay para matulungan kang mag-focus</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index ef516c4..0c4e7f0 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (kırmızı-yeşil)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (mavi-sarı)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Renk düzeltme"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Renklerin cihazınızda nasıl görüntüleneceğini düzenleyin Bu, şunları yapmak istediğinizde kullanışlı olur:<br/><br/> <ol> <li> Renkleri daha doğru görmek</li> <li> Odaklanmanıza yardımcı olması için renkleri kaldırmak</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Renklerin cihazınızda nasıl görüntüleneceğini düzenleyin Bu, şunları yapmak istediğinizde kullanışlı olur:<br/><br/> <ol> <li>&nbsp;Renkleri daha doğru görmek</li> <li>&nbsp;Odaklanmanıza yardımcı olması için renkleri kaldırmak</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 81528ad..7097835 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалія (червоний – зелений)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалія (синій – жовтий)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекція кольору"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Налаштуйте відтворення кольорів на екрані пристрою. Це може бути корисно, якщо ви хочете:<br/><br/> <ol> <li> точніше відтворювати кольори;</li> <li> вилучити кольори, щоб зосередитися на головному.</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Налаштуйте відтворення кольорів на екрані пристрою. Це може бути корисно, якщо ви хочете:<br/><br/> <ol> <li>&nbsp;точніше відтворювати кольори;</li> <li>&nbsp;вилучити кольори, щоб зосередитися на головному.</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 798c885..0b03d99 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (سرخ سبز)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (نیلا پیلا)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"رنگ کی اصلاح"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"آپ کے آلے پر رنگوں کے ڈسپلے ہونے کے طریقے کو ایڈجسٹ کریں۔ یہ خصوصیت درج ذیل کے لیے مددگار ثابت ہو سکتی ہے:<br/><br/> <ol> <li> جب آپ رنگوں کو مزید درست طریقے سے دیکھنا چاہیں </li> <li> فوکس کرنے میں مدد کے لیے رنگوں کو ہٹادیں</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"آپ کے آلے پر رنگوں کے ڈسپلے ہونے کے طریقے کو ایڈجسٹ کریں۔ یہ درج ذیل کے لیے مددگار ثابت ہوسکتا ہے :<br/>&ltlt;br/> <ol><li>جب آپ رنگوں کو مزید درست طریقے سے دیکھنا چاہیں </li> <li>&nbsp;فوکس کرنے میں مدد کرنے کے لئے رنگوں کو ہٹائیں </li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 6efc0be..4144aac 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qizil/yashil)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (ko‘k/sariq)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rangni tuzatish"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Qurilmadagi ranglar qanday chiqishini moslash Bu quyidagi amallarni bajarishga yordam beradi:<br/><br/> <ol> <li> Ranglarni yanada aniq koʻrish</li> <li> Diqqatni jamlash uchun ranglarni olib tashlash</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Qurilmadagi ranglar qanday chiqishini moslash Bu quyidagi amallarni bajarishga yordam beradi:<br/><br/> <ol> <li>&nbsp;Ranglarni yanada aniq koʻrish</li> <li>&nbsp;Diqqatni jamlash uchun ranglarni olib tashlash</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 148ed89..1afa1fe 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Mù màu đỏ không hoàn toàn (đỏ-xanh lục)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Mù màu (xanh lam-vàng)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Chỉnh màu"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Điều chỉnh cách các màu hiển thị trên thiết bị. Tùy chọn này có thể hữu ích khi bạn muốn:<br/><br/> <ol> <li> Xem các màu chính xác hơn</li> <li> Loại bỏ các màu để giúp bạn tập trung</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Điều chỉnh cách các màu hiển thị trên thiết bị. Tùy chọn này có thể hữu ích khi bạn muốn:<br/><br/> <ol> <li>&nbsp;Xem các màu chính xác hơn</li> <li>&nbsp;Loại bỏ các màu để giúp bạn tập trung</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 67923c5..a71d543 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"红色弱视(红绿不分)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"蓝色弱视(蓝黄不分)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"调整设备上的颜色显示方式。此设置适用于以下情况:<br/><br/> <ol> <li>想要更准确地查看颜色</li> <li>想要去除颜色,以便集中注意力</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"调整设备上的颜色显示方式。此设置对以下情况有帮助:<br/><br/> <ol> <li>&nbsp;您想更准确地看颜色</li> <li>&nbsp;您想去除一些颜色,以便集中注意力</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"大约还可使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index bf69b31..b628c35 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"紅色弱視 (紅綠)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"藍色弱視 (藍黃)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"調整裝置顯示顏色嘅方式。呢項設定喺以下情況適用:<br/><br/> <ol> <li> 想令裝置更加準確咁顯示顏色</li> <li> 移除顏色嚟提高專注力</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"調整裝置顯示顏色嘅方式。呢項設定喺以下情況適用:<br/><br/> <ol> <li>&nbsp;想令裝置更加準確咁顯示顏色</li> <li>&nbsp;移除顏色嚟提高專注力</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index dcfc599..16f405b 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"紅色弱視 (紅-綠)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"藍色弱視 (藍-黃)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"調整裝置顯示顏色的方式。這項設定適用於以下情況:<br/><br/> <ol> <li> 想讓裝置更準確地顯示顏色</li> <li> 移除顏色以提高專注力</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"調整裝置顯示顏色的方式。這項設定適用於以下情況:<br/><br/> <ol> <li>&nbsp;想讓裝置更準確地顯示顏色</li> <li>&nbsp;移除顏色以提高專注力</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 7b0274a..324ebf6 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -424,7 +424,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"I-Protanomaly (bomvu-luhlaza)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"I-Tritanomaly (luhlaza okwesibhakabhaka-phuzi)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ukulungiswa kombala"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="8625527799885140826">"Lungisa indlela imibala eboniswa ngayo kudivayisi yakkho. Lokhu kungaba usizo lapho ufuna:<br/><br/> <ol> <li> Ukubona imibala ngokunembilie</li> <li> Ukususa imibala ukuze ugxile</li> </ol>"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Lungisa indlela imibala eboniswa ngayo kudivayisi yakkho. Lokhu kungasiza uma ufuna ukwenza lokhu:<br/><br/> <ol> <li>&nbsp;Ukubona imibala ngokunembe kakhulu</li> <li>&nbsp;Ukususa imibala ukukusiza ukuthi ugxile</li> </ol>"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 5e2d21b..9c7aac1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1006,7 +1006,7 @@
private boolean isProfileConnectedFail() {
return mIsA2dpProfileConnectedFail || mIsHearingAidProfileConnectedFail
- || mIsHeadsetProfileConnectedFail;
+ || (!isConnectedSapDevice() && mIsHeadsetProfileConnectedFail);
}
/**
@@ -1149,6 +1149,12 @@
BluetoothProfile.STATE_CONNECTED;
}
+ private boolean isConnectedSapDevice() {
+ SapProfile sapProfile = mProfileManager.getSapProfile();
+ return sapProfile != null && sapProfile.getConnectionStatus(mDevice)
+ == BluetoothProfile.STATE_CONNECTED;
+ }
+
public CachedBluetoothDevice getSubDevice() {
return mSubDevice;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 34fdc1e..63cb381 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -441,6 +441,10 @@
return mHearingAidProfile;
}
+ SapProfile getSapProfile() {
+ return mSapProfile;
+ }
+
@VisibleForTesting
HidProfile getHidProfile() {
return mHidProfile;
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java
index 3bb3a0c..7f12cc8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.wifi.WifiManager;
@@ -28,7 +29,6 @@
import com.android.settingslib.R;
import com.android.settingslib.core.lifecycle.Lifecycle;
-import java.net.InetAddress;
import java.util.Iterator;
/**
@@ -93,19 +93,19 @@
* @return the formatted and newline-separated IP addresses, or null if none.
*/
private static String getDefaultIpAddresses(ConnectivityManager cm) {
- LinkProperties prop = cm.getActiveLinkProperties();
+ LinkProperties prop = cm.getLinkProperties(cm.getActiveNetwork());
return formatIpAddresses(prop);
}
private static String formatIpAddresses(LinkProperties prop) {
if (prop == null) return null;
- Iterator<InetAddress> iter = prop.getAllAddresses().iterator();
+ Iterator<LinkAddress> iter = prop.getAllLinkAddresses().iterator();
// If there are no entries, return null
if (!iter.hasNext()) return null;
// Concatenate all available addresses, newline separated
StringBuilder addresses = new StringBuilder();
while (iter.hasNext()) {
- addresses.append(iter.next().getHostAddress());
+ addresses.append(iter.next().getAddress().getHostAddress());
if (iter.hasNext()) addresses.append("\n");
}
return addresses.toString();
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c520568..068efac 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -139,7 +139,6 @@
Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
Settings.Global.AVERAGE_TIME_TO_DISCHARGE,
- Settings.Global.BACKPORT_S_NOTIF_RULES,
Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME,
Settings.Global.BROADCAST_BG_CONSTANTS,
@@ -217,7 +216,6 @@
Settings.Global.DEBUG_APP,
Settings.Global.DEBUG_VIEW_ATTRIBUTES,
Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE,
- Settings.Global.DECORATED_CUSTOM_VIEW_NOTIF_DECORATION,
Settings.Global.DEFAULT_DNS_SERVER,
Settings.Global.DEFAULT_INSTALL_LOCATION,
Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA,
@@ -289,7 +287,6 @@
Settings.Global.WIFI_ON_WHEN_PROXY_DISCONNECTED,
Settings.Global.FSTRIM_MANDATORY_INTERVAL,
Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED,
- Settings.Global.FULLY_CUSTOM_VIEW_NOTIF_DECORATION,
Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Settings.Global.GLOBAL_HTTP_PROXY_HOST,
Settings.Global.GLOBAL_HTTP_PROXY_PAC,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index db38ff6..b86ae6d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -433,6 +433,11 @@
<!-- Permission required for hotword detection service CTS tests -->
<uses-permission android:name="android.permission.MANAGE_HOTWORD_DETECTION" />
+ <uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION"/>
+
+ <!-- Permission required for CTS test - ResourceObserverNativeTest -->
+ <uses-permission android:name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d3d7a95..3904201 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -336,7 +336,7 @@
</receiver>
<activity android:name=".screenshot.LongScreenshotActivity"
- android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
+ android:theme="@style/LongScreenshotActivity"
android:process=":screenshot"
android:exported="false"
android:finishOnTaskLaunch="true" />
@@ -605,11 +605,6 @@
<receiver android:name=".people.widget.PeopleSpaceWidgetPinnedReceiver"
android:enabled="true"/>
- <!-- Widget service -->
- <service android:name=".people.widget.PeopleSpaceWidgetService"
- android:permission="android.permission.BIND_REMOTEVIEWS"
- android:exported="false" />
-
<!-- ContentProvider that returns a People Tile preview for a given shortcut -->
<provider
android:name="com.android.systemui.people.PeopleProvider"
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index 7ba28a8..19bcf95 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -24,51 +24,27 @@
<Button
android:id="@+id/save"
+ style="@android:style/Widget.DeviceDefault.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save"
- app:layout_constraintEnd_toStartOf="@id/cancel"
- app:layout_constraintHorizontal_chainStyle="packed"
+ android:layout_marginLeft="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline" />
+ app:layout_constraintBottom_toTopOf="@id/preview" />
- <Button
- android:id="@+id/cancel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/cancel"
- app:layout_constraintEnd_toStartOf="@id/edit"
- app:layout_constraintStart_toEndOf="@id/save"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline" />
-
- <Button
- android:id="@+id/edit"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/screenshot_edit_label"
- app:layout_constraintEnd_toStartOf="@id/share"
- app:layout_constraintStart_toEndOf="@id/cancel"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline" />
-
- <Button
+ <ImageButton
android:id="@+id/share"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@*android:string/share"
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:tint="?android:textColorPrimary"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:padding="6dp"
+ android:src="@drawable/ic_screenshot_share"
+ android:layout_marginRight="8dp"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toEndOf="@+id/edit"
app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline" />
-
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- app:layout_constraintGuide_percent="0.1" />
+ app:layout_constraintBottom_toTopOf="@id/preview" />
<ImageView
android:id="@+id/preview"
@@ -78,7 +54,7 @@
android:layout_marginHorizontal="48dp"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
- app:layout_constraintTop_toBottomOf="@id/guideline"
+ app:layout_constraintTop_toBottomOf="@id/save"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -93,7 +69,7 @@
android:layout_marginBottom="42dp"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
- app:layout_constraintTop_toBottomOf="@id/guideline"
+ app:layout_constraintTop_toTopOf="@id/preview"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -110,7 +86,7 @@
android:layout_width="200dp"
android:layout_height="200dp"
android:elevation="2dp"
- app:layout_constraintTop_toBottomOf="@id/guideline"
+ app:layout_constraintTop_toTopOf="@id/preview"
app:layout_constraintLeft_toLeftOf="parent"
app:handleThickness="@dimen/screenshot_crop_handle_thickness"
app:handleColor="@*android:color/accent_device_default"
@@ -119,5 +95,24 @@
app:borderColor="#fff"
/>
+ <Button
+ android:id="@+id/edit"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ style="@android:style/Widget.DeviceDefault.Button.Colored"
+ android:backgroundTint="?android:colorBackground"
+ android:drawableStart="@drawable/ic_screenshot_edit"
+ android:drawableTint="?android:textColorPrimary"
+ android:paddingStart="16dp"
+ android:paddingEnd="8dp"
+ android:paddingVertical="8dp"
+ android:textColor="?android:textColorPrimary"
+ android:text="@string/screenshot_edit_label"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ />
+
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 2163806..52a97b1 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -50,4 +50,6 @@
<bool name="flag_pm_lite">false</bool>
<bool name="flag_alarm_tile">false</bool>
+
+ <bool name="flag_charging_ripple">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6858965..691d111 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -958,8 +958,6 @@
<string name="quick_settings_dark_mode_secondary_label_on_at">On at <xliff:g id="time" example="10 pm">%s</xliff:g></string>
<!-- QuickSettings: Secondary text for when the Dark theme or some other tile will be on until some user-selected time. [CHAR LIMIT=20] -->
<string name="quick_settings_dark_mode_secondary_label_until">Until <xliff:g id="time" example="7 am">%s</xliff:g></string>
- <!-- QuickSettings: Label for the toggle that controls whether Reduce Brightness is enabled. [CHAR LIMIT=NONE] -->
- <string name="quick_settings_reduce_bright_colors_label">Reduce brightness</string>
<!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] -->
<string name="quick_settings_nfc_label">NFC</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ff9ea01..4a661dc 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -610,6 +610,11 @@
<item name="android:windowCloseOnTouchOutside">true</item>
</style>
+ <!-- Screenshots -->
+ <style name="LongScreenshotActivity" parent="@android:style/Theme.DeviceDefault.DayNight">
+ <item name="android:windowNoTitle">true</item>
+ </style>
+
<!-- Privacy dialog -->
<style name="PrivacyDialog" parent="ScreenRecord">
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 09e9675a..f98a959 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -41,6 +41,7 @@
srcs: [
"src/**/*.java",
"src/**/I*.aidl",
+ ":wm_shell-aidls",
],
static_libs: [
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 5126284..3da3085 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -16,11 +16,6 @@
package com.android.systemui.shared.recents;
-import android.app.PendingIntent;
-import android.app.PictureInPictureParams;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -28,26 +23,15 @@
import android.os.UserHandle;
import android.view.MotionEvent;
-import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
-import com.android.systemui.shared.recents.ISplitScreenListener;
-import com.android.systemui.shared.recents.IStartingWindowListener;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteTransitionCompat;
/**
* Temporary callbacks into SystemUI.
- * Next id = 44
*/
interface ISystemUiProxy {
/**
- * Proxies SurfaceControl.screenshotToBuffer().
- * @Removed
- * GraphicBufferCompat screenshot(in Rect sourceCrop, int width, int height, int minLayer,
- * int maxLayer, boolean useIdentityTransform, int rotation) = 0;
- */
-
- /**
* Begins screen pinning on the provided {@param taskId}.
*/
void startScreenPinning(int taskId) = 1;
@@ -115,11 +99,6 @@
void stopScreenPinning() = 17;
/**
- * Sets the shelf height and visibility.
- */
- void setShelfHeight(boolean visible, int shelfHeight) = 20;
-
- /**
* Handle the provided image as if it was a screenshot.
*
* Deprecated, use handleImageBundleAsScreenshot with image bundle and UserTask
@@ -139,27 +118,12 @@
void notifySwipeToHomeFinished() = 23;
/**
- * Sets listener to get pinned stack animation callbacks.
- */
- void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) = 24;
-
- /**
* Notifies that quickstep will switch to a new task
* @param rotation indicates which Surface.Rotation the gesture was started in
*/
void onQuickSwitchToNewTask(int rotation) = 25;
/**
- * Start the one-handed mode.
- */
- void startOneHandedMode() = 26;
-
- /**
- * Stop the one-handed mode.
- */
- void stopOneHandedMode() = 27;
-
- /**
* Handle the provided image as if it was a screenshot.
*/
void handleImageBundleAsScreenshot(in Bundle screenImageBundle, in Rect locationInScreen,
@@ -170,88 +134,5 @@
*/
void expandNotificationPanel() = 29;
- /**
- * Notifies that Activity is about to be swiped to home with entering PiP transition and
- * queries the destination bounds for PiP depends on Launcher's rotation and shelf height.
- *
- * @param componentName ComponentName represents the Activity
- * @param activityInfo ActivityInfo tied to the Activity
- * @param pictureInPictureParams PictureInPictureParams tied to the Activity
- * @param launcherRotation Launcher rotation to calculate the PiP destination bounds
- * @param shelfHeight Shelf height of launcher to calculate the PiP destination bounds
- * @return destination bounds the PiP window should land into
- */
- Rect startSwipePipToHome(in ComponentName componentName, in ActivityInfo activityInfo,
- in PictureInPictureParams pictureInPictureParams,
- int launcherRotation, int shelfHeight) = 30;
-
- /**
- * Notifies the swiping Activity to PiP onto home transition is finished
- *
- * @param componentName ComponentName represents the Activity
- * @param destinationBounds the destination bounds the PiP window lands into
- */
- void stopSwipePipToHome(in ComponentName componentName, in Rect destinationBounds) = 31;
-
- /**
- * Registers a RemoteTransitionCompat that will handle transitions. This parameter bundles an
- * IRemoteTransition and a filter that must pass for it.
- */
- void registerRemoteTransition(in RemoteTransitionCompat remoteTransition) = 32;
-
- /** Unegisters a RemoteTransitionCompat that will handle transitions. */
- void unregisterRemoteTransition(in RemoteTransitionCompat remoteTransition) = 33;
-
-// SplitScreen APIs...copied from SplitScreen.java
- /**
- * Stage position isn't specified normally meaning to use what ever it is currently set to.
- */
- //int STAGE_POSITION_UNDEFINED = -1;
- /**
- * Specifies that a stage is positioned at the top half of the screen if
- * in portrait mode or at the left half of the screen if in landscape mode.
- */
- //int STAGE_POSITION_TOP_OR_LEFT = 0;
- /**
- * Specifies that a stage is positioned at the bottom half of the screen if
- * in portrait mode or at the right half of the screen if in landscape mode.
- */
- //int STAGE_POSITION_BOTTOM_OR_RIGHT = 1;
-
- /**
- * Stage type isn't specified normally meaning to use what ever the default is.
- * E.g. exit split-screen and launch the app in fullscreen.
- */
- //int STAGE_TYPE_UNDEFINED = -1;
- /**
- * The main stage type.
- * @see MainStage
- */
- //int STAGE_TYPE_MAIN = 0;
- /**
- * The side stage type.
- * @see SideStage
- */
- //int STAGE_TYPE_SIDE = 1;
-
- void registerSplitScreenListener(in ISplitScreenListener listener) = 34;
- void unregisterSplitScreenListener(in ISplitScreenListener listener) = 35;
-
- /** Hides the side-stage if it is currently visible. */
- void setSideStageVisibility(in boolean visible) = 36;
- /** Removes the split-screen stages. */
- void exitSplitScreen() = 37;
- /** @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible. */
- void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) = 38;
- void startTask(in int taskId, in int stage, in int position, in Bundle options) = 39;
- void startShortcut(in String packageName, in String shortcutId, in int stage, in int position,
- in Bundle options, in UserHandle user) = 40;
- void startIntent(
- in PendingIntent intent, in Intent fillInIntent, in int stage, in int position,
- in Bundle options) = 41;
- void removeFromSideStage(in int taskId) = 42;
- /**
- * Sets listener to get task launching callbacks.
- */
- void setStartingWindowListener(IStartingWindowListener listener) = 43;
+ // Next id = 44
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 937c1df..41840af 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -41,6 +41,18 @@
public static final String KEY_EXTRA_INPUT_MONITOR = "extra_input_monitor";
public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
+ // See IPip.aidl
+ public static final String KEY_EXTRA_SHELL_PIP = "extra_shell_pip";
+ // See ISplitScreen.aidl
+ public static final String KEY_EXTRA_SHELL_SPLIT_SCREEN = "extra_shell_split_screen";
+ // See IOneHanded.aidl
+ public static final String KEY_EXTRA_SHELL_ONE_HANDED = "extra_shell_one_handed";
+ // See IShellTransitions.aidl
+ public static final String KEY_EXTRA_SHELL_SHELL_TRANSITIONS =
+ "extra_shell_shell_transitions";
+ // See IStartingWindow.aidl
+ public static final String KEY_EXTRA_SHELL_STARTING_WINDOW =
+ "extra_shell_starting_window";
public static final String NAV_BAR_MODE_2BUTTON_OVERLAY =
WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
index 255fffd..fa2f32f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
@@ -99,11 +99,6 @@
return this;
}
- @Deprecated
- public TransactionCompat setEarlyWakeup() {
- return this;
- }
-
public TransactionCompat setColor(SurfaceControlCompat surfaceControl, float[] color) {
mTransaction.setColor(surfaceControl.mSurfaceControl, color);
return this;
@@ -118,8 +113,4 @@
SurfaceControl relativeTo, int z) {
t.setRelativeLayer(surfaceControl, relativeTo, z);
}
-
- @Deprecated
- public static void setEarlyWakeup(Transaction t) {
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
index 945c9c4..118f98d 100644
--- a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
+++ b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
@@ -154,7 +154,9 @@
@Override
public void onBiometricRunningStateChanged(boolean running,
BiometricSourceType biometricSourceType) {
- mRunningFPS = running && biometricSourceType == FINGERPRINT;
+ if (biometricSourceType == FINGERPRINT) {
+ mRunningFPS = running;
+ }
mAuthenticated &= !mRunningFPS;
updateButtonVisibility();
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 59c0fb8..865ca40 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -19,18 +19,15 @@
import android.app.ActivityThread;
import android.app.Application;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Process;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
-import android.provider.Settings;
import android.util.Log;
import android.util.TimingsTraceLog;
import android.view.SurfaceControl;
@@ -40,8 +37,6 @@
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.people.PeopleSpaceActivity;
-import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
import com.android.systemui.shared.system.ThreadedRendererCompat;
import com.android.systemui.util.NotificationChannels;
@@ -126,26 +121,6 @@
mServices[i].onBootCompleted();
}
}
- // If SHOW_PEOPLE_SPACE is true, enable People Space widget provider.
- // TODO(b/170396074): Migrate to new feature flag (go/silk-flags-howto)
- try {
- int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.SHOW_PEOPLE_SPACE, 1);
- context.getPackageManager().setComponentEnabledSetting(
- new ComponentName(context, PeopleSpaceWidgetProvider.class),
- showPeopleSpace == 1
- ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- context.getPackageManager().setComponentEnabledSetting(
- new ComponentName(context, PeopleSpaceActivity.class),
- showPeopleSpace == 1
- ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- } catch (Exception e) {
- Log.w(TAG, "Error enabling People Space widget:", e);
- }
}
}, bootCompletedFilter);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index c051b69..ca2c034 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -49,7 +49,6 @@
import com.android.internal.R;
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
import com.android.internal.util.ScreenshotHelper;
-import com.android.systemui.Dependency;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.recents.Recents;
@@ -140,6 +139,7 @@
private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
private final SystemActionsBroadcastReceiver mReceiver;
+ private final Recents mRecents;
private Locale mLocale;
private final AccessibilityManager mA11yManager;
private final Lazy<StatusBar> mStatusBar;
@@ -150,8 +150,10 @@
@Inject
public SystemActions(Context context,
NotificationShadeWindowController notificationShadeController,
- Lazy<StatusBar> statusBar) {
+ Lazy<StatusBar> statusBar,
+ Recents recents) {
super(context);
+ mRecents = recents;
mReceiver = new SystemActionsBroadcastReceiver();
mLocale = mContext.getResources().getConfiguration().getLocales().get(0);
mA11yManager = (AccessibilityManager) mContext.getSystemService(
@@ -366,15 +368,15 @@
}
private void handleRecents() {
- Dependency.get(Recents.class).toggleRecentApps();
+ mRecents.toggleRecentApps();
}
private void handleNotifications() {
- Dependency.get(StatusBar.class).animateExpandNotificationsPanel();
+ mStatusBar.get().animateExpandNotificationsPanel();
}
private void handleQuickSettings() {
- Dependency.get(StatusBar.class).animateExpandSettingsPanel(null);
+ mStatusBar.get().animateExpandSettingsPanel(null);
}
private void handlePowerDialog() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java
index b7726f4..2f025f6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java
@@ -72,7 +72,7 @@
mStateListener.onStateChanged(mStatusBarStateController.getState());
mStatusBar.addExpansionChangedListener(mStatusBarExpansionChangedListener);
- mDumpManger.registerDumpable(getTag(), this);
+ mDumpManger.registerDumpable(getDumpTag(), this);
}
@Override
@@ -80,7 +80,17 @@
mStatusBarStateController.removeCallback(mStateListener);
mStatusBar.removeExpansionChangedListener(mStatusBarExpansionChangedListener);
- mDumpManger.unregisterDumpable(getTag());
+ mDumpManger.unregisterDumpable(getDumpTag());
+ }
+
+ /**
+ * in some cases, onViewAttached is called for the newly added view using an instance of
+ * this controller before onViewDetached is called on the previous view, so we must have a
+ * unique dump tag per instance of this class
+ * @return a unique tag for this instance of this class
+ */
+ private String getDumpTag() {
+ return getTag() + " (" + this + ")";
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index b9f9b1bc..98b3fe4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -321,6 +321,7 @@
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
checkArgument(mSensorProps != null);
+ mStatusBar.setSensorRect(getSensorLocation());
mCoreLayoutParams = new WindowManager.LayoutParams(
// TODO(b/152419866): Use the UDFPS window type when it becomes available.
@@ -367,7 +368,8 @@
*/
public RectF getSensorLocation() {
// This is currently used to calculate the amount of space available for notifications
- // on lockscreen. Keyguard is only shown in portrait mode for now, so this will need to
+ // on lockscreen and for the udfps light reveal animation on keyguard.
+ // Keyguard is only shown in portrait mode for now, so this will need to
// be updated if that ever changes.
return new RectF(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 8f79de5..ed3d5ec 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -34,7 +34,7 @@
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
-import com.android.wm.shell.transition.RemoteTransitions;
+import com.android.wm.shell.transition.ShellTransitions;
import java.util.Optional;
@@ -87,7 +87,7 @@
Builder setShellCommandHandler(Optional<ShellCommandHandler> shellDump);
@BindsInstance
- Builder setTransitions(RemoteTransitions t);
+ Builder setTransitions(ShellTransitions t);
@BindsInstance
Builder setStartingSurface(Optional<StartingSurface> s);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index 1b77d1c..bbd95b4 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -33,7 +33,7 @@
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
-import com.android.wm.shell.transition.RemoteTransitions;
+import com.android.wm.shell.transition.ShellTransitions;
import java.util.Optional;
@@ -98,7 +98,7 @@
Optional<TaskViewFactory> getTaskViewFactory();
@WMSingleton
- RemoteTransitions getTransitions();
+ ShellTransitions getTransitions();
@WMSingleton
Optional<StartingSurface> getStartingSurface();
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 09461c3..54d6a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -29,7 +29,6 @@
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.ServiceManager;
-import android.provider.Settings;
import android.util.Log;
import android.view.ViewGroup;
@@ -58,7 +57,6 @@
private Context mContext;
private NotificationEntryManager mNotificationEntryManager;
private int mAppWidgetId;
- private boolean mShowSingleConversation;
@Inject
public PeopleSpaceActivity(NotificationEntryManager notificationEntryManager,
@@ -84,15 +82,7 @@
setTileViewsWithPriorityConversations();
mAppWidgetId = getIntent().getIntExtra(EXTRA_APPWIDGET_ID,
INVALID_APPWIDGET_ID);
- mShowSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
setResult(RESULT_CANCELED);
- // Finish the configuration activity immediately if a widget is added for multiple
- // conversations. If the mAppWidgetId is INVALID, then the activity wasn't launched as a
- // widget configuration activity.
- if (!mShowSingleConversation && mAppWidgetId != INVALID_APPWIDGET_ID) {
- finishActivity();
- }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index 5163879..f9c2a2a 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -19,12 +19,13 @@
import static android.app.Notification.CATEGORY_MISSED_CALL;
import static android.app.Notification.EXTRA_MESSAGES;
import static android.app.people.ConversationStatus.ACTIVITY_ANNIVERSARY;
+import static android.app.people.ConversationStatus.ACTIVITY_AUDIO;
import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
import static android.app.people.ConversationStatus.ACTIVITY_GAME;
import static android.app.people.ConversationStatus.ACTIVITY_LOCATION;
-import static android.app.people.ConversationStatus.ACTIVITY_MEDIA;
import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY;
import static android.app.people.ConversationStatus.ACTIVITY_UPCOMING_BIRTHDAY;
+import static android.app.people.ConversationStatus.ACTIVITY_VIDEO;
import static android.app.people.ConversationStatus.AVAILABILITY_AVAILABLE;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH;
@@ -62,7 +63,6 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.ContactsContract;
-import android.provider.Settings;
import android.service.notification.ConversationChannelWrapper;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
@@ -170,8 +170,6 @@
Context context, INotificationManager notificationManager, IPeopleManager peopleManager,
LauncherApps launcherApps, NotificationEntryManager notificationEntryManager)
throws Exception {
- boolean showOnlyPriority = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 1;
List<ConversationChannelWrapper> conversations =
notificationManager.getConversations(
false).getList();
@@ -184,25 +182,23 @@
priorityConversations);
// Sort and then add recent and non priority conversations to tiles list.
- if (!showOnlyPriority) {
- if (DEBUG) Log.d(TAG, "Add recent conversations");
- Stream<ShortcutInfo> nonPriorityConversations = conversations.stream()
- .filter(c -> c.getNotificationChannel() == null
- || !c.getNotificationChannel().isImportantConversation())
- .map(c -> c.getShortcutInfo());
+ if (DEBUG) Log.d(TAG, "Add recent conversations");
+ Stream<ShortcutInfo> nonPriorityConversations = conversations.stream()
+ .filter(c -> c.getNotificationChannel() == null
+ || !c.getNotificationChannel().isImportantConversation())
+ .map(c -> c.getShortcutInfo());
- List<ConversationChannel> recentConversationsList =
- peopleManager.getRecentConversations().getList();
- Stream<ShortcutInfo> recentConversations = recentConversationsList
- .stream()
- .map(c -> c.getShortcutInfo());
+ List<ConversationChannel> recentConversationsList =
+ peopleManager.getRecentConversations().getList();
+ Stream<ShortcutInfo> recentConversations = recentConversationsList
+ .stream()
+ .map(c -> c.getShortcutInfo());
- Stream<ShortcutInfo> mergedStream = Stream.concat(nonPriorityConversations,
- recentConversations);
- List<PeopleSpaceTile> recentTiles =
- getSortedTiles(peopleManager, launcherApps, mergedStream);
- tiles.addAll(recentTiles);
- }
+ Stream<ShortcutInfo> mergedStream = Stream.concat(nonPriorityConversations,
+ recentConversations);
+ List<PeopleSpaceTile> recentTiles =
+ getSortedTiles(peopleManager, launcherApps, mergedStream);
+ tiles.addAll(recentTiles);
tiles = augmentTilesFromVisibleNotifications(context, tiles, notificationEntryManager);
return tiles;
@@ -501,8 +497,10 @@
return context.getString(R.string.location_status);
case ACTIVITY_NEW_STORY:
return context.getString(R.string.new_story_status);
- case ACTIVITY_MEDIA:
+ case ACTIVITY_VIDEO:
return context.getString(R.string.video_status);
+ case ACTIVITY_AUDIO:
+ return context.getString(R.string.audio_status);
case ACTIVITY_GAME:
return context.getString(R.string.game_status);
default:
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index fa7b7b3..4ad685e 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -45,7 +45,6 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.preference.PreferenceManager;
-import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
@@ -129,12 +128,8 @@
}
if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets");
- boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
- if (showSingleConversation) {
- synchronized (mLock) {
- updateSingleConversationWidgets(widgetIds);
- }
+ synchronized (mLock) {
+ updateSingleConversationWidgets(widgetIds);
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e);
@@ -227,11 +222,6 @@
public void updateWidgetsWithNotificationChanged(StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction notificationAction) {
if (DEBUG) Log.d(TAG, "updateWidgetsWithNotificationChanged called");
- boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
- if (!showSingleConversation) {
- return;
- }
try {
String sbnShortcutId = sbn.getShortcutId();
if (sbnShortcutId == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
deleted file mode 100644
index 87b2a15..0000000
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.people.widget;
-
-import android.app.INotificationManager;
-import android.app.people.IPeopleManager;
-import android.app.people.PeopleSpaceTile;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.LauncherApps;
-import android.content.pm.PackageManager;
-import android.os.ServiceManager;
-import android.util.Log;
-import android.widget.RemoteViews;
-import android.widget.RemoteViewsService;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.people.PeopleSpaceTileView;
-import com.android.systemui.people.PeopleSpaceUtils;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** People Space Widget RemoteViewsFactory class. */
-public class PeopleSpaceWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
- private static final String TAG = "PeopleSpaceWRVFactory";
- private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
-
- private IPeopleManager mPeopleManager;
- private INotificationManager mNotificationManager;
- private NotificationEntryManager mNotificationEntryManager;
- private PackageManager mPackageManager;
- private LauncherApps mLauncherApps;
- private List<PeopleSpaceTile> mTiles = new ArrayList<>();
- private Context mContext;
-
- public PeopleSpaceWidgetRemoteViewsFactory(Context context, Intent intent) {
- this.mContext = context;
- }
-
- @Override
- public void onCreate() {
- if (DEBUG) Log.d(TAG, "onCreate called");
- mNotificationManager = INotificationManager.Stub.asInterface(
- ServiceManager.getService(Context.NOTIFICATION_SERVICE));
- mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
- mPackageManager = mContext.getPackageManager();
- mPeopleManager = IPeopleManager.Stub.asInterface(
- ServiceManager.getService(Context.PEOPLE_SERVICE));
- mLauncherApps = mContext.getSystemService(LauncherApps.class);
- setTileViewsWithPriorityConversations();
- }
-
- /**
- * Retrieves all priority conversations and sets a {@link PeopleSpaceTileView}s for each
- * priority conversation.
- */
- private void setTileViewsWithPriorityConversations() {
- try {
- mTiles = PeopleSpaceUtils.getTiles(mContext, mNotificationManager,
- mPeopleManager, mLauncherApps, mNotificationEntryManager);
- } catch (Exception e) {
- Log.e(TAG, "Couldn't retrieve conversations", e);
- }
- }
-
- @Override
- public void onDataSetChanged() {
- if (DEBUG) Log.d(TAG, "onDataSetChanged called");
- setTileViewsWithPriorityConversations();
- }
-
- @Override
- public void onDestroy() {
- mTiles.clear();
- }
-
- @Override
- public int getCount() {
- return mTiles.size();
- }
-
- @Override
- public RemoteViews getViewAt(int i) {
- if (DEBUG) Log.d(TAG, "getViewAt called, index: " + i);
-
- RemoteViews personView = new RemoteViews(mContext.getPackageName(),
- R.layout.people_space_widget_item);
- try {
- PeopleSpaceTile tile = mTiles.get(i);
-
- String status = PeopleSpaceUtils.getLastInteractionString(mContext,
- tile.getLastInteractionTimestamp());
-
- personView.setTextViewText(R.id.status, status);
- personView.setTextViewText(R.id.name, tile.getUserName().toString());
-
- personView.setImageViewBitmap(
- R.id.package_icon,
- PeopleSpaceUtils.convertDrawableToBitmap(
- mPackageManager.getApplicationIcon(tile.getPackageName())
- )
- );
- personView.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
-
- Intent fillInIntent = new Intent();
- fillInIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
- fillInIntent.putExtra(
- PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
- fillInIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE,
- tile.getUserHandle());
- personView.setOnClickFillInIntent(R.id.item, fillInIntent);
- } catch (Exception e) {
- Log.e(TAG, "Couldn't retrieve shortcut information", e);
- }
- return personView;
- }
-
- @Override
- public RemoteViews getLoadingView() {
- return null;
- }
-
- @Override
- public int getViewTypeCount() {
- return 1;
- }
-
- @Override
- public long getItemId(int i) {
- return i;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetService.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetService.java
deleted file mode 100644
index c0e4347..0000000
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetService.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.people.widget;
-import android.content.Intent;
-import android.util.Log;
-import android.widget.RemoteViewsService;
-
-import com.android.systemui.people.PeopleSpaceUtils;
-
-/** People Space Widget Service class. */
-public class PeopleSpaceWidgetService extends RemoteViewsService {
- private static final String TAG = "PeopleSpaceWidgetSvc";
- private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
-
- @Override
- public RemoteViewsFactory onGetViewFactory(Intent intent) {
- if (DEBUG) Log.d(TAG, "onGetViewFactory called");
- return new PeopleSpaceWidgetRemoteViewsFactory(this.getApplicationContext(), intent);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
index 479be65..03a6689 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
@@ -25,8 +25,8 @@
import android.service.quicksettings.Tile;
import android.widget.Switch;
+import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -98,14 +98,14 @@
@Override
public CharSequence getTileLabel() {
- return mContext.getString(R.string.quick_settings_reduce_bright_colors_label);
+ return mContext.getString(R.string.reduce_bright_colors_feature_name);
}
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
state.value = mReduceBrightColorsController.isReduceBrightColorsActivated();
state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
- state.label = mContext.getString(R.string.quick_settings_reduce_bright_colors_label);
+ state.label = mContext.getString(R.string.reduce_bright_colors_feature_name);
state.expandedAccessibilityClassName = Switch.class.getName();
state.contentDescription = state.label;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index dab68ed..86ea50c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -177,8 +177,10 @@
}
}
boolean transientEnabling = arg == ARG_SHOW_TRANSIENT_ENABLING;
- boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.ssid != null);
- boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.ssid == null);
+ boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0)
+ && (cb.ssid != null || cb.wifiSignalIconId != WifiIcons.QS_WIFI_NO_NETWORK);
+ boolean wifiNotConnected = (cb.ssid == null)
+ && (cb.wifiSignalIconId == WifiIcons.QS_WIFI_NO_NETWORK);
boolean enabledChanging = state.value != cb.enabled;
if (enabledChanging) {
mDetailAdapter.setItemsVisible(cb.enabled);
@@ -210,7 +212,7 @@
state.label = r.getString(R.string.quick_settings_wifi_label);
} else if (wifiConnected) {
state.icon = ResourceIcon.get(cb.wifiSignalIconId);
- state.label = removeDoubleQuotes(cb.ssid);
+ state.label = cb.ssid != null ? removeDoubleQuotes(cb.ssid) : getTileLabel();
} else if (wifiNotConnected) {
state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_NO_NETWORK);
state.label = r.getString(R.string.quick_settings_wifi_label);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 8951605..b0a3f43 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -25,6 +25,11 @@
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SPLIT_SCREEN;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_STARTING_WINDOW;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SUPPORTS_WINDOW_CORNERS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_WINDOW_CORNER_RADIUS;
@@ -35,15 +40,12 @@
import android.annotation.FloatRange;
import android.app.ActivityTaskManager;
-import android.app.PendingIntent;
-import android.app.PictureInPictureParams;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -57,14 +59,12 @@
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.util.ArraySet;
import android.util.Log;
import android.view.InputMonitor;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.accessibility.AccessibilityManager;
-import android.window.IRemoteTransition;
import androidx.annotation.NonNull;
@@ -83,15 +83,11 @@
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.shared.recents.IOverviewProxy;
-import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
-import com.android.systemui.shared.recents.ISplitScreenListener;
-import com.android.systemui.shared.recents.IStartingWindowListener;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.RemoteTransitionCompat;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -103,7 +99,7 @@
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
-import com.android.wm.shell.transition.RemoteTransitions;
+import com.android.wm.shell.transition.ShellTransitions;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -111,7 +107,6 @@
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
-import java.util.function.Consumer;
import javax.inject.Inject;
@@ -151,12 +146,11 @@
private final ScreenshotHelper mScreenshotHelper;
private final Optional<OneHanded> mOneHandedOptional;
private final CommandQueue mCommandQueue;
- private final RemoteTransitions mShellTransitions;
+ private final ShellTransitions mShellTransitions;
private final Optional<StartingSurface> mStartingSurface;
private Region mActiveNavBarRegion;
- private IPinnedStackAnimationListener mIPinnedStackAnimationListener;
private IOverviewProxy mOverviewProxy;
private int mConnectionBackoffAttempts;
private boolean mBound;
@@ -169,8 +163,6 @@
private float mWindowCornerRadius;
private boolean mSupportsRoundedCornersOnWindows;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
- private final ArraySet<IRemoteTransition> mRemoteTransitions = new ArraySet<>();
- private IStartingWindowListener mIStartingWindowListener;
@VisibleForTesting
public ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
@@ -383,20 +375,6 @@
}
@Override
- public void setShelfHeight(boolean visible, int shelfHeight) {
- if (!verifyCaller("setShelfHeight")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mPipOptional.ifPresent(
- pip -> pip.setShelfHeight(visible, shelfHeight));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
public void handleImageAsScreenshot(Bitmap screenImage, Rect locationInScreen,
Insets visibleInsets, int taskId) {
// Deprecated
@@ -424,36 +402,6 @@
}
@Override
- public void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) {
- if (!verifyCaller("setPinnedStackAnimationListener")) {
- return;
- }
- mIPinnedStackAnimationListener = listener;
- final long token = Binder.clearCallingIdentity();
- try {
- mPipOptional.ifPresent(
- pip -> pip.setPinnedStackAnimationListener(mPinnedStackAnimationCallback));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void setStartingWindowListener(IStartingWindowListener listener) {
- if (!verifyCaller("setStartingWindowListener")) {
- return;
- }
- mIStartingWindowListener = listener;
- final long token = Binder.clearCallingIdentity();
- try {
- mStartingSurface.ifPresent(s ->
- s.setStartingWindowListener(mStartingWindowListener));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
public void onQuickSwitchToNewTask(@Surface.Rotation int rotation) {
if (!verifyCaller("onQuickSwitchToNewTask")) {
return;
@@ -467,32 +415,6 @@
}
@Override
- public void startOneHandedMode() {
- if (!verifyCaller("startOneHandedMode")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mOneHandedOptional.ifPresent(oneHanded -> oneHanded.startOneHanded());
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void stopOneHandedMode() {
- if (!verifyCaller("stopOneHandedMode")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mOneHandedOptional.ifPresent(oneHanded -> oneHanded.stopOneHanded());
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen,
Insets visibleInsets, Task.TaskKey task) {
mScreenshotHelper.provideScreenshot(
@@ -520,190 +442,6 @@
}
}
- @Override
- public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
- PictureInPictureParams pictureInPictureParams,
- int launcherRotation, int shelfHeight) {
- if (!verifyCaller("startSwipePipToHome")) {
- return null;
- }
- final long binderToken = Binder.clearCallingIdentity();
- try {
- return mPipOptional.map(pip ->
- pip.startSwipePipToHome(componentName, activityInfo,
- pictureInPictureParams, launcherRotation, shelfHeight))
- .orElse(null);
- } finally {
- Binder.restoreCallingIdentity(binderToken);
- }
- }
-
- @Override
- public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
- if (!verifyCaller("stopSwipePipToHome")) {
- return;
- }
- final long binderToken = Binder.clearCallingIdentity();
- try {
- mPipOptional.ifPresent(pip -> pip.stopSwipePipToHome(
- componentName, destinationBounds));
- } finally {
- Binder.restoreCallingIdentity(binderToken);
- }
- }
-
- @Override
- public void registerRemoteTransition(RemoteTransitionCompat remoteTransition) {
- if (!verifyCaller("registerRemoteTransition")) return;
- final long binderToken = Binder.clearCallingIdentity();
- try {
- mRemoteTransitions.add(remoteTransition.getTransition());
- mShellTransitions.registerRemote(
- remoteTransition.getFilter(), remoteTransition.getTransition());
- } finally {
- Binder.restoreCallingIdentity(binderToken);
- }
- }
-
- @Override
- public void unregisterRemoteTransition(RemoteTransitionCompat remoteTransition) {
- if (!verifyCaller("registerRemoteTransition")) return;
- final long binderToken = Binder.clearCallingIdentity();
- try {
- mRemoteTransitions.remove(remoteTransition.getTransition());
- mShellTransitions.unregisterRemote(remoteTransition.getTransition());
- } finally {
- Binder.restoreCallingIdentity(binderToken);
- }
- }
-
- @Override
- public void registerSplitScreenListener(ISplitScreenListener listener) {
- if (!verifyCaller("registerSplitScreenListener")) {
- return;
- }
- mISplitScreenListener = listener;
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(
- s -> s.registerSplitScreenListener(mSplitScreenListener));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void unregisterSplitScreenListener(ISplitScreenListener listener) {
- if (!verifyCaller("unregisterSplitScreenListener")) {
- return;
- }
- mISplitScreenListener = null;
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(
- s -> s.unregisterSplitScreenListener(mSplitScreenListener));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void setSideStageVisibility(boolean visible) {
- if (!verifyCaller("setSideStageVisibility")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s -> s.setSideStageVisibility(visible));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void exitSplitScreen() {
- if (!verifyCaller("exitSplitScreen")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s -> s.exitSplitScreen());
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
- if (!verifyCaller("exitSplitScreenOnHide")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s -> s.exitSplitScreenOnHide(exitSplitScreenOnHide));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void startTask(int taskId, int stage, int position, Bundle options) {
- if (!verifyCaller("startTask")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(
- s -> s.startTask(taskId, stage, position, options));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void startShortcut(String packageName, String shortcutId, int stage, int position,
- Bundle options, UserHandle user) {
- if (!verifyCaller("startShortcut")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s ->
- s.startShortcut(packageName, shortcutId, stage, position, options, user));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void startIntent(PendingIntent intent, Intent fillInIntent,
- int stage, int position, Bundle options) {
- if (!verifyCaller("startIntent")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s ->
- s.startIntent(intent, mContext, fillInIntent, stage, position, options));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void removeFromSideStage(int taskId) {
- if (!verifyCaller("removeFromSideStage")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(
- s -> s.removeFromSideStage(taskId));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
private boolean verifyCaller(String reason) {
final int callerId = Binder.getCallingUserHandle().getIdentifier();
if (callerId != mCurrentBoundedUserId) {
@@ -757,6 +495,22 @@
params.putBinder(KEY_EXTRA_SYSUI_PROXY, mSysUiProxy.asBinder());
params.putFloat(KEY_EXTRA_WINDOW_CORNER_RADIUS, mWindowCornerRadius);
params.putBoolean(KEY_EXTRA_SUPPORTS_WINDOW_CORNERS, mSupportsRoundedCornersOnWindows);
+
+ mPipOptional.ifPresent((pip) -> params.putBinder(
+ KEY_EXTRA_SHELL_PIP,
+ pip.createExternalInterface().asBinder()));
+ mSplitScreenOptional.ifPresent((splitscreen) -> params.putBinder(
+ KEY_EXTRA_SHELL_SPLIT_SCREEN,
+ splitscreen.createExternalInterface().asBinder()));
+ mOneHandedOptional.ifPresent((onehanded) -> params.putBinder(
+ KEY_EXTRA_SHELL_ONE_HANDED,
+ onehanded.createExternalInterface().asBinder()));
+ params.putBinder(KEY_EXTRA_SHELL_SHELL_TRANSITIONS,
+ mShellTransitions.createExternalInterface().asBinder());
+ mStartingSurface.ifPresent((startingwindow) -> params.putBinder(
+ KEY_EXTRA_SHELL_STARTING_WINDOW,
+ startingwindow.createExternalInterface().asBinder()));
+
try {
mOverviewProxy.onInitialize(params);
} catch (RemoteException e) {
@@ -796,42 +550,11 @@
private final StatusBarWindowCallback mStatusBarWindowCallback = this::onStatusBarStateChanged;
private final BiConsumer<Rect, Rect> mSplitScreenBoundsChangeListener =
this::notifySplitScreenBoundsChanged;
- private final Consumer<Boolean> mPinnedStackAnimationCallback =
- this::notifyPinnedStackAnimationStarted;
-
- private final BiConsumer<Integer, Integer> mStartingWindowListener =
- this::notifyTaskLaunching;
// This is the death handler for the binder from the launcher service
private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
= this::cleanupAfterDeath;
- private ISplitScreenListener mISplitScreenListener;
- private final SplitScreen.SplitScreenListener mSplitScreenListener =
- new SplitScreen.SplitScreenListener() {
- @Override
- public void onStagePositionChanged(int stage, int position) {
- try {
- if (mISplitScreenListener != null) {
- mISplitScreenListener.onStagePositionChanged(stage, position);
- }
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "onStagePositionChanged", e);
- }
- }
-
- @Override
- public void onTaskStageChanged(int taskId, int stage, boolean visible) {
- try {
- if (mISplitScreenListener != null) {
- mISplitScreenListener.onTaskStageChanged(taskId, stage, visible);
- }
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "onTaskStageChanged", e);
- }
- }
- };
-
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Inject
public OverviewProxyService(Context context, CommandQueue commandQueue,
@@ -844,7 +567,7 @@
Optional<Lazy<StatusBar>> statusBarOptionalLazy,
Optional<OneHanded> oneHandedOptional,
BroadcastDispatcher broadcastDispatcher,
- RemoteTransitions shellTransitions,
+ ShellTransitions shellTransitions,
Optional<StartingSurface> startingSurface) {
super(broadcastDispatcher);
mContext = context;
@@ -961,29 +684,6 @@
}
}
- private void notifyPinnedStackAnimationStarted(Boolean isAnimationStarted) {
- if (mIPinnedStackAnimationListener == null) {
- return;
- }
- try {
- mIPinnedStackAnimationListener.onPinnedStackAnimationStarted();
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "Failed to call onPinnedStackAnimationStarted()", e);
- }
- }
-
- private void notifyTaskLaunching(int taskId, int supportedType) {
- if (mIStartingWindowListener == null) {
- return;
- }
-
- try {
- mIStartingWindowListener.onTaskLaunching(taskId, supportedType);
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "Failed to call notifyTaskLaunching()", e);
- }
- }
-
private void onStatusBarStateChanged(boolean keyguardShowing, boolean keyguardOccluded,
boolean bouncerShowing) {
mSysUiState.setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
@@ -1027,12 +727,6 @@
// Clean up the minimized state if launcher dies
mLegacySplitScreenOptional.ifPresent(
splitScreen -> splitScreen.setMinimized(false));
-
- // Clean up any registered remote transitions
- for (int i = mRemoteTransitions.size() - 1; i >= 0; --i) {
- mShellTransitions.unregisterRemote(mRemoteTransitions.valueAt(i));
- }
- mRemoteTransitions.clear();
}
public void startConnectionToCurrentUser() {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index 31cdada..6a004c2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -76,7 +76,6 @@
private ImageView mPreview;
private View mSave;
- private View mCancel;
private View mEdit;
private View mShare;
private CropView mCropView;
@@ -117,7 +116,6 @@
mPreview = requireViewById(R.id.preview);
mSave = requireViewById(R.id.save);
- mCancel = requireViewById(R.id.cancel);
mEdit = requireViewById(R.id.edit);
mShare = requireViewById(R.id.share);
mCropView = requireViewById(R.id.crop_view);
@@ -125,7 +123,6 @@
mCropView.setCropInteractionListener(mMagnifierView);
mSave.setOnClickListener(this::onClicked);
- mCancel.setOnClickListener(this::onClicked);
mEdit.setOnClickListener(this::onClicked);
mShare.setOnClickListener(this::onClicked);
@@ -313,7 +310,6 @@
private void setButtonsEnabled(boolean enabled) {
mSave.setEnabled(enabled);
- mCancel.setEnabled(enabled);
mEdit.setEnabled(enabled);
mShare.setEnabled(enabled);
}
@@ -350,8 +346,6 @@
setButtonsEnabled(false);
if (id == R.id.save) {
startExport(PendingAction.SAVE);
- } else if (id == R.id.cancel) {
- finishAndRemoveTask();
} else if (id == R.id.edit) {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
startExport(PendingAction.EDIT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index c3de81c..708bdfe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -98,4 +98,8 @@
public boolean isAlarmTileAvailable() {
return mFlagReader.isEnabled(R.bool.flag_alarm_tile);
}
+
+ public boolean isChargingRippleEnabled() {
+ return mFlagReader.isEnabled(R.bool.flag_charging_ripple);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index c1feaca..563470d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -82,6 +82,31 @@
}
}
+class CircleReveal(
+ /** X-value of the circle center of the reveal. */
+ val centerX: Float,
+ /** Y-value of the circle center of the reveal. */
+ val centerY: Float,
+ /** Radius of initial state of circle reveal */
+ val startRadius: Float,
+ /** Radius of end state of circle reveal */
+ val endRadius: Float
+) : LightRevealEffect {
+ override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
+ val interpolatedAmount = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(amount)
+ val fadeAmount =
+ LightRevealEffect.getPercentPastThreshold(interpolatedAmount, 0.75f)
+ val radius = startRadius + ((endRadius - startRadius) * interpolatedAmount)
+ scrim.revealGradientEndColorAlpha = 1f - fadeAmount
+ scrim.setRevealGradientBounds(
+ centerX - radius /* left */,
+ centerY - radius /* top */,
+ centerX + radius /* right */,
+ centerY + radius /* bottom */
+ )
+ }
+}
+
class PowerButtonReveal(
/** Approximate Y-value of the center of the power button on the physical device. */
val powerButtonY: Float
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index e119907..3daa2b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -132,6 +132,7 @@
mHiddenShelfIconSize = res.getDimensionPixelOffset(R.dimen.hidden_shelf_icon_size);
mGapHeight = res.getDimensionPixelSize(R.dimen.qs_notification_padding);
+ mShelfIcons.setInNotificationIconShelf(true);
if (!mShowNotificationShelf) {
setVisibility(GONE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/ChargingRippleView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/ChargingRippleView.kt
new file mode 100644
index 0000000..6f80317
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/ChargingRippleView.kt
@@ -0,0 +1,86 @@
+/*
+ * 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 com.android.systemui.statusbar.charging
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ValueAnimator
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.PointF
+import android.util.AttributeSet
+import android.view.View
+import kotlin.math.max
+
+private const val RIPPLE_ANIMATION_DURATION: Long = 1500
+private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
+
+/**
+ * Expanding ripple effect that shows when charging begins.
+ */
+class ChargingRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
+ private var rippleInProgress: Boolean = false
+ private val rippleShader = RippleShader()
+ private val defaultColor: Int = 0xffffffff.toInt()
+ private val ripplePaint = Paint()
+
+ init {
+ rippleShader.color = defaultColor
+ rippleShader.progress = 0f
+ rippleShader.sparkleStrength = RIPPLE_SPARKLE_STRENGTH
+ ripplePaint.shader = rippleShader
+ }
+
+ override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+ rippleShader.origin = PointF(measuredWidth / 2f, measuredHeight.toFloat())
+ rippleShader.radius = max(measuredWidth, measuredHeight).toFloat()
+ super.onLayout(changed, left, top, right, bottom)
+ }
+
+ fun startRipple() {
+ if (rippleInProgress) {
+ return // Ignore if ripple effect is already playing
+ }
+ val animator = ValueAnimator.ofFloat(0f, 1f)
+ animator.duration = RIPPLE_ANIMATION_DURATION
+ animator.addUpdateListener { animator ->
+ val now = animator.currentPlayTime
+ val phase = now / 30000f
+ rippleShader.progress = animator.animatedValue as Float
+ rippleShader.noisePhase = phase
+ invalidate()
+ }
+ animator.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ rippleInProgress = false
+ visibility = View.GONE
+ }
+ })
+ animator.start()
+ visibility = View.VISIBLE
+ rippleInProgress = true
+ }
+
+ fun setColor(color: Int) {
+ rippleShader.color = color
+ }
+
+ override fun onDraw(canvas: Canvas?) {
+ canvas?.drawRect(0f, 0f, width.toFloat(), height.toFloat(), ripplePaint)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt
new file mode 100644
index 0000000..5547c1e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt
@@ -0,0 +1,147 @@
+/*
+ * 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 com.android.systemui.statusbar.charging
+
+import android.graphics.Color
+import android.graphics.PointF
+import android.graphics.RuntimeShader
+
+/**
+ * Shader class that renders an expanding charging ripple effect. A charging ripple contains
+ * three elements:
+ * 1. an expanding filled circle that appears in the beginning and quickly fades away
+ * 2. an expanding ring that appears throughout the effect
+ * 3. an expanding ring-shaped area that reveals noise over #2.
+ *
+ * Modeled after frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java.
+ */
+class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
+ companion object {
+ private const val SHADER_UNIFORMS = """uniform vec2 in_origin;
+ uniform float in_progress;
+ uniform float in_maxRadius;
+ uniform float in_noisePhase;
+ uniform vec4 in_color;
+ uniform float in_sparkle_strength;"""
+ private const val SHADER_LIB = """float triangleNoise(vec2 n) {
+ n = fract(n * vec2(5.3987, 5.4421));
+ n += dot(n.yx, n.xy + vec2(21.5351, 14.3137));
+ float xy = n.x * n.y;
+ return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
+ }
+ const float PI = 3.1415926535897932384626;
+
+ float threshold(float v, float l, float h) {
+ return step(l, v) * (1.0 - step(h, v));
+ }
+
+ float sparkles(vec2 uv, float t) {
+ float n = triangleNoise(uv);
+ float s = 0.0;
+ for (float i = 0; i < 4; i += 1) {
+ float l = i * 0.25;
+ float h = l + 0.025;
+ float o = abs(sin(0.1 * PI * (t + i)));
+ s += threshold(n + o, l, h);
+ }
+ return saturate(s);
+ }
+
+ float softCircle(vec2 uv, vec2 xy, float radius, float blur) {
+ float blurHalf = blur * 0.5;
+ float d = distance(uv, xy);
+ return 1. - smoothstep(1. - blurHalf, 1. + blurHalf, d / radius);
+ }
+
+ float softRing(vec2 uv, vec2 xy, float radius, float blur) {
+ float thickness = 0.4;
+ float circle_outer = softCircle(uv, xy,
+ radius + thickness * radius * 0.5, blur);
+ float circle_inner = softCircle(uv, xy,
+ radius - thickness * radius * 0.5, blur);
+ return circle_outer - circle_inner;
+ }
+
+ float subProgress(float start, float end, float progress) {
+ float sub = clamp(progress, start, end);
+ return (sub - start) / (end - start);
+ }
+
+ float smoothstop2(float t) {
+ return 1 - (1 - t) * (1 - t);
+ }"""
+ private const val SHADER_MAIN = """vec4 main(vec2 p) {
+ float fadeIn = subProgress(0., 0.1, in_progress);
+ float fadeOutNoise = subProgress(0.8, 1., in_progress);
+ float fadeOutRipple = subProgress(0.7, 1., in_progress);
+ float fadeCircle = subProgress(0., 0.5, in_progress);
+ float radius = smoothstop2(in_progress) * in_maxRadius;
+ float sparkleRing = softRing(p, in_origin, radius, 0.5);
+ float sparkleAlpha = min(fadeIn, 1. - fadeOutNoise);
+ float sparkle = sparkles(p, in_noisePhase) * sparkleRing * sparkleAlpha;
+ float circle = softCircle(p, in_origin, radius * 1.2, 0.5)
+ * (1 - fadeCircle);
+ float fadeRipple = min(fadeIn, 1.-fadeOutRipple);
+ float rippleAlpha = softRing(p, in_origin, radius, 0.5)
+ * fadeRipple * in_color.a;
+ vec4 ripple = in_color * max(circle, rippleAlpha) * 0.4;
+ return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
+ }"""
+ private const val SHADER = SHADER_UNIFORMS + SHADER_LIB + SHADER_MAIN
+ }
+
+ /**
+ * Maximum radius of the ripple.
+ */
+ var radius: Float = 0.0f
+ set(value) { setUniform("in_maxRadius", value) }
+
+ /**
+ * Origin coordinate of the ripple.
+ */
+ var origin: PointF = PointF()
+ set(value) { setUniform("in_origin", floatArrayOf(value.x, value.y)) }
+
+ /**
+ * Progress of the ripple. Float value between [0, 1].
+ */
+ var progress: Float = 0.0f
+ set(value) { setUniform("in_progress", value) }
+
+ /**
+ * Continuous offset used as noise phase.
+ */
+ var noisePhase: Float = 0.0f
+ set(value) { setUniform("in_noisePhase", value) }
+
+ /**
+ * A hex value representing the ripple color, in the format of ARGB
+ */
+ var color: Int = 0xffffff.toInt()
+ set(value) {
+ val color = Color.valueOf(value)
+ setUniform("in_color", floatArrayOf(color.red(),
+ color.green(), color.blue(), color.alpha()))
+ }
+
+ /**
+ * Noise sparkle intensity. Expected value between [0, 1]. The sparkle is white, and thus
+ * with strength 0 it's transparent, leaving the ripple fully smooth, while with strength 1
+ * it's opaque white and looks the most grainy.
+ */
+ var sparkleStrength: Float = 0.0f
+ set(value) { setUniform("in_sparkle_strength", value) }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt
new file mode 100644
index 0000000..b567ad4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt
@@ -0,0 +1,137 @@
+/*
+ * 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 com.android.systemui.statusbar.charging
+
+import android.content.Context
+import android.content.res.Configuration
+import android.util.DisplayMetrics
+import android.view.View
+import android.view.ViewGroupOverlay
+import com.android.internal.annotations.VisibleForTesting
+import com.android.settingslib.Utils
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.FeatureFlags
+import com.android.systemui.statusbar.commandline.Command
+import com.android.systemui.statusbar.commandline.CommandRegistry
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import java.io.PrintWriter
+import javax.inject.Inject
+
+/***
+ * Controls the ripple effect that shows when wired charging begins.
+ * The ripple uses the accent color of the current theme.
+ */
+@SysUISingleton
+class WiredChargingRippleController @Inject constructor(
+ commandRegistry: CommandRegistry,
+ batteryController: BatteryController,
+ configurationController: ConfigurationController,
+ featureFlags: FeatureFlags,
+ private val context: Context,
+ private val keyguardStateController: KeyguardStateController
+) {
+ private var pluggedIn: Boolean? = null
+ private val rippleEnabled: Boolean = featureFlags.isChargingRippleEnabled
+ @VisibleForTesting
+ var rippleView: ChargingRippleView = ChargingRippleView(context, attrs = null)
+
+ init {
+ val batteryStateChangeCallback = object : BatteryController.BatteryStateChangeCallback {
+ override fun onBatteryLevelChanged(
+ level: Int,
+ nowPluggedIn: Boolean,
+ charging: Boolean
+ ) {
+ if (!rippleEnabled) {
+ return
+ }
+ val wasPluggedIn = pluggedIn
+ pluggedIn = nowPluggedIn
+ // Only triggers when the keyguard is active and the device is just plugged in.
+ if (wasPluggedIn == false && nowPluggedIn && keyguardStateController.isShowing) {
+ rippleView.startRipple()
+ }
+ }
+ }
+ batteryController.addCallback(batteryStateChangeCallback)
+
+ val configurationChangedListener = object : ConfigurationController.ConfigurationListener {
+ override fun onUiModeChanged() {
+ updateRippleColor()
+ }
+ override fun onThemeChanged() {
+ updateRippleColor()
+ }
+ override fun onOverlayChanged() {
+ updateRippleColor()
+ }
+ override fun onConfigChanged(newConfig: Configuration?) {
+ layoutRippleView()
+ }
+ }
+ configurationController.addCallback(configurationChangedListener)
+
+ commandRegistry.registerCommand("charging-ripple") { ChargingRippleCommand() }
+ }
+
+ fun setViewHost(viewHost: View) {
+ // Add the ripple view as an overlay of the root view so that it always
+ // shows on top.
+ viewHost.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
+ override fun onViewDetachedFromWindow(view: View?) {}
+
+ override fun onViewAttachedToWindow(view: View?) {
+ (viewHost.viewRootImpl.view.overlay as ViewGroupOverlay).add(rippleView)
+ layoutRippleView()
+ viewHost.removeOnAttachStateChangeListener(this)
+ }
+ })
+
+ updateRippleColor()
+ }
+
+ private fun layoutRippleView() {
+ // Overlays are not auto measured and laid out so we do it manually here.
+ val displayMetrics = DisplayMetrics()
+ context.display.getRealMetrics(displayMetrics)
+ val width = displayMetrics.widthPixels
+ val height = displayMetrics.heightPixels
+ if (width != rippleView.width || height != rippleView.height) {
+ rippleView.measure(
+ View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY))
+ rippleView.layout(0, 0, width, height)
+ }
+ }
+
+ private fun updateRippleColor() {
+ rippleView.setColor(
+ Utils.getColorAttr(context, android.R.attr.colorAccent).defaultColor)
+ }
+
+ inner class ChargingRippleCommand : Command {
+ override fun execute(pw: PrintWriter, args: List<String>) {
+ rippleView.startRipple()
+ }
+
+ override fun help(pw: PrintWriter) {
+ pw.println("Usage: adb shell cmd statusbar charging-ripple")
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index dff97a6..fd5128a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification.init
import android.content.Context
-import android.provider.Settings
import android.service.notification.StatusBarNotification
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.people.widget.PeopleSpaceWidgetManager
@@ -132,11 +131,7 @@
entryManager.attach(notificationListener)
}
- val showPeopleSpace = Settings.Global.getInt(context.contentResolver,
- Settings.Global.SHOW_PEOPLE_SPACE, 1)
- if (showPeopleSpace == 1) {
- peopleSpaceWidgetManager.attach(notificationListener)
- }
+ peopleSpaceWidgetManager.attach(notificationListener)
}
override fun dump(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 6b144c6..25de551 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -152,6 +152,7 @@
private boolean mDozing;
private boolean mOnLockScreen;
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
+ private boolean mInNotificationIconShelf;
private boolean mChangingViewPositions;
private int mAddAnimationStartIndex = -1;
private int mCannedAnimationStartIndex = -1;
@@ -702,6 +703,10 @@
mLockScreenMode = lockScreenMode;
}
+ public void setInNotificationIconShelf(boolean inShelf) {
+ mInNotificationIconShelf = inShelf;
+ }
+
public class IconState extends ViewState {
public static final int NO_VALUE = NotificationIconContainer.NO_VALUE;
public float iconAppearAmount = 1.0f;
@@ -813,7 +818,7 @@
}
}
icon.setVisibleState(visibleState, animationsAllowed);
- icon.setIconColor(mThemedTextColorPrimary,
+ icon.setIconColor(mInNotificationIconShelf ? mThemedTextColorPrimary : iconColor,
needsCannedAnimation && animationsAllowed);
if (animate) {
animateTo(icon, animationProperties);
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 6dd00a5..0e1fe22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -22,6 +22,7 @@
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -46,6 +47,7 @@
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import static com.android.wm.shell.bubbles.BubbleController.TASKBAR_CHANGED_BROADCAST;
+import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -74,6 +76,7 @@
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.RectF;
import android.media.AudioAttributes;
import android.metrics.LogMaker;
import android.net.Uri;
@@ -179,6 +182,7 @@
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.BackDropView;
+import com.android.systemui.statusbar.CircleReveal;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.FeatureFlags;
@@ -202,6 +206,8 @@
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.charging.ChargingRippleView;
+import com.android.systemui.statusbar.charging.WiredChargingRippleController;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
@@ -377,7 +383,11 @@
private boolean mWakeUpComingFromTouch;
private PointF mWakeUpTouchLocation;
private LightRevealScrim mLightRevealScrim;
+ private ChargingRippleView mChargingRipple;
+ private WiredChargingRippleController mChargingRippleAnimationController;
private PowerButtonReveal mPowerButtonReveal;
+ private CircleReveal mCircleReveal;
+ private ValueAnimator mCircleRevealAnimator = ValueAnimator.ofFloat(0f, 1f);
private final Object mQueueLock = new Object();
@@ -777,6 +787,7 @@
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
NotificationIconAreaController notificationIconAreaController,
BrightnessSlider.Factory brightnessSliderFactory,
+ WiredChargingRippleController chargingRippleAnimationController,
FeatureFlags featureFlags) {
super(context);
mNotificationsController = notificationsController;
@@ -855,6 +866,7 @@
mDemoModeController = demoModeController;
mNotificationIconAreaController = notificationIconAreaController;
mBrightnessSliderFactory = brightnessSliderFactory;
+ mChargingRippleAnimationController = chargingRippleAnimationController;
mFeatureFlags = featureFlags;
mExpansionChangedListeners = new ArrayList<>();
@@ -1198,8 +1210,11 @@
mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble);
mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
+ mChargingRippleAnimationController.setViewHost(mNotificationShadeWindowView);
- if (mFeatureFlags.useNewLockscreenAnimations() && mDozeParameters.getAlwaysOn()) {
+
+ if (mFeatureFlags.useNewLockscreenAnimations()
+ && (mDozeParameters.getAlwaysOn() || mDozeParameters.isQuickPickupEnabled())) {
mLightRevealScrim.setVisibility(View.VISIBLE);
mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
} else {
@@ -3346,6 +3361,9 @@
mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
()-> {
hideKeyguard();
+ if (shouldShowCircleReveal()) {
+ startCircleReveal();
+ }
mStatusBarKeyguardViewManager.onKeyguardFadedAway();
}).start();
}
@@ -3659,15 +3677,16 @@
updateQsExpansionEnabled();
mKeyguardViewMediator.setDozing(mDozing);
- final boolean usePowerButtonEffect =
- (isDozing && mWakefulnessLifecycle.getLastSleepReason()
- == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
- || (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
- == PowerManager.WAKE_REASON_POWER_BUTTON);
-
- mLightRevealScrim.setRevealEffect(usePowerButtonEffect
- ? mPowerButtonReveal
- : LiftReveal.INSTANCE);
+ if (!isDozing && shouldShowCircleReveal()) {
+ startCircleReveal();
+ } else if ((isDozing && mWakefulnessLifecycle.getLastSleepReason()
+ == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
+ || (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
+ == PowerManager.WAKE_REASON_POWER_BUTTON)) {
+ mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
+ } else if (!mCircleRevealAnimator.isRunning()) {
+ mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
+ }
mNotificationsController.requestNotificationUpdate("onDozingChanged");
updateDozingState();
@@ -3677,6 +3696,22 @@
Trace.endSection();
}
+ private void startCircleReveal() {
+ mLightRevealScrim.setRevealEffect(mCircleReveal);
+ mCircleRevealAnimator.cancel();
+ mCircleRevealAnimator.addUpdateListener(animation ->
+ mLightRevealScrim.setRevealAmount(
+ (float) mCircleRevealAnimator.getAnimatedValue()));
+ mCircleRevealAnimator.setDuration(900);
+ mCircleRevealAnimator.start();
+ }
+
+ private boolean shouldShowCircleReveal() {
+ return mCircleReveal != null && !mCircleRevealAnimator.isRunning()
+ && mKeyguardUpdateMonitor.isUdfpsEnrolled()
+ && mBiometricUnlockController.getBiometricType() == FINGERPRINT;
+ }
+
private void updateKeyguardState() {
mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
mStatusBarKeyguardViewManager.isOccluded());
@@ -4163,6 +4198,15 @@
mBiometricUnlockController.getBiometricType());
}
+ /**
+ * Set the location of the sensor on UDFPS if existent.
+ */
+ public void setSensorRect(RectF rect) {
+ final float startRadius = (rect.right - rect.left) / 2f;
+ mCircleReveal = new CircleReveal(rect.centerX(), rect.centerY(),
+ startRadius, rect.centerY() - startRadius);
+ }
+
@VisibleForTesting
public void updateScrimController() {
Trace.beginSection("StatusBar#updateScrimController");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 8620376..8fe9a48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -66,7 +66,11 @@
/**
* Display the no calling & SMS icons.
*/
- void setCallIndicatorIcons(String slot, List<CallIndicatorIconState> states);
+ void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states);
+ /**
+ * Display the no calling & SMS icons.
+ */
+ void setNoCallingIcons(String slot, List<CallIndicatorIconState> states);
public void setIconVisibility(String slot, boolean b);
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index f0c8527..6404aea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -219,27 +219,56 @@
}
/**
- * Accept a list of CallIndicatorIconStates, and show them in the same slot
- * @param slot StatusBar slot
+ * Accept a list of CallIndicatorIconStates, and show the call strength icons.
+ * @param slot StatusBar slot for the call strength icons
* @param states All of the no Calling & SMS icon states
*/
@Override
- public void setCallIndicatorIcons(String slot, List<CallIndicatorIconState> states) {
- Slot noCallingSlot = getSlot(slot);
- int slotIndex = getSlotIndex(slot);
+ public void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states) {
+ Slot callStrengthSlot = getSlot(slot);
+ int callStrengthSlotIndex = getSlotIndex(slot);
+ Collections.reverse(states);
for (CallIndicatorIconState state : states) {
- StatusBarIconHolder holder = noCallingSlot.getHolderForTag(state.subId);
- if (holder == null) {
- holder = StatusBarIconHolder.fromCallIndicatorState(mContext, state);
- setIcon(slotIndex, holder);
- } else {
- int resId = state.isNoCalling ? state.noCallingResId : state.callStrengthResId;
- String contentDescription = state.isNoCalling
- ? state.noCallingDescription : state.callStrengthDescription;
- holder.setIcon(new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
- Icon.createWithResource(mContext, resId), 0, 0, contentDescription));
- setIcon(slotIndex, holder);
+ if (!state.isNoCalling) {
+ StatusBarIconHolder holder = callStrengthSlot.getHolderForTag(state.subId);
+ if (holder == null) {
+ holder = StatusBarIconHolder.fromCallIndicatorState(mContext, state);
+ setIcon(callStrengthSlotIndex, holder);
+ } else {
+ holder.setIcon(new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
+ Icon.createWithResource(mContext, state.callStrengthResId), 0, 0,
+ state.callStrengthDescription));
+ setIcon(callStrengthSlotIndex, holder);
+ }
}
+ setIconVisibility(slot, !state.isNoCalling, state.subId);
+ }
+ }
+
+ /**
+ * Accept a list of CallIndicatorIconStates, and show the no calling icons.
+ * @param slot StatusBar slot for the no calling icons
+ * @param states All of the no Calling & SMS icon states
+ */
+ @Override
+ public void setNoCallingIcons(String slot, List<CallIndicatorIconState> states) {
+ Slot noCallingSlot = getSlot(slot);
+ int noCallingSlotIndex = getSlotIndex(slot);
+ Collections.reverse(states);
+ for (CallIndicatorIconState state : states) {
+ if (state.isNoCalling) {
+ StatusBarIconHolder holder = noCallingSlot.getHolderForTag(state.subId);
+ if (holder == null) {
+ holder = StatusBarIconHolder.fromCallIndicatorState(mContext, state);
+ setIcon(noCallingSlotIndex, holder);
+ } else {
+ holder.setIcon(new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
+ Icon.createWithResource(mContext, state.noCallingResId), 0, 0,
+ state.noCallingDescription));
+ setIcon(noCallingSlotIndex, holder);
+ }
+ }
+ setIconVisibility(slot, state.isNoCalling, state.subId);
}
}
@@ -282,9 +311,15 @@
}
}
+ /** */
public void setIconVisibility(String slot, boolean visibility) {
+ setIconVisibility(slot, visibility, 0);
+ }
+
+ /** */
+ public void setIconVisibility(String slot, boolean visibility, int tag) {
int index = getSlotIndex(slot);
- StatusBarIconHolder holder = getIcon(index, 0);
+ StatusBarIconHolder holder = getIcon(index, tag);
if (holder == null || holder.isVisible() == visibility) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index a1a2d30..19db02a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -83,7 +83,6 @@
holder.mIcon = new StatusBarIcon(UserHandle.SYSTEM, context.getPackageName(),
Icon.createWithResource(context, resId), 0, 0, contentDescription);
holder.mTag = state.subId;
- holder.setVisible(true);
return holder;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 9ee7b09..3445826 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -50,6 +50,7 @@
private final String mSlotEthernet;
private final String mSlotVpn;
private final String mSlotNoCalling;
+ private final String mSlotCallStrength;
private final Context mContext;
private final StatusBarIconController mIconController;
@@ -83,6 +84,8 @@
mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet);
mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn);
mSlotNoCalling = mContext.getString(com.android.internal.R.string.status_bar_no_calling);
+ mSlotCallStrength =
+ mContext.getString(com.android.internal.R.string.status_bar_call_strength);
mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
mIconController = iconController;
@@ -212,8 +215,10 @@
state.callStrengthResId = statusIcon.icon;
state.callStrengthDescription = statusIcon.contentDescription;
}
- mIconController.setCallIndicatorIcons(
- mSlotNoCalling, CallIndicatorIconState.copyStates(mCallIndicatorStates));
+ mIconController.setCallStrengthIcons(mSlotCallStrength,
+ CallIndicatorIconState.copyStates(mCallIndicatorStates));
+ mIconController.setNoCallingIcons(mSlotNoCalling,
+ CallIndicatorIconState.copyStates(mCallIndicatorStates));
}
@Override
@@ -300,6 +305,7 @@
mIconController.removeAllIconsForSlot(mSlotMobile);
mIconController.removeAllIconsForSlot(mSlotNoCalling);
+ mIconController.removeAllIconsForSlot(mSlotCallStrength);
mMobileStates.clear();
List<CallIndicatorIconState> noCallingStates = new ArrayList<CallIndicatorIconState>();
noCallingStates.addAll(mCallIndicatorStates);
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 17bb449..4f32712 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
@@ -60,6 +60,7 @@
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.charging.WiredChargingRippleController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
@@ -204,6 +205,7 @@
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
NotificationIconAreaController notificationIconAreaController,
BrightnessSlider.Factory brightnessSliderFactory,
+ WiredChargingRippleController chargingRippleAnimationController,
FeatureFlags featureFlags) {
return new StatusBar(
context,
@@ -285,6 +287,7 @@
statusBarTouchableRegionManager,
notificationIconAreaController,
brightnessSliderFactory,
+ chargingRippleAnimationController,
featureFlags);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 3f4ec85..ddfa63a 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -81,7 +81,7 @@
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.startingsurface.StartingWindowController;
-import com.android.wm.shell.transition.RemoteTransitions;
+import com.android.wm.shell.transition.ShellTransitions;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -399,8 +399,8 @@
@WMSingleton
@Provides
- static RemoteTransitions provideRemoteTransitions(Transitions transitions) {
- return Transitions.asRemoteTransitions(transitions);
+ static ShellTransitions provideRemoteTransitions(Transitions transitions) {
+ return transitions.asRemoteTransitions();
}
@WMSingleton
@@ -509,27 +509,33 @@
@WMSingleton
@Provides
- static ShellInit provideShellInit(DisplayImeController displayImeController,
+ static ShellInit provideShellInit(ShellInitImpl impl) {
+ return impl.asShellInit();
+ }
+
+ @WMSingleton
+ @Provides
+ static ShellInitImpl provideShellInitImpl(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
- Optional<StartingSurface> startingSurface,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
+ StartingWindowController startingWindow,
@ShellMainThread ShellExecutor mainExecutor) {
- return ShellInitImpl.create(displayImeController,
+ return new ShellInitImpl(displayImeController,
dragAndDropController,
shellTaskOrganizer,
legacySplitScreenOptional,
splitScreenOptional,
appPairsOptional,
- startingSurface,
pipTouchHandlerOptional,
fullscreenTaskListener,
transitions,
+ startingWindow,
mainExecutor);
}
@@ -539,7 +545,13 @@
*/
@WMSingleton
@Provides
- static Optional<ShellCommandHandler> provideShellCommandHandler(
+ static Optional<ShellCommandHandler> provideShellCommandHandler(ShellCommandHandlerImpl impl) {
+ return Optional.of(impl.asShellCommandHandler());
+ }
+
+ @WMSingleton
+ @Provides
+ static ShellCommandHandlerImpl provideShellCommandHandlerImpl(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
@@ -548,8 +560,8 @@
Optional<HideDisplayCutoutController> hideDisplayCutout,
Optional<AppPairsController> appPairsOptional,
@ShellMainThread ShellExecutor mainExecutor) {
- return Optional.of(ShellCommandHandlerImpl.create(shellTaskOrganizer,
+ return new ShellCommandHandlerImpl(shellTaskOrganizer,
legacySplitScreenOptional, splitScreenOptional, pipOptional, oneHandedOptional,
- hideDisplayCutout, appPairsOptional, mainExecutor));
+ hideDisplayCutout, appPairsOptional, mainExecutor);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
index 9185cd6..ee98a59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -67,7 +67,6 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.ContactsContract;
-import android.provider.Settings;
import android.service.notification.ConversationChannelWrapper;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
@@ -234,8 +233,6 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
mOptions = new Bundle();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index 5834aef..7090e78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -60,7 +60,6 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
-import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
@@ -176,9 +175,6 @@
verify(mListenerService).addNotificationHandler(mListenerCaptor.capture());
NotificationHandler serviceListener = requireNonNull(mListenerCaptor.getValue());
mNoMan.addListener(serviceListener);
- // Default to single People tile widgets.
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
clearStorage();
setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
@@ -304,8 +300,6 @@
@Test
public void testDoNotUpdateNotificationPostedIfDifferentPackageName() throws Exception {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
index 6032e51..9799514 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
@@ -30,8 +30,8 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
@@ -99,7 +99,7 @@
assertEquals(Tile.STATE_INACTIVE, mTile.getState().state);
assertEquals(mTile.getState().label.toString(),
- mContext.getString(R.string.quick_settings_reduce_bright_colors_label));
+ mContext.getString(R.string.reduce_bright_colors_feature_name));
}
@Test
@@ -110,7 +110,7 @@
assertEquals(Tile.STATE_ACTIVE, mTile.getState().state);
assertEquals(mTile.getState().label.toString(),
- mContext.getString(R.string.quick_settings_reduce_bright_colors_label));
+ mContext.getString(R.string.reduce_bright_colors_feature_name));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
deleted file mode 100644
index 25104b8..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.pm.PackageManager;
-import android.os.RemoteException;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableContext;
-import android.testing.TestableLooper;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
-import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
-import com.android.wm.shell.startingsurface.StartingSurface;
-import com.android.wm.shell.transition.RemoteTransitions;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Optional;
-
-import dagger.Lazy;
-
-/**
- * Unit tests for {@link com.android.systemui.recents.OverviewProxyService}
- */
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class OverviewProxyServiceTest extends SysuiTestCase {
- private OverviewProxyService mSpiedOverviewProxyService;
- private TestableContext mSpiedContext;
-
- @Mock private BroadcastDispatcher mMockBroadcastDispatcher;
- @Mock private CommandQueue mMockCommandQueue;
- @Mock private Lazy<NavigationBarController> mMockNavBarControllerLazy;
- @Mock private IPinnedStackAnimationListener mMockPinnedStackAnimationListener;
- @Mock private NavigationModeController mMockNavModeController;
- @Mock private NotificationShadeWindowController mMockStatusBarWinController;
- @Mock private Optional<Pip> mMockPipOptional;
- @Mock private Optional<LegacySplitScreen> mMockLegacySplitScreenOptional;
- @Mock private Optional<SplitScreen> mMockSplitScreenOptional;
- @Mock private Optional<Lazy<StatusBar>> mMockStatusBarOptionalLazy;
- @Mock private Optional<com.android.wm.shell.onehanded.OneHanded> mMockOneHandedOptional;
- @Mock private PackageManager mPackageManager;
- @Mock private SysUiState mMockSysUiState;
- @Mock private RemoteTransitions mMockTransitions;
- @Mock private Optional<StartingSurface> mStartingSurface;
-
- @Before
- public void setUp() throws RemoteException {
- MockitoAnnotations.initMocks(this);
-
- mSpiedContext = spy(mContext);
-
- when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false);
- when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager);
-
- mSpiedOverviewProxyService = spy(new OverviewProxyService(mSpiedContext, mMockCommandQueue,
- mMockNavBarControllerLazy, mMockNavModeController, mMockStatusBarWinController,
- mMockSysUiState, mMockPipOptional, mMockLegacySplitScreenOptional,
- mMockSplitScreenOptional, mMockStatusBarOptionalLazy, mMockOneHandedOptional,
- mMockBroadcastDispatcher, mMockTransitions, mStartingSurface));
- }
-
- @Test
- public void testNonPipDevice_shouldNotNotifySwipeToHomeFinished() throws RemoteException {
- mSpiedOverviewProxyService.mSysUiProxy.notifySwipeToHomeFinished();
-
- verify(mMockPipOptional, never()).ifPresent(any());
- }
-
- @Test
- public void testNonPipDevice_shouldNotSetPinnedStackAnimationListener() throws RemoteException {
- mSpiedOverviewProxyService.mSysUiProxy.setPinnedStackAnimationListener(
- mMockPinnedStackAnimationListener);
-
- verify(mMockPipOptional, never()).ifPresent(any());
- }
-
- @Test
- public void testNonPipDevice_shouldNotSetShelfHeight() throws RemoteException {
- mSpiedOverviewProxyService.mSysUiProxy.setShelfHeight(true /* visible */,
- 100 /* shelfHeight */);
-
- verify(mMockPipOptional, never()).ifPresent(any());
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt
new file mode 100644
index 0000000..3701b91
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt
@@ -0,0 +1,115 @@
+/*
+ * 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 com.android.systemui.statusbar.charging
+
+import android.testing.AndroidTestingRunner
+import android.view.View
+import android.view.ViewGroupOverlay
+import android.view.ViewRootImpl
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.FeatureFlags
+import com.android.systemui.statusbar.commandline.CommandRegistry
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class WiredChargingRippleControllerTest : SysuiTestCase() {
+ private lateinit var controller: WiredChargingRippleController
+ @Mock private lateinit var commandRegistry: CommandRegistry
+ @Mock private lateinit var batteryController: BatteryController
+ @Mock private lateinit var featureFlags: FeatureFlags
+ @Mock private lateinit var configurationController: ConfigurationController
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var rippleView: ChargingRippleView
+ @Mock private lateinit var viewHost: View
+ @Mock private lateinit var viewHostRootImpl: ViewRootImpl
+ @Mock private lateinit var viewGroupOverlay: ViewGroupOverlay
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ `when`(viewHost.viewRootImpl).thenReturn(viewHostRootImpl)
+ `when`(viewHostRootImpl.view).thenReturn(viewHost)
+ `when`(viewHost.overlay).thenReturn(viewGroupOverlay)
+ `when`(featureFlags.isChargingRippleEnabled).thenReturn(true)
+ `when`(keyguardStateController.isShowing).thenReturn(true)
+ controller = WiredChargingRippleController(
+ commandRegistry, batteryController, configurationController,
+ featureFlags, context, keyguardStateController)
+ controller.rippleView = rippleView // Replace the real ripple view with a mock instance
+ controller.setViewHost(viewHost)
+ }
+
+ @Test
+ fun testSetRippleViewAsOverlay() {
+ val listenerCaptor = ArgumentCaptor.forClass(View.OnAttachStateChangeListener::class.java)
+ verify(viewHost).addOnAttachStateChangeListener(listenerCaptor.capture())
+
+ // Fake attach to window
+ listenerCaptor.value.onViewAttachedToWindow(viewHost)
+ verify(viewGroupOverlay).add(rippleView)
+ }
+
+ @Test
+ fun testTriggerRipple() {
+ val captor = ArgumentCaptor
+ .forClass(BatteryController.BatteryStateChangeCallback::class.java)
+ verify(batteryController).addCallback(captor.capture())
+
+ val unusedBatteryLevel = 0
+ captor.value.onBatteryLevelChanged(
+ unusedBatteryLevel,
+ false /* plugged in */,
+ false /* charging */)
+ verify(rippleView, never()).startRipple()
+
+ captor.value.onBatteryLevelChanged(
+ unusedBatteryLevel,
+ true /* plugged in */,
+ false /* charging */)
+ verify(rippleView).startRipple()
+ }
+
+ @Test
+ fun testUpdateRippleColor() {
+ val captor = ArgumentCaptor
+ .forClass(ConfigurationController.ConfigurationListener::class.java)
+ verify(configurationController).addCallback(captor.capture())
+
+ reset(rippleView)
+ captor.value.onThemeChanged()
+ verify(rippleView).setColor(ArgumentMatchers.anyInt())
+
+ reset(rippleView)
+ captor.value.onUiModeChanged()
+ verify(rippleView).setColor(ArgumentMatchers.anyInt())
+ }
+}
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 0b454bf..781cde6c 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
@@ -113,6 +113,7 @@
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.charging.WiredChargingRippleController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -261,6 +262,7 @@
@Mock private DemoModeController mDemoModeController;
@Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
@Mock private BrightnessSlider.Factory mBrightnessSliderFactory;
+ @Mock private WiredChargingRippleController mWiredChargingRippleController;
@Mock private FeatureFlags mFeatureFlags;
private ShadeController mShadeController;
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -424,6 +426,7 @@
mStatusBarTouchableRegionManager,
mNotificationIconAreaController,
mBrightnessSliderFactory,
+ mWiredChargingRippleController,
mFeatureFlags);
when(mNotificationShadeWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
index 203ece9..8ad6271 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -66,7 +66,11 @@
}
@Override
- public void setCallIndicatorIcons(String slot, List<CallIndicatorIconState> states) {
+ public void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states) {
+ }
+
+ @Override
+ public void setNoCallingIcons(String slot, List<CallIndicatorIconState> states) {
}
@Override
diff --git a/services/api/Android.bp b/services/api/Android.bp
index b8ca548..bbc8c72 100644
--- a/services/api/Android.bp
+++ b/services/api/Android.bp
@@ -14,6 +14,12 @@
package {
default_visibility: ["//visibility:private"],
+ // 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"],
}
filegroup {
@@ -26,4 +32,4 @@
name: "non-updatable-system-server-removed.txt",
srcs: ["non-updatable-removed.txt"],
visibility: ["//frameworks/base/api"],
-}
\ No newline at end of file
+}
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index b089014..c295778 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1141,12 +1141,4 @@
*/
public abstract boolean isPackageFrozen(
@NonNull String packageName, int callingUid, int userId);
-
- /**
- * Returns true if the given {@code packageName} has declared the
- * {@code neverForLocation} flag in the {@code uses-permission} manifest tag
- * where they request the given {@code permissionName}.
- */
- public abstract boolean isPackageUsesPermissionNeverForLocation(@NonNull String packageName,
- @NonNull String permissionName);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 512cc72..0515eca 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -107,6 +107,7 @@
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivityManager.RestrictBackgroundStatus;
+import android.net.ConnectivityResources;
import android.net.ConnectivitySettingsManager;
import android.net.DataStallReportParcelable;
import android.net.DnsResolverServiceManager;
@@ -116,6 +117,7 @@
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.INetworkActivityListener;
+import android.net.INetworkAgent;
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
import android.net.IOnCompleteListener;
@@ -165,7 +167,6 @@
import android.net.Uri;
import android.net.VpnManager;
import android.net.VpnTransportInfo;
-import android.net.ConnectivityResources;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.netlink.InetDiagMessage;
@@ -210,7 +211,6 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
-import com.android.connectivity.aidl.INetworkAgent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
@@ -238,7 +238,6 @@
import com.android.server.connectivity.ProfileNetworkPreferences;
import com.android.server.connectivity.ProxyTracker;
import com.android.server.connectivity.QosCallbackTracker;
-import com.android.server.net.NetworkPolicyManagerInternal;
import libcore.io.IoUtils;
@@ -351,7 +350,6 @@
protected INetd mNetd;
private NetworkStatsManager mStatsManager;
private NetworkPolicyManager mPolicyManager;
- private NetworkPolicyManagerInternal mPolicyManagerInternal;
private final NetdCallback mNetdCallback;
/**
@@ -1238,9 +1236,6 @@
mStatsManager = mContext.getSystemService(NetworkStatsManager.class);
mPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
- mPolicyManagerInternal = Objects.requireNonNull(
- LocalServices.getService(NetworkPolicyManagerInternal.class),
- "missing NetworkPolicyManagerInternal");
mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver");
mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);
@@ -1340,7 +1335,7 @@
netCap.addCapability(NET_CAPABILITY_INTERNET);
netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
- netCap.setUids(Collections.singleton(uids));
+ netCap.setUids(UidRange.toIntRanges(Collections.singleton(uids)));
return netCap;
}
@@ -1781,7 +1776,7 @@
}
// No need to check mLockdownEnabled. If it's true, getVpnUnderlyingNetworks returns null.
- final Network[] networks = getVpnUnderlyingNetworks(Binder.getCallingUid());
+ final Network[] networks = getVpnUnderlyingNetworks(mDeps.getCallingUid());
if (null != networks) {
for (final Network network : networks) {
final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network);
@@ -2873,7 +2868,7 @@
if (0 == defaultRequest.mRequests.size()) {
pw.println("none, this should never occur.");
} else {
- pw.println(defaultRequest.mRequests.get(0).networkCapabilities.getUids());
+ pw.println(defaultRequest.mRequests.get(0).networkCapabilities.getUidRanges());
}
pw.decreaseIndent();
pw.decreaseIndent();
@@ -2974,6 +2969,9 @@
case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
if (nai.everConnected) {
loge("ERROR: cannot call explicitlySelected on already-connected network");
+ // Note that if the NAI had been connected, this would affect the
+ // score, and therefore would require re-mixing the score and performing
+ // a rematch.
}
nai.networkAgentConfig.explicitlySelected = toBool(msg.arg1);
nai.networkAgentConfig.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2);
@@ -3660,7 +3658,7 @@
log("Replacing " + existingRequest.mRequests.get(0) + " with "
+ nri.mRequests.get(0) + " because their intents matched.");
}
- handleReleaseNetworkRequest(existingRequest.mRequests.get(0), getCallingUid(),
+ handleReleaseNetworkRequest(existingRequest.mRequests.get(0), mDeps.getCallingUid(),
/* callOnUnavailable */ false);
}
handleRegisterNetworkRequest(nri);
@@ -4058,6 +4056,7 @@
// network, we should respect the user's option and don't need to popup the
// PARTIAL_CONNECTIVITY notification to user again.
nai.networkAgentConfig.acceptPartialConnectivity = accept;
+ nai.updateScoreForNetworkAgentConfigUpdate();
rematchAllNetworksAndRequests();
sendUpdatedScoreToFactories(nai);
}
@@ -4320,7 +4319,7 @@
Intent intent = new Intent(action);
if (type != NotificationType.PRIVATE_DNS_BROKEN) {
- intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.getNetId()), null));
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK, nai.network);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Some OEMs have their own Settings package. Thus, need to get the current using
// Settings package name instead of just use default name "com.android.settings".
@@ -5294,9 +5293,8 @@
private Set<UidRange> getUids() {
// networkCapabilities.getUids() returns a defensive copy.
// multilayer requests will all have the same uids so return the first one.
- final Set<UidRange> uids = null == mRequests.get(0).networkCapabilities.getUids()
- ? new ArraySet<>() : mRequests.get(0).networkCapabilities.getUids();
- return uids;
+ final Set<UidRange> uids = mRequests.get(0).networkCapabilities.getUidRanges();
+ return (null == uids) ? new ArraySet<>() : uids;
}
NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final PendingIntent pi,
@@ -5749,14 +5747,14 @@
private void releasePendingNetworkRequestWithDelay(PendingIntent operation) {
mHandler.sendMessageDelayed(
mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
- getCallingUid(), 0, operation), mReleasePendingIntentDelayMs);
+ mDeps.getCallingUid(), 0, operation), mReleasePendingIntentDelayMs);
}
@Override
public void releasePendingNetworkRequest(PendingIntent operation) {
Objects.requireNonNull(operation, "PendingIntent cannot be null.");
mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
- getCallingUid(), 0, operation));
+ mDeps.getCallingUid(), 0, operation));
}
// In order to implement the compatibility measure for pre-M apps that call
@@ -5853,7 +5851,7 @@
public void releaseNetworkRequest(NetworkRequest networkRequest) {
ensureNetworkRequestHasType(networkRequest);
mHandler.sendMessage(mHandler.obtainMessage(
- EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest));
+ EVENT_RELEASE_NETWORK_REQUEST, mDeps.getCallingUid(), 0, networkRequest));
}
private void handleRegisterNetworkProvider(NetworkProviderInfo npi) {
@@ -6102,7 +6100,7 @@
for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
// Currently, all network requests will have the same uids therefore checking the first
// one is sufficient. If/when uids are tracked at the nri level, this can change.
- final Set<UidRange> uids = nri.mRequests.get(0).networkCapabilities.getUids();
+ final Set<UidRange> uids = nri.mRequests.get(0).networkCapabilities.getUidRanges();
if (null == uids) {
continue;
}
@@ -6543,7 +6541,7 @@
return;
}
- final Set<UidRange> ranges = nai.networkCapabilities.getUids();
+ final Set<UidRange> ranges = nai.networkCapabilities.getUidRanges();
final int vpnAppUid = nai.networkCapabilities.getOwnerUid();
// TODO: this create a window of opportunity for apps to receive traffic between the time
// when the old rules are removed and the time when new rules are added. To fix this,
@@ -6908,8 +6906,8 @@
private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
NetworkCapabilities newNc) {
- Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
- Set<UidRange> newRanges = null == newNc ? null : newNc.getUids();
+ Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUidRanges();
+ Set<UidRange> newRanges = null == newNc ? null : newNc.getUidRanges();
if (null == prevRanges) prevRanges = new ArraySet<>();
if (null == newRanges) newRanges = new ArraySet<>();
final Set<UidRange> prevRangesCopy = new ArraySet<>(prevRanges);
@@ -8331,7 +8329,7 @@
final NetworkAgentInfo vpn = getVpnForUid(uid);
if (vpn == null || getVpnType(vpn) != VpnManager.TYPE_VPN_SERVICE
- || vpn.networkCapabilities.getOwnerUid() != Binder.getCallingUid()) {
+ || vpn.networkCapabilities.getOwnerUid() != mDeps.getCallingUid()) {
return INVALID_UID;
}
@@ -9240,7 +9238,7 @@
final ArrayList<NetworkRequest> nrs = new ArrayList<>();
nrs.add(createNetworkRequest(NetworkRequest.Type.REQUEST, pref.capabilities));
nrs.add(createDefaultRequest());
- setNetworkRequestUids(nrs, pref.capabilities.getUids());
+ setNetworkRequestUids(nrs, UidRange.fromIntRanges(pref.capabilities.getUids()));
final NetworkRequestInfo nri = new NetworkRequestInfo(nrs);
result.add(nri);
}
@@ -9456,9 +9454,8 @@
private static void setNetworkRequestUids(@NonNull final List<NetworkRequest> requests,
@NonNull final Set<UidRange> uids) {
- final Set<UidRange> ranges = new ArraySet<>(uids);
for (final NetworkRequest req : requests) {
- req.networkCapabilities.setUids(ranges);
+ req.networkCapabilities.setUids(UidRange.toIntRanges(uids));
}
}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 4c3c6ef..794cb93 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1651,7 +1651,7 @@
c.getMode(),
c.getSourceAddress(),
c.getDestinationAddress(),
- (c.getNetwork() != null) ? c.getNetwork().netId : 0,
+ (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0,
spiRecord.getSpi(),
c.getMarkValue(),
c.getMarkMask(),
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 10d6570..3ea0ce1 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -643,7 +643,7 @@
String route, String gateway, String ifName) throws RemoteException {
final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
- ifName);
+ ifName, RouteInfo.RTN_UNICAST);
mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute));
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index cbce720..7f96aff 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1792,7 +1792,7 @@
public StorageManagerService(Context context) {
sSelf = this;
mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
mContext = context;
mResolver = mContext.getContentResolver();
mCallbacks = new Callbacks(FgThread.get().getLooper());
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 56aabc20..d756c1f 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -352,7 +352,10 @@
@Override
public void startLegacyVpn(VpnProfile profile) {
int user = UserHandle.getUserId(mDeps.getCallingUid());
- final LinkProperties egress = mCm.getActiveLinkProperties();
+ // Note that if the caller is not system (uid >= Process.FIRST_APPLICATION_UID),
+ // the code might not work well since getActiveNetwork might return null if the uid is
+ // blocked by NetworkPolicyManagerService.
+ final LinkProperties egress = mCm.getLinkProperties(mCm.getActiveNetwork());
if (egress == null) {
throw new IllegalStateException("Missing active network connection");
}
diff --git a/services/core/java/com/android/server/WatchableIntentResolver.java b/services/core/java/com/android/server/WatchedIntentResolver.java
similarity index 97%
rename from services/core/java/com/android/server/WatchableIntentResolver.java
rename to services/core/java/com/android/server/WatchedIntentResolver.java
index 2ef94f1..e514f3c 100644
--- a/services/core/java/com/android/server/WatchableIntentResolver.java
+++ b/services/core/java/com/android/server/WatchedIntentResolver.java
@@ -31,7 +31,7 @@
* @param <R> The resolver type.
* {@hide}
*/
-public abstract class WatchableIntentResolver<F, R extends Object>
+public abstract class WatchedIntentResolver<F, R extends Object>
extends IntentResolver<F, R>
implements Watchable {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3c445ae..1b352c7 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -160,6 +160,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
@@ -559,6 +560,45 @@
return smap != null ? smap.mStartingBackground.size() >= mMaxStartingBackground : false;
}
+ boolean hasForegroundServiceNotificationLocked(String pkg, int userId, String channelId) {
+ final ServiceMap smap = mServiceMap.get(userId);
+ if (smap != null) {
+ for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) {
+ final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
+ if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) {
+ if (Objects.equals(sr.foregroundNoti.getChannelId(), channelId)) {
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.d(TAG_SERVICE, "Channel u" + userId + "/pkg=" + pkg
+ + "/channelId=" + channelId
+ + " has fg service notification");
+ }
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ void stopForegroundServicesForChannelLocked(String pkg, int userId, String channelId) {
+ final ServiceMap smap = mServiceMap.get(userId);
+ if (smap != null) {
+ for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) {
+ final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
+ if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) {
+ if (Objects.equals(sr.foregroundNoti.getChannelId(), channelId)) {
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.d(TAG_SERVICE, "Stopping FGS u" + userId + "/pkg=" + pkg
+ + "/channelId=" + channelId
+ + " for conversation channel clear");
+ }
+ stopServiceLocked(sr, false);
+ }
+ }
+ }
+ }
+ }
+
private ServiceMap getServiceMapLocked(int callingUser) {
ServiceMap smap = mServiceMap.get(callingUser);
if (smap == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0e8644a..c4548a3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15911,6 +15911,22 @@
}
@Override
+ public boolean hasForegroundServiceNotification(String pkg, int userId,
+ String channelId) {
+ synchronized (ActivityManagerService.this) {
+ return mServices.hasForegroundServiceNotificationLocked(pkg, userId, channelId);
+ }
+ }
+
+ @Override
+ public void stopForegroundServicesForChannel(String pkg, int userId,
+ String channelId) {
+ synchronized (ActivityManagerService.this) {
+ mServices.stopForegroundServicesForChannelLocked(pkg, userId, channelId);
+ }
+ }
+
+ @Override
public void registerProcessObserver(IProcessObserver processObserver) {
ActivityManagerService.this.registerProcessObserver(processObserver);
}
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 9e79b02..273b9c3 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -30,6 +30,10 @@
michaelwr@google.com
narayan@google.com
+# Voice Interaction
+per-file *Assist* = file:/core/java/android/service/voice/OWNERS
+per-file *Voice* = file:/core/java/android/service/voice/OWNERS
+
per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
per-file CarUserSwitchingDialog.java = keunyoung@google.com, felipeal@google.com, gurunagarajan@google.com
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 442cdd9..51bcde8 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -786,7 +786,7 @@
mAppDataIsolationEnabled =
SystemProperties.getBoolean(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
mAppDataIsolationAllowlistedApps = new ArrayList<>(
SystemConfig.getInstance().getAppDataIsolationWhitelistedApps());
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 2c0a589..ad5a65c 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -173,7 +173,9 @@
if (!checkHibernationEnabled("isHibernatingForUser")) {
return false;
}
-
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_APP_HIBERNATION,
+ "Caller does not have MANAGE_APP_HIBERNATION permission.");
userId = handleIncomingUser(userId, "isHibernating");
if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
Slog.e(TAG, "Attempt to get hibernation state of stopped or nonexistent user "
@@ -202,6 +204,9 @@
if (!checkHibernationEnabled("isHibernatingGlobally")) {
return false;
}
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_APP_HIBERNATION,
+ "Caller does not have MANAGE_APP_HIBERNATION permission.");
synchronized (mLock) {
GlobalLevelState state = mGlobalHibernationStates.get(packageName);
if (state == null) {
@@ -223,6 +228,9 @@
if (!checkHibernationEnabled("setHibernatingForUser")) {
return;
}
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_APP_HIBERNATION,
+ "Caller does not have MANAGE_APP_HIBERNATION permission.");
userId = handleIncomingUser(userId, "setHibernating");
if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
Slog.w(TAG, "Attempt to set hibernation state for a stopped or nonexistent user "
@@ -263,6 +271,9 @@
if (!checkHibernationEnabled("setHibernatingGlobally")) {
return;
}
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_APP_HIBERNATION,
+ "Caller does not have MANAGE_APP_HIBERNATION permission.");
synchronized (mLock) {
GlobalLevelState state = mGlobalHibernationStates.get(packageName);
if (state == null) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 2e6cfdc..804550b 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3871,7 +3871,9 @@
* @return true if microphone is reported as muted by primary HAL
*/
public boolean isMicrophoneMuted() {
- return mMicMuteFromSystemCached && !mMicMuteFromPrivacyToggle;
+ return mMicMuteFromSystemCached
+ && (!mMicMuteFromPrivacyToggle
+ || mMicMuteFromApi || mMicMuteFromRestrictions || mMicMuteFromSwitch);
}
private boolean isMicrophoneSupposedToBeMuted() {
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index f888200..6017e92 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -195,7 +195,8 @@
final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
final boolean requireConfirmation = isConfirmationRequired(sensor);
sensor.goToStateWaitingForCookie(requireConfirmation, mToken, mOperationId,
- mUserId, mSensorReceiver, mOpPackageName, cookie);
+ mUserId, mSensorReceiver, mOpPackageName, cookie,
+ mPromptInfo.isAllowBackgroundAuthentication());
}
}
@@ -596,7 +597,8 @@
mPreAuthInfo.confirmationRequested,
FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
latency,
- mDebugEnabled);
+ mDebugEnabled,
+ -1 /* sensorId */);
} else {
final long latency = System.currentTimeMillis() - mStartTimeMs;
@@ -624,7 +626,8 @@
error,
0 /* vendorCode */,
mDebugEnabled,
- latency);
+ latency,
+ -1 /* sensorId */);
}
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricSensor.java b/services/core/java/com/android/server/biometrics/BiometricSensor.java
index 85de81bb3..c9e148f 100644
--- a/services/core/java/com/android/server/biometrics/BiometricSensor.java
+++ b/services/core/java/com/android/server/biometrics/BiometricSensor.java
@@ -103,11 +103,12 @@
void goToStateWaitingForCookie(boolean requireConfirmation, IBinder token, long sessionId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- int cookie)
+ int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mCookie = cookie;
impl.prepareForAuthentication(requireConfirmation, token,
- sessionId, userId, sensorReceiver, opPackageName, mCookie);
+ sessionId, userId, sensorReceiver, opPackageName, mCookie,
+ allowBackgroundAuthentication);
mSensorState = STATE_WAITING_FOR_COOKIE;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 9617bb0..79e75b1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -55,7 +55,7 @@
@Nullable private final TaskStackListener mTaskStackListener;
private final LockoutTracker mLockoutTracker;
private final boolean mIsRestricted;
- private final boolean mIsKeyguard;
+ private final boolean mAllowBackgroundAuthentication;
protected final long mOperationId;
@@ -68,7 +68,7 @@
int targetUserId, long operationId, boolean restricted, @NonNull String owner,
int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric,
int statsModality, int statsClient, @Nullable TaskStackListener taskStackListener,
- @NonNull LockoutTracker lockoutTracker, boolean isKeyguard) {
+ @NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
mIsStrongBiometric = isStrongBiometric;
@@ -79,7 +79,7 @@
mTaskStackListener = taskStackListener;
mLockoutTracker = lockoutTracker;
mIsRestricted = restricted;
- mIsKeyguard = isKeyguard;
+ mAllowBackgroundAuthentication = allowBackgroundAuthentication;
}
public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
@@ -120,7 +120,7 @@
}
public boolean isKeyguard() {
- return mIsKeyguard;
+ return Utils.isKeyguard(getContext(), getOwnerString());
}
@Override
@@ -152,9 +152,15 @@
pm.incrementAuthForUser(getTargetUserId(), authenticated);
}
+ if (mAllowBackgroundAuthentication) {
+ Slog.w(TAG, "Allowing background authentication,"
+ + " this is allowed only for platform or test invocations");
+ }
+
// Ensure authentication only succeeds if the client activity is on top.
boolean isBackgroundAuth = false;
- if (authenticated && !Utils.isKeyguard(getContext(), getOwnerString())
+ if (!mAllowBackgroundAuthentication && authenticated
+ && !Utils.isKeyguard(getContext(), getOwnerString())
&& !Utils.isSystem(getContext(), getOwnerString())) {
final List<ActivityManager.RunningTaskInfo> tasks =
mActivityTaskManager.getTasks(1);
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index de57186..282261e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -127,7 +127,8 @@
getContext().getPackageName(), mBiometricUtils, getSensorId(), mAuthenticatorIds);
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
mStatsModality,
- BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL);
+ BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL,
+ -1 /* sensorId */);
mCurrentTask.start(mRemoveCallback);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
index e3feb74..7f6903a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
@@ -118,7 +118,8 @@
getTargetUserId(), identifier.getBiometricId());
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
mStatsModality,
- BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK);
+ BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK,
+ -1 /* sensorId */);
}
mEnrolledList.clear();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
index edde3d4..4da644d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
@@ -126,7 +126,8 @@
mStatsClient,
acquiredInfo,
vendorCode,
- Utils.isDebugEnabled(context, targetUserId));
+ Utils.isDebugEnabled(context, targetUserId),
+ -1 /* sensorId */);
}
protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) {
@@ -164,7 +165,8 @@
error,
vendorCode,
Utils.isDebugEnabled(context, targetUserId),
- sanitizeLatency(latency));
+ sanitizeLatency(latency),
+ -1 /* sensorId */);
}
protected final void logOnAuthenticated(Context context, boolean authenticated,
@@ -214,7 +216,8 @@
requireConfirmation,
authState,
sanitizeLatency(latency),
- Utils.isDebugEnabled(context, targetUserId));
+ Utils.isDebugEnabled(context, targetUserId),
+ -1 /* sensorId */);
}
protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
@@ -240,7 +243,8 @@
mStatsModality,
targetUserId,
sanitizeLatency(latency),
- enrollSuccessful);
+ enrollSuccessful,
+ -1 /* sensorId */);
}
private long sanitizeLatency(long latency) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
index 2926260..0002ad2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
@@ -61,10 +61,10 @@
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, int cookie)
+ String opPackageName, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mFaceService.prepareForAuthentication(mSensorId, requireConfirmation, token, operationId,
- userId, sensorReceiver, opPackageName, cookie);
+ userId, sensorReceiver, opPackageName, cookie, allowBackgroundAuthentication);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index a74e2da..9f5dc69 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -306,7 +306,8 @@
@Override // Binder call
public void prepareForAuthentication(int sensorId, boolean requireConfirmation,
IBinder token, long operationId, int userId,
- IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie) {
+ IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie,
+ boolean allowBackgroundAuthentication) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -318,7 +319,7 @@
final boolean restricted = true; // BiometricPrompt is always restricted
provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted,
- BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, false /* isKeyguard */);
+ BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, allowBackgroundAuthentication);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
index 88edfbf..9b6fb0b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -103,7 +103,8 @@
void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard);
+ @NonNull String opPackageName, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication);
void cancelAuthentication(int sensorId, @NonNull IBinder token);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 089cf1e..07d173c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -69,11 +69,11 @@
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
boolean isStrongBiometric, int statsClient, @NonNull UsageStats usageStats,
- @NonNull LockoutCache lockoutCache, boolean isKeyguard) {
+ @NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
- lockoutCache, isKeyguard);
+ lockoutCache, allowBackgroundAuthentication);
mUsageStats = usageStats;
mLockoutCache = lockoutCache;
mNotificationManager = context.getSystemService(NotificationManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index ebf13e0..ca29057 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -27,6 +27,7 @@
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
+import android.hardware.biometrics.common.ComponentInfo;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
@@ -137,8 +138,7 @@
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
if (prop.commonProps.componentInfo != null) {
- for (android.hardware.biometrics.common.ComponentInfo info
- : prop.commonProps.componentInfo) {
+ for (ComponentInfo info : prop.commonProps.componentInfo) {
componentInfo.add(new ComponentInfoInternal(info.componentId,
info.hardwareVersion, info.firmwareVersion, info.serialNumber,
info.softwareVersion));
@@ -445,7 +445,7 @@
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
- boolean isKeyguard) {
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
final IFace daemon = getHalInstance();
if (daemon == null) {
@@ -466,7 +466,8 @@
mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
operationId, restricted, opPackageName, cookie,
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
- mUsageStats, mSensors.get(sensorId).getLockoutCache(), isKeyguard);
+ mUsageStats, mSensors.get(sensorId).getLockoutCache(),
+ allowBackgroundAuthentication);
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
} catch (RemoteException e) {
Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index c7d2f0f..c6f39aa 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -546,7 +546,8 @@
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
BiometricsProtoEnums.MODALITY_FACE,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ BiometricsProtoEnums.ISSUE_HAL_DEATH,
+ -1 /* sensorId */);
}
mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 55e9a83..50756c8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -387,7 +387,8 @@
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
BiometricsProtoEnums.MODALITY_FACE,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ BiometricsProtoEnums.ISSUE_HAL_DEATH,
+ -1 /* sensorId */);
}
mScheduler.recordCrashState();
@@ -638,7 +639,7 @@
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
@NonNull String opPackageName, boolean restricted, int statsClient,
- boolean isKeyguard) {
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
@@ -646,7 +647,7 @@
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
mLazyDaemon, token, receiver, userId, operationId, restricted, opPackageName,
cookie, false /* requireConfirmation */, mSensorId, isStrongBiometric,
- statsClient, mLockoutTracker, mUsageStats, isKeyguard);
+ statsClient, mLockoutTracker, mUsageStats, allowBackgroundAuthentication);
mScheduler.scheduleClientMonitor(client);
});
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 3ca51d3..ff06a4a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -62,11 +62,11 @@
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
boolean isStrongBiometric, int statsClient, @NonNull LockoutTracker lockoutTracker,
- @NonNull UsageStats usageStats, boolean isKeyguard) {
+ @NonNull UsageStats usageStats, boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
- lockoutTracker, isKeyguard);
+ lockoutTracker, allowBackgroundAuthentication);
mUsageStats = usageStats;
final Resources resources = getContext().getResources();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
index 9e82ffc..8109680 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
@@ -62,10 +62,10 @@
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, int cookie)
+ String opPackageName, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mFingerprintService.prepareForAuthentication(mSensorId, token, operationId, userId,
- sensorReceiver, opPackageName, cookie);
+ sensorReceiver, opPackageName, cookie, allowBackgroundAuthentication);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index aa5afb7..e4397fd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -403,7 +403,7 @@
@Override // Binder call
public void prepareForAuthentication(int sensorId, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- int cookie) {
+ int cookie, boolean allowBackgroundAuthentication) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -415,7 +415,7 @@
final boolean restricted = true; // BiometricPrompt is always restricted
provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted,
- BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, false /* isKeyguard */);
+ BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, allowBackgroundAuthentication);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index 0d50499..c09d2d3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -96,7 +96,8 @@
void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard);
+ @NonNull String opPackageName, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication);
void startPreparedClient(int sensorId, int cookie);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index e2743f6..76a47d3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -59,11 +59,12 @@
boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
int sensorId, boolean isStrongBiometric, int statsClient,
@Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache,
- @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isKeyguard) {
+ @Nullable IUdfpsOverlayController udfpsOverlayController,
+ boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner,
cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
- lockoutCache, isKeyguard);
+ lockoutCache, allowBackgroundAuthentication);
mLockoutCache = lockoutCache;
mUdfpsOverlayController = udfpsOverlayController;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 2c85dc9..1b5def6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -29,6 +29,7 @@
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
+import android.hardware.biometrics.common.ComponentInfo;
import android.hardware.biometrics.fingerprint.IFingerprint;
import android.hardware.biometrics.fingerprint.SensorProps;
import android.hardware.fingerprint.Fingerprint;
@@ -141,8 +142,7 @@
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
if (prop.commonProps.componentInfo != null) {
- for (android.hardware.biometrics.common.ComponentInfo info
- : prop.commonProps.componentInfo) {
+ for (ComponentInfo info : prop.commonProps.componentInfo) {
componentInfo.add(new ComponentInfoInternal(info.componentId,
info.hardwareVersion, info.firmwareVersion, info.serialNumber,
info.softwareVersion));
@@ -469,7 +469,7 @@
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
- boolean isKeyguard) {
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
final IFingerprint daemon = getHalInstance();
if (daemon == null) {
@@ -491,7 +491,7 @@
operationId, restricted, opPackageName, cookie,
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
- mUdfpsOverlayController, isKeyguard);
+ mUdfpsOverlayController, allowBackgroundAuthentication);
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
} catch (RemoteException e) {
Slog.e(getTag(), "Remote exception when scheduling authenticate", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index b9dee7d..5631647 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -526,7 +526,8 @@
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
BiometricsProtoEnums.MODALITY_FINGERPRINT,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ BiometricsProtoEnums.ISSUE_HAL_DEATH,
+ -1 /* sensorId */);
}
mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index f112549..f2992cc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -390,7 +390,8 @@
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
BiometricsProtoEnums.MODALITY_FINGERPRINT,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ BiometricsProtoEnums.ISSUE_HAL_DEATH,
+ -1 /* sensorId */);
}
mScheduler.recordCrashState();
@@ -611,7 +612,7 @@
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
@NonNull String opPackageName, boolean restricted, int statsClient,
- boolean isKeyguard) {
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
@@ -620,7 +621,8 @@
mContext, mLazyDaemon, token, listener, userId, operationId, restricted,
opPackageName, cookie, false /* requireConfirmation */,
mSensorProperties.sensorId, isStrongBiometric, statsClient,
- mTaskStackListener, mLockoutTracker, mUdfpsOverlayController, isKeyguard);
+ mTaskStackListener, mLockoutTracker, mUdfpsOverlayController,
+ allowBackgroundAuthentication);
mScheduler.scheduleClientMonitor(client);
});
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index db37112..97f1287 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -59,11 +59,12 @@
int sensorId, boolean isStrongBiometric, int statsClient,
@NonNull TaskStackListener taskStackListener,
@NonNull LockoutFrameworkImpl lockoutTracker,
- @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isKeyguard) {
+ @Nullable IUdfpsOverlayController udfpsOverlayController,
+ boolean allowBackgroundAuthentication) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
- lockoutTracker, isKeyguard);
+ lockoutTracker, allowBackgroundAuthentication);
mLockoutFrameworkImpl = lockoutTracker;
mUdfpsOverlayController = udfpsOverlayController;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
index 95915b7..1003c26 100644
--- a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
@@ -59,7 +59,8 @@
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long sessionId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, int cookie) throws RemoteException {
+ String opPackageName, int cookie, boolean allowBackgroundAuthentication)
+ throws RemoteException {
}
@Override
diff --git a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java b/services/core/java/com/android/server/connectivity/ConnectivityConstants.java
index 0fb6fec..325a2cd 100644
--- a/services/core/java/com/android/server/connectivity/ConnectivityConstants.java
+++ b/services/core/java/com/android/server/connectivity/ConnectivityConstants.java
@@ -18,18 +18,10 @@
/**
* A class encapsulating various constants used by Connectivity.
+ * TODO : remove this class.
* @hide
*/
public class ConnectivityConstants {
-
- // Penalty applied to scores of Networks that have not been validated.
- public static final int UNVALIDATED_SCORE_PENALTY = 40;
-
- // Score for explicitly connected network.
- //
- // This ensures that a) the explicitly selected network is never trumped by anything else, and
- // b) the explicitly selected network is never torn down.
- public static final int EXPLICITLY_SELECTED_NETWORK_SCORE = 100;
// VPNs typically have priority over other networks. Give them a score that will
// let them win every single time.
public static final int VPN_DEFAULT_SCORE = 101;
diff --git a/services/core/java/com/android/server/connectivity/FullScore.java b/services/core/java/com/android/server/connectivity/FullScore.java
new file mode 100644
index 0000000..028cfee
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/FullScore.java
@@ -0,0 +1,211 @@
+/*
+ * 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 com.android.server.connectivity;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.net.NetworkAgentConfig;
+import android.net.NetworkCapabilities;
+import android.net.NetworkScore;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.StringJoiner;
+
+/**
+ * This class represents how desirable a network is.
+ *
+ * FullScore is very similar to NetworkScore, but it contains the bits that are managed
+ * by ConnectivityService. This provides static guarantee that all users must know whether
+ * they are handling a score that had the CS-managed bits set.
+ */
+public class FullScore {
+ // This will be removed soon. Do *NOT* depend on it for any new code that is not part of
+ // a migration.
+ private final int mLegacyInt;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"POLICY_"}, value = {
+ POLICY_IS_VALIDATED,
+ POLICY_IS_VPN,
+ POLICY_EVER_USER_SELECTED,
+ POLICY_ACCEPT_UNVALIDATED
+ })
+ public @interface Policy {
+ }
+
+ // Agent-managed policies are in NetworkScore. They start from 1.
+ // CS-managed policies, counting from 63 downward
+ // This network is validated. CS-managed because the source of truth is in NetworkCapabilities.
+ /** @hide */
+ public static final int POLICY_IS_VALIDATED = 63;
+
+ // This is a VPN and behaves as one for scoring purposes.
+ /** @hide */
+ public static final int POLICY_IS_VPN = 62;
+
+ // This network has been selected by the user manually from settings or a 3rd party app
+ // at least once. {@see NetworkAgentConfig#explicitlySelected}.
+ /** @hide */
+ public static final int POLICY_EVER_USER_SELECTED = 61;
+
+ // The user has indicated in UI that this network should be used even if it doesn't
+ // validate. {@see NetworkAgentConfig#acceptUnvalidated}.
+ /** @hide */
+ public static final int POLICY_ACCEPT_UNVALIDATED = 60;
+
+ // To help iterate when printing
+ @VisibleForTesting
+ static final int MIN_CS_MANAGED_POLICY = POLICY_ACCEPT_UNVALIDATED;
+ @VisibleForTesting
+ static final int MAX_CS_MANAGED_POLICY = POLICY_IS_VALIDATED;
+
+ @VisibleForTesting
+ static @NonNull String policyNameOf(final int policy) {
+ switch (policy) {
+ case POLICY_IS_VALIDATED: return "IS_VALIDATED";
+ case POLICY_IS_VPN: return "IS_VPN";
+ case POLICY_EVER_USER_SELECTED: return "EVER_USER_SELECTED";
+ case POLICY_ACCEPT_UNVALIDATED: return "ACCEPT_UNVALIDATED";
+ }
+ throw new IllegalArgumentException("Unknown policy : " + policy);
+ }
+
+ // Bitmask of all the policies applied to this score.
+ private final long mPolicies;
+
+ FullScore(final int legacyInt, final long policies) {
+ mLegacyInt = legacyInt;
+ mPolicies = policies;
+ }
+
+ /**
+ * Given a score supplied by the NetworkAgent and CS-managed objects, produce a full score.
+ *
+ * @param score the score supplied by the agent
+ * @param caps the NetworkCapabilities of the network
+ * @param config the NetworkAgentConfig of the network
+ * @return an FullScore that is appropriate to use for ranking.
+ */
+ public static FullScore fromNetworkScore(@NonNull final NetworkScore score,
+ @NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config) {
+ return withPolicies(score.getLegacyInt(), caps.hasCapability(NET_CAPABILITY_VALIDATED),
+ caps.hasTransport(TRANSPORT_VPN),
+ config.explicitlySelected,
+ config.acceptUnvalidated);
+ }
+
+ /**
+ * Return a new score given updated caps and config.
+ *
+ * @param caps the NetworkCapabilities of the network
+ * @param config the NetworkAgentConfig of the network
+ * @return a score with the policies from the arguments reset
+ */
+ public FullScore mixInScore(@NonNull final NetworkCapabilities caps,
+ @NonNull final NetworkAgentConfig config) {
+ return withPolicies(mLegacyInt, caps.hasCapability(NET_CAPABILITY_VALIDATED),
+ caps.hasTransport(TRANSPORT_VPN),
+ config.explicitlySelected,
+ config.acceptUnvalidated);
+ }
+
+ private static FullScore withPolicies(@NonNull final int legacyInt,
+ final boolean isValidated,
+ final boolean isVpn,
+ final boolean everUserSelected,
+ final boolean acceptUnvalidated) {
+ return new FullScore(legacyInt,
+ (isValidated ? 1L << POLICY_IS_VALIDATED : 0)
+ | (isVpn ? 1L << POLICY_IS_VPN : 0)
+ | (everUserSelected ? 1L << POLICY_EVER_USER_SELECTED : 0)
+ | (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0));
+ }
+
+ /**
+ * For backward compatibility, get the legacy int.
+ * This will be removed before S is published.
+ */
+ public int getLegacyInt() {
+ return getLegacyInt(false /* pretendValidated */);
+ }
+
+ public int getLegacyIntAsValidated() {
+ return getLegacyInt(true /* pretendValidated */);
+ }
+
+ // TODO : remove these two constants
+ // Penalty applied to scores of Networks that have not been validated.
+ private static final int UNVALIDATED_SCORE_PENALTY = 40;
+
+ // Score for a network that can be used unvalidated
+ private static final int ACCEPT_UNVALIDATED_NETWORK_SCORE = 100;
+
+ private int getLegacyInt(boolean pretendValidated) {
+ // If the user has chosen this network at least once, give it the maximum score when
+ // checking to pretend it's validated, or if it doesn't need to validate because the
+ // user said to use it even if it doesn't validate.
+ // This ensures that networks that have been selected in UI are not torn down before the
+ // user gets a chance to prefer it when a higher-scoring network (e.g., Ethernet) is
+ // available.
+ if (hasPolicy(POLICY_EVER_USER_SELECTED)
+ && (hasPolicy(POLICY_ACCEPT_UNVALIDATED) || pretendValidated)) {
+ return ACCEPT_UNVALIDATED_NETWORK_SCORE;
+ }
+
+ int score = mLegacyInt;
+ // Except for VPNs, networks are subject to a penalty for not being validated.
+ // Apply the penalty unless the network is a VPN, or it's validated or pretending to be.
+ if (!hasPolicy(POLICY_IS_VALIDATED) && !pretendValidated && !hasPolicy(POLICY_IS_VPN)) {
+ score -= UNVALIDATED_SCORE_PENALTY;
+ }
+ if (score < 0) score = 0;
+ return score;
+ }
+
+ /**
+ * @return whether this score has a particular policy.
+ */
+ @VisibleForTesting
+ public boolean hasPolicy(final int policy) {
+ return 0 != (mPolicies & (1L << policy));
+ }
+
+ // Example output :
+ // Score(50 ; Policies : EVER_USER_SELECTED&IS_VALIDATED)
+ @Override
+ public String toString() {
+ final StringJoiner sj = new StringJoiner(
+ "&", // delimiter
+ "Score(" + mLegacyInt + " ; Policies : ", // prefix
+ ")"); // suffix
+ for (int i = NetworkScore.MIN_AGENT_MANAGED_POLICY;
+ i <= NetworkScore.MAX_AGENT_MANAGED_POLICY; ++i) {
+ if (hasPolicy(i)) sj.add(policyNameOf(i));
+ }
+ for (int i = MIN_CS_MANAGED_POLICY; i <= MAX_CS_MANAGED_POLICY; ++i) {
+ if (hasPolicy(i)) sj.add(policyNameOf(i));
+ }
+ return sj.toString();
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index e44dcf5..103ab95 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -25,6 +25,8 @@
import android.net.CaptivePortalData;
import android.net.IDnsResolver;
import android.net.INetd;
+import android.net.INetworkAgent;
+import android.net.INetworkAgentRegistry;
import android.net.INetworkMonitor;
import android.net.LinkProperties;
import android.net.NattKeepalivePacketData;
@@ -51,8 +53,6 @@
import android.util.Pair;
import android.util.SparseArray;
-import com.android.connectivity.aidl.INetworkAgent;
-import com.android.connectivity.aidl.INetworkAgentRegistry;
import com.android.internal.util.WakeupMessage;
import com.android.server.ConnectivityService;
@@ -303,8 +303,9 @@
// validated).
private boolean mInactive;
- // This represents the quality of the network.
- private NetworkScore mScore;
+ // This represents the quality of the network. As opposed to NetworkScore, FullScore includes
+ // the ConnectivityService-managed bits.
+ private FullScore mScore;
// The list of NetworkRequests being satisfied by this Network.
private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
@@ -356,12 +357,12 @@
networkInfo = info;
linkProperties = lp;
networkCapabilities = nc;
- mScore = score;
+ networkAgentConfig = config;
+ setScore(score); // uses members networkCapabilities and networkAgentConfig
clatd = new Nat464Xlat(this, netd, dnsResolver, deps);
mConnService = connService;
mContext = context;
mHandler = handler;
- networkAgentConfig = config;
this.factorySerialNumber = factorySerialNumber;
this.creatorUid = creatorUid;
mQosCallbackTracker = qosCallbackTracker;
@@ -667,6 +668,7 @@
@NonNull final NetworkCapabilities nc) {
final NetworkCapabilities oldNc = networkCapabilities;
networkCapabilities = nc;
+ mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig);
final NetworkMonitorManager nm = mNetworkMonitor;
if (nm != null) {
nm.notifyNetworkCapabilitiesChanged(nc);
@@ -844,30 +846,6 @@
return isVPN();
}
- private int getCurrentScore(boolean pretendValidated) {
- // TODO: We may want to refactor this into a NetworkScore class that takes a base score from
- // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the
- // score. The NetworkScore class would provide a nice place to centralize score constants
- // so they are not scattered about the transports.
-
- // If this network is explicitly selected and the user has decided to use it even if it's
- // unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly
- // selected and we're trying to see what its score could be. This ensures that we don't tear
- // down an explicitly selected network before the user gets a chance to prefer it when
- // a higher-scoring network (e.g., Ethernet) is available.
- if (networkAgentConfig.explicitlySelected
- && (networkAgentConfig.acceptUnvalidated || pretendValidated)) {
- return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
- }
-
- int score = mScore.getLegacyInt();
- if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
- score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
- }
- if (score < 0) score = 0;
- return score;
- }
-
// Return true on devices configured to ignore score penalty for wifi networks
// that become unvalidated (b/31075769).
private boolean ignoreWifiUnvalidationPenalty() {
@@ -880,17 +858,29 @@
// Get the current score for this Network. This may be modified from what the
// NetworkAgent sent, as it has modifiers applied to it.
public int getCurrentScore() {
- return getCurrentScore(false);
+ return mScore.getLegacyInt();
}
// Get the current score for this Network as if it was validated. This may be modified from
// what the NetworkAgent sent, as it has modifiers applied to it.
public int getCurrentScoreAsValidated() {
- return getCurrentScore(true);
+ return mScore.getLegacyIntAsValidated();
}
+ /**
+ * Mix-in the ConnectivityService-managed bits in the score.
+ */
public void setScore(final NetworkScore score) {
- mScore = score;
+ mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig);
+ }
+
+ /**
+ * Update the ConnectivityService-managed bits in the score.
+ *
+ * Call this after updating the network agent config.
+ */
+ public void updateScoreForNetworkAgentConfigUpdate() {
+ mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig);
}
/**
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 181a10d..0c0d459 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -28,6 +28,8 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.graphics.drawable.Icon;
+import android.net.ConnectivityResources;
import android.net.NetworkSpecifier;
import android.net.TelephonyNetworkSpecifier;
import android.net.wifi.WifiInfo;
@@ -40,7 +42,7 @@
import android.util.SparseIntArray;
import android.widget.Toast;
-import com.android.internal.R;
+import com.android.connectivity.resources.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
@@ -82,6 +84,7 @@
// The context is for the current user (system server)
private final Context mContext;
+ private final Resources mResources;
private final TelephonyManager mTelephonyManager;
// The notification manager is created from a context for User.ALL, so notifications
// will be sent to all users.
@@ -96,6 +99,7 @@
(NotificationManager) c.createContextAsUser(UserHandle.ALL, 0 /* flags */)
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationTypeMap = new SparseIntArray();
+ mResources = new ConnectivityResources(mContext).get();
}
@VisibleForTesting
@@ -113,20 +117,19 @@
return -1;
}
- private static String getTransportName(final int transportType) {
- Resources r = Resources.getSystem();
- String[] networkTypes = r.getStringArray(R.array.network_switch_type_name);
+ private String getTransportName(final int transportType) {
+ String[] networkTypes = mResources.getStringArray(R.array.network_switch_type_name);
try {
return networkTypes[transportType];
} catch (IndexOutOfBoundsException e) {
- return r.getString(R.string.network_switch_type_name_unknown);
+ return mResources.getString(R.string.network_switch_type_name_unknown);
}
}
private static int getIcon(int transportType) {
return (transportType == TRANSPORT_WIFI)
- ? R.drawable.stat_notify_wifi_in_range : // TODO: Distinguish ! from ?.
- R.drawable.stat_notify_rssi_in_range;
+ ? R.drawable.stat_notify_wifi_in_range // TODO: Distinguish ! from ?.
+ : R.drawable.stat_notify_rssi_in_range;
}
/**
@@ -194,10 +197,10 @@
tag, nameOf(eventId), getTransportName(transportType), name, highPriority));
}
- Resources r = mContext.getResources();
+ final Resources r = mResources;
final CharSequence title;
final CharSequence details;
- int icon = getIcon(transportType);
+ Icon icon = Icon.createWithResource(r, getIcon(transportType));
if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) {
title = r.getString(R.string.wifi_no_internet, name);
details = r.getString(R.string.wifi_no_internet_detailed);
@@ -272,8 +275,7 @@
.setSmallIcon(icon)
.setAutoCancel(true)
.setTicker(title)
- .setColor(mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color))
+ .setColor(mContext.getColor(android.R.color.system_notification_accent_color))
.setContentTitle(title)
.setContentIntent(intent)
.setLocalOnly(true)
@@ -353,7 +355,7 @@
public void showToast(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) {
String fromTransport = getTransportName(approximateTransportType(fromNai));
String toTransport = getTransportName(approximateTransportType(toNai));
- String text = mContext.getResources().getString(
+ String text = mResources.getString(
R.string.network_switch_metered_toast, fromTransport, toTransport);
Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
}
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index f883307..f572b46 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -34,7 +34,6 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -105,7 +104,7 @@
PacProxyInstalledListener listener = new PacProxyInstalledListener(pacChangedEvent);
mPacProxyManager.addPacProxyInstalledListener(
- new HandlerExecutor(mConnectivityServiceHandler), listener);
+ mConnectivityServiceHandler::post, listener);
}
// Convert empty ProxyInfo's to null as null-checks are used to determine if proxies are present
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 2e61ae1..a4df43c 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -23,6 +23,7 @@
import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN;
import static android.os.PowerWhitelistManager.REASON_VPN;
+import static android.os.UserHandle.PER_USER_RANGE;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
@@ -69,8 +70,8 @@
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkProvider;
import android.net.NetworkRequest;
+import android.net.NetworkScore;
import android.net.RouteInfo;
-import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.UnderlyingNetworkInfo;
import android.net.VpnManager;
@@ -223,7 +224,7 @@
protected NetworkAgent mNetworkAgent;
private final Looper mLooper;
@VisibleForTesting
- protected final NetworkCapabilities mNetworkCapabilities;
+ protected NetworkCapabilities mNetworkCapabilities;
private final SystemServices mSystemServices;
private final Ikev2SessionCreator mIkev2SessionCreator;
private final UserManager mUserManager;
@@ -460,11 +461,12 @@
mLegacyState = LegacyVpnInfo.STATE_DISCONNECTED;
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE,
"" /* subtypeName */);
- mNetworkCapabilities = new NetworkCapabilities();
- mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
- mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
- mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
- mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE));
+ mNetworkCapabilities = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+ .build();
loadAlwaysOnPackage();
}
@@ -525,8 +527,10 @@
}
private void resetNetworkCapabilities() {
- mNetworkCapabilities.setUids(null);
- mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE));
+ mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
+ .setUids(null)
+ .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+ .build();
}
/**
@@ -1176,11 +1180,13 @@
if (!allowIPv4) {
lp.addRoute(new RouteInfo(new IpPrefix(
- NetworkStackConstants.IPV4_ADDR_ANY, 0), RTN_UNREACHABLE));
+ NetworkStackConstants.IPV4_ADDR_ANY, 0), null /*gateway*/,
+ null /*iface*/, RTN_UNREACHABLE));
}
if (!allowIPv6) {
lp.addRoute(new RouteInfo(new IpPrefix(
- NetworkStackConstants.IPV6_ADDR_ANY, 0), RTN_UNREACHABLE));
+ NetworkStackConstants.IPV6_ADDR_ANY, 0), null /*gateway*/,
+ null /*iface*/, RTN_UNREACHABLE));
}
// Concatenate search domains into a string.
@@ -1236,33 +1242,38 @@
// registered with registerDefaultNetworkCallback. This in turn protects the invariant
// that an app calling ConnectivityManager#bindProcessToNetwork(getDefaultNetwork())
// behaves the same as when it uses the default network.
- mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ final NetworkCapabilities.Builder capsBuilder =
+ new NetworkCapabilities.Builder(mNetworkCapabilities);
+ capsBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
mLegacyState = LegacyVpnInfo.STATE_CONNECTING;
updateState(DetailedState.CONNECTING, "agentConnect");
- NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
+ NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig.Builder().build();
networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown;
- mNetworkCapabilities.setOwnerUid(mOwnerUID);
- mNetworkCapabilities.setAdministratorUids(new int[] {mOwnerUID});
- mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserId,
+ capsBuilder.setOwnerUid(mOwnerUID);
+ capsBuilder.setAdministratorUids(new int[] {mOwnerUID});
+ capsBuilder.setUids(createUserAndRestrictedProfilesRanges(mUserId,
mConfig.allowedApplications, mConfig.disallowedApplications));
- mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
+ capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
// Only apps targeting Q and above can explicitly declare themselves as metered.
// These VPNs are assumed metered unless they state otherwise.
if (mIsPackageTargetingAtLeastQ && mConfig.isMetered) {
- mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_METERED);
+ capsBuilder.removeCapability(NET_CAPABILITY_NOT_METERED);
} else {
- mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
+ capsBuilder.addCapability(NET_CAPABILITY_NOT_METERED);
}
+ mNetworkCapabilities = capsBuilder.build();
mNetworkAgent = new NetworkAgent(mContext, mLooper, NETWORKTYPE /* logtag */,
- mNetworkCapabilities, lp, VPN_DEFAULT_SCORE, networkAgentConfig, mNetworkProvider) {
+ mNetworkCapabilities, lp,
+ new NetworkScore.Builder().setLegacyInt(VPN_DEFAULT_SCORE).build(),
+ networkAgentConfig, mNetworkProvider) {
@Override
- public void unwanted() {
+ public void onNetworkUnwanted() {
// We are user controlled, not driven by NetworkRequest.
}
};
@@ -1348,7 +1359,7 @@
String oldInterface = mInterface;
Connection oldConnection = mConnection;
NetworkAgent oldNetworkAgent = mNetworkAgent;
- Set<UidRange> oldUsers = mNetworkCapabilities.getUids();
+ Set<Range<Integer>> oldUsers = mNetworkCapabilities.getUids();
// Configure the interface. Abort if any of these steps fails.
ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
@@ -1423,7 +1434,8 @@
// restore old state
mConfig = oldConfig;
mConnection = oldConnection;
- mNetworkCapabilities.setUids(oldUsers);
+ mNetworkCapabilities =
+ new NetworkCapabilities.Builder(mNetworkCapabilities).setUids(oldUsers).build();
mNetworkAgent = oldNetworkAgent;
mInterface = oldInterface;
throw e;
@@ -1454,7 +1466,7 @@
}
/**
- * Creates a {@link Set} of non-intersecting {@link UidRange} objects including all UIDs
+ * Creates a {@link Set} of non-intersecting {@code Range<Integer>} objects including all UIDs
* associated with one user, and any restricted profiles attached to that user.
*
* <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
@@ -1467,10 +1479,10 @@
* @param disallowedApplications (optional) List of applications to deny.
*/
@VisibleForTesting
- Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userId,
+ Set<Range<Integer>> createUserAndRestrictedProfilesRanges(@UserIdInt int userId,
@Nullable List<String> allowedApplications,
@Nullable List<String> disallowedApplications) {
- final Set<UidRange> ranges = new ArraySet<>();
+ final Set<Range<Integer>> ranges = new ArraySet<>();
// Assign the top-level user to the set of ranges
addUserToRanges(ranges, userId, allowedApplications, disallowedApplications);
@@ -1494,20 +1506,20 @@
}
/**
- * Updates a {@link Set} of non-intersecting {@link UidRange} objects to include all UIDs
+ * Updates a {@link Set} of non-intersecting {@code Range<Integer>} objects to include all UIDs
* associated with one user.
*
* <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
* the UID ranges will match the app allowlist or denylist specified there. Otherwise, all UIDs
* in the user will be included.
*
- * @param ranges {@link Set} of {@link UidRange}s to which to add.
+ * @param ranges {@link Set} of {@code Range<Integer>}s to which to add.
* @param userId The userId to add to {@param ranges}.
* @param allowedApplications (optional) allowlist of applications to include.
* @param disallowedApplications (optional) denylist of applications to exclude.
*/
@VisibleForTesting
- void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userId,
+ void addUserToRanges(@NonNull Set<Range<Integer>> ranges, @UserIdInt int userId,
@Nullable List<String> allowedApplications,
@Nullable List<String> disallowedApplications) {
if (allowedApplications != null) {
@@ -1517,40 +1529,41 @@
if (start == -1) {
start = uid;
} else if (uid != stop + 1) {
- ranges.add(new UidRange(start, stop));
+ ranges.add(new Range<Integer>(start, stop));
start = uid;
}
stop = uid;
}
- if (start != -1) ranges.add(new UidRange(start, stop));
+ if (start != -1) ranges.add(new Range<Integer>(start, stop));
} else if (disallowedApplications != null) {
// Add all ranges for user skipping UIDs for disallowedApplications.
- final UidRange userRange = UidRange.createForUser(UserHandle.of(userId));
- int start = userRange.start;
+ final Range<Integer> userRange = createUidRangeForUser(userId);
+ int start = userRange.getLower();
for (int uid : getAppsUids(disallowedApplications, userId)) {
if (uid == start) {
start++;
} else {
- ranges.add(new UidRange(start, uid - 1));
+ ranges.add(new Range<Integer>(start, uid - 1));
start = uid + 1;
}
}
- if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop));
+ if (start <= userRange.getUpper()) {
+ ranges.add(new Range<Integer>(start, userRange.getUpper()));
+ }
} else {
// Add all UIDs for the user.
- ranges.add(UidRange.createForUser(UserHandle.of(userId)));
+ ranges.add(createUidRangeForUser(userId));
}
}
// Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that
// apply to userId.
- private static List<UidRange> uidRangesForUser(int userId, Set<UidRange> existingRanges) {
- // UidRange#createForUser returns the entire range of UIDs available to a macro-user.
- // This is something like 0-99999 ; {@see UserHandle#PER_USER_RANGE}
- final UidRange userRange = UidRange.createForUser(UserHandle.of(userId));
- final List<UidRange> ranges = new ArrayList<>();
- for (UidRange range : existingRanges) {
- if (userRange.containsRange(range)) {
+ private static List<Range<Integer>> uidRangesForUser(int userId,
+ Set<Range<Integer>> existingRanges) {
+ final Range<Integer> userRange = createUidRangeForUser(userId);
+ final List<Range<Integer>> ranges = new ArrayList<>();
+ for (Range<Integer> range : existingRanges) {
+ if (userRange.contains(range)) {
ranges.add(range);
}
}
@@ -1567,12 +1580,13 @@
UserInfo user = mUserManager.getUserInfo(userId);
if (user.isRestricted() && user.restrictedProfileParentId == mUserId) {
synchronized(Vpn.this) {
- final Set<UidRange> existingRanges = mNetworkCapabilities.getUids();
+ final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids();
if (existingRanges != null) {
try {
addUserToRanges(existingRanges, userId, mConfig.allowedApplications,
mConfig.disallowedApplications);
- mNetworkCapabilities.setUids(existingRanges);
+ mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
+ .setUids(existingRanges).build();
} catch (Exception e) {
Log.wtf(TAG, "Failed to add restricted user to owner", e);
}
@@ -1595,13 +1609,14 @@
UserInfo user = mUserManager.getUserInfo(userId);
if (user.isRestricted() && user.restrictedProfileParentId == mUserId) {
synchronized(Vpn.this) {
- final Set<UidRange> existingRanges = mNetworkCapabilities.getUids();
+ final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids();
if (existingRanges != null) {
try {
- final List<UidRange> removedRanges =
+ final List<Range<Integer>> removedRanges =
uidRangesForUser(userId, existingRanges);
existingRanges.removeAll(removedRanges);
- mNetworkCapabilities.setUids(existingRanges);
+ mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
+ .setUids(existingRanges).build();
} catch (Exception e) {
Log.wtf(TAG, "Failed to remove restricted user to owner", e);
}
@@ -1659,7 +1674,7 @@
final Set<UidRangeParcel> rangesToRemove = new ArraySet<>(mBlockedUidsAsToldToConnectivity);
final Set<UidRangeParcel> rangesToAdd;
if (enforce) {
- final Set<UidRange> restrictedProfilesRanges =
+ final Set<Range<Integer>> restrictedProfilesRanges =
createUserAndRestrictedProfilesRanges(mUserId,
/* allowedApplications */ null,
/* disallowedApplications */ exemptedPackages);
@@ -1668,11 +1683,12 @@
// The UID range of the first user (0-99999) would block the IPSec traffic, which comes
// directly from the kernel and is marked as uid=0. So we adjust the range to allow
// it through (b/69873852).
- for (UidRange range : restrictedProfilesRanges) {
- if (range.start == 0 && range.stop != 0) {
- rangesThatShouldBeBlocked.add(new UidRangeParcel(1, range.stop));
- } else if (range.start != 0) {
- rangesThatShouldBeBlocked.add(new UidRangeParcel(range.start, range.stop));
+ for (Range<Integer> range : restrictedProfilesRanges) {
+ if (range.getLower() == 0 && range.getUpper() != 0) {
+ rangesThatShouldBeBlocked.add(new UidRangeParcel(1, range.getUpper()));
+ } else if (range.getLower() != 0) {
+ rangesThatShouldBeBlocked.add(
+ new UidRangeParcel(range.getLower(), range.getUpper()));
}
}
@@ -1694,12 +1710,12 @@
}
/**
- * Tell ConnectivityService to add or remove a list of {@link UidRange}s to the list of UIDs
- * that are only allowed to make connections through sockets that have had {@code protect()}
- * called on them.
+ * Tell ConnectivityService to add or remove a list of {@link UidRangeParcel}s to the list of
+ * UIDs that are only allowed to make connections through sockets that have had
+ * {@code protect()} called on them.
*
* @param enforce {@code true} to add to the denylist, {@code false} to remove.
- * @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is
+ * @param ranges {@link Collection} of {@link UidRangeParcel}s to add (if {@param enforce} is
* {@code true}) or to remove.
* @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise,
* including added ranges that already existed or removed ones that didn't.
@@ -1881,7 +1897,12 @@
if (!isRunningLocked()) {
return false;
}
- return mNetworkCapabilities.appliesToUid(uid);
+ final Set<Range<Integer>> uids = mNetworkCapabilities.getUids();
+ if (uids == null) return true;
+ for (final Range<Integer> range : uids) {
+ if (range.contains(uid)) return true;
+ }
+ return false;
}
/**
@@ -2698,7 +2719,8 @@
mConfig.routes.clear();
for (final RouteInfo route : oldRoutes) {
- mConfig.routes.add(new RouteInfo(route.getDestination(), RTN_UNREACHABLE));
+ mConfig.routes.add(new RouteInfo(route.getDestination(), null /*gateway*/,
+ null /*iface*/, RTN_UNREACHABLE));
}
if (mNetworkAgent != null) {
mNetworkAgent.sendLinkProperties(makeLinkProperties());
@@ -3037,10 +3059,12 @@
// Add a throw route for the VPN server endpoint, if one was specified.
if (endpointAddress instanceof Inet4Address) {
mConfig.routes.add(new RouteInfo(
- new IpPrefix(endpointAddress, 32), RTN_THROW));
+ new IpPrefix(endpointAddress, 32), null /*gateway*/,
+ null /*iface*/, RTN_THROW));
} else if (endpointAddress instanceof Inet6Address) {
mConfig.routes.add(new RouteInfo(
- new IpPrefix(endpointAddress, 128), RTN_THROW));
+ new IpPrefix(endpointAddress, 128), null /*gateway*/,
+ null /*iface*/, RTN_THROW));
} else {
Log.e(TAG, "Unknown IP address family for VPN endpoint: "
+ endpointAddress);
@@ -3340,4 +3364,12 @@
firstChildSessionCallback);
}
}
+
+ /**
+ * Returns the entire range of UIDs available to a macro-user. This is something like 0-99999.
+ */
+ @VisibleForTesting
+ static Range<Integer> createUidRangeForUser(int userId) {
+ return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1);
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
index fa03e59..47eb3eb 100644
--- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
+++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
@@ -405,7 +405,8 @@
for (final IkeTrafficSelector selector : trafficSelectors) {
for (final IpPrefix prefix :
new IpRange(selector.startingAddress, selector.endingAddress).asIpPrefixes()) {
- routes.add(new RouteInfo(prefix, null));
+ routes.add(new RouteInfo(prefix, null /*gateway*/, null /*iface*/,
+ RouteInfo.RTN_UNICAST));
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 251b579..1261296 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -652,8 +652,11 @@
builder.setPackageName(parser.getAttributeValue(null, ATTR_PACKAGE_NAME));
builder.setUserId(mInjector.getUserId(mUserManager,
parser.getAttributeInt(null, ATTR_USER)));
- builder.setUniqueDisplayId(
- parser.getAttributeValue(null, ATTR_UNIQUE_DISPLAY_ID));
+ String uniqueDisplayId = parser.getAttributeValue(null, ATTR_UNIQUE_DISPLAY_ID);
+ if (uniqueDisplayId == null) {
+ uniqueDisplayId = "";
+ }
+ builder.setUniqueDisplayId(uniqueDisplayId);
builder.setBatteryLevel(parser.getAttributeFloat(null, ATTR_BATTERY_LEVEL));
builder.setNightMode(parser.getAttributeBoolean(null, ATTR_NIGHT_MODE));
builder.setColorTemperature(
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 82ca820..c010906 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -20,6 +20,7 @@
import static android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT;
import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+import static android.hardware.display.DisplayManager.EventsMask;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
@@ -28,6 +29,7 @@
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
+import static android.hardware.display.DisplayManagerGlobal.DisplayEvent;
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
@@ -125,6 +127,7 @@
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
/**
@@ -820,14 +823,16 @@
}
private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid,
- int callingUid) {
+ int callingUid, @EventsMask long eventsMask) {
synchronized (mSyncRoot) {
- if (mCallbacks.get(callingPid) != null) {
- throw new SecurityException("The calling process has already "
- + "registered an IDisplayManagerCallback.");
+ CallbackRecord record = mCallbacks.get(callingPid);
+
+ if (record != null) {
+ record.updateEventsMask(eventsMask);
+ return;
}
- CallbackRecord record = new CallbackRecord(callingPid, callingUid, callback);
+ record = new CallbackRecord(callingPid, callingUid, callback, eventsMask);
try {
IBinder binder = callback.asBinder();
binder.linkToDeath(record, 0);
@@ -1129,8 +1134,13 @@
recordStableDisplayStatsIfNeededLocked(display);
recordTopInsetLocked(display);
}
- addDisplayPowerControllerLocked(display);
- mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
+ final int groupId = mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(displayId);
+ if (groupId != Display.INVALID_DISPLAY_GROUP) {
+ addDisplayPowerControllerLocked(display);
+ mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
+ } else {
+ mDisplayStates.append(displayId, Display.STATE_ON);
+ }
mDisplayBrightnesses.append(displayId, display.getDisplayInfoLocked().brightnessDefault);
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
@@ -1209,8 +1219,7 @@
final int displayId = display.getDisplayIdLocked();
final int state = mDisplayStates.get(displayId);
- // Only send a request for display state if the display state has already been
- // initialized by DisplayPowercontroller.
+ // Only send a request for display state if display state has already been initialized.
if (state != Display.STATE_UNKNOWN) {
final float brightness = mDisplayBrightnesses.get(displayId);
return device.requestDisplayStateLocked(state, brightness);
@@ -1695,7 +1704,7 @@
}
}
- private void sendDisplayEventLocked(int displayId, int event) {
+ private void sendDisplayEventLocked(int displayId, @DisplayEvent int event) {
Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
mHandler.sendMessage(msg);
}
@@ -1724,7 +1733,8 @@
// Runs on Handler thread.
// Delivers display event notifications to callbacks.
- private void deliverDisplayEvent(int displayId, ArraySet<Integer> uids, int event) {
+ private void deliverDisplayEvent(int displayId, ArraySet<Integer> uids,
+ @DisplayEvent int event) {
if (DEBUG) {
Slog.d(TAG, "Delivering display event: displayId="
+ displayId + ", event=" + event);
@@ -2059,13 +2069,20 @@
public final int mPid;
public final int mUid;
private final IDisplayManagerCallback mCallback;
+ private @EventsMask AtomicLong mEventsMask;
public boolean mWifiDisplayScanRequested;
- CallbackRecord(int pid, int uid, IDisplayManagerCallback callback) {
+ CallbackRecord(int pid, int uid, IDisplayManagerCallback callback,
+ @EventsMask long eventsMask) {
mPid = pid;
mUid = uid;
mCallback = callback;
+ mEventsMask = new AtomicLong(eventsMask);
+ }
+
+ public void updateEventsMask(@EventsMask long eventsMask) {
+ mEventsMask.set(eventsMask);
}
@Override
@@ -2076,7 +2093,11 @@
onCallbackDied(this);
}
- public void notifyDisplayEventAsync(int displayId, int event) {
+ public void notifyDisplayEventAsync(int displayId, @DisplayEvent int event) {
+ if (!shouldSendEvent(event)) {
+ return;
+ }
+
try {
mCallback.onDisplayEvent(displayId, event);
} catch (RemoteException ex) {
@@ -2085,6 +2106,22 @@
binderDied();
}
}
+
+ private boolean shouldSendEvent(@DisplayEvent int event) {
+ final long mask = mEventsMask.get();
+ switch (event) {
+ case DisplayManagerGlobal.EVENT_DISPLAY_ADDED:
+ return (mask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0;
+ case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED:
+ return (mask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0;
+ case DisplayManagerGlobal.EVENT_DISPLAY_REMOVED:
+ return (mask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0;
+ default:
+ // This should never happen.
+ Slog.e(TAG, "Unknown display event " + event);
+ return true;
+ }
+ }
}
@VisibleForTesting
@@ -2149,6 +2186,14 @@
@Override // Binder call
public void registerCallback(IDisplayManagerCallback callback) {
+ registerCallbackWithEventMask(callback, DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+ }
+
+ @Override // Binder call
+ public void registerCallbackWithEventMask(IDisplayManagerCallback callback,
+ @EventsMask long eventsMask) {
if (callback == null) {
throw new IllegalArgumentException("listener must not be null");
}
@@ -2157,7 +2202,7 @@
final int callingUid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- registerCallbackInternal(callback, callingPid, callingUid);
+ registerCallbackInternal(callback, callingPid, callingUid, eventsMask);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index fcfa674..6c2e6eb 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -433,31 +433,37 @@
final int displayId = display.getDisplayIdLocked();
// Get current display group data
- int groupId = getDisplayGroupIdFromDisplayIdLocked(displayId);
+ final int groupId = getDisplayGroupIdFromDisplayIdLocked(displayId);
final DisplayGroup oldGroup = getDisplayGroupLocked(groupId);
// Get the new display group if a change is needed
final DisplayInfo info = display.getDisplayInfoLocked();
final boolean needsOwnDisplayGroup = (info.flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0;
final boolean hasOwnDisplayGroup = groupId != Display.DEFAULT_DISPLAY_GROUP;
- if (groupId == Display.INVALID_DISPLAY_GROUP
- || hasOwnDisplayGroup != needsOwnDisplayGroup) {
- groupId = assignDisplayGroupIdLocked(needsOwnDisplayGroup);
- }
-
- // Create a new group if needed
- DisplayGroup newGroup = getDisplayGroupLocked(groupId);
- if (newGroup == null) {
- newGroup = new DisplayGroup(groupId);
- mDisplayGroups.append(groupId, newGroup);
- }
- if (oldGroup != newGroup) {
+ final boolean needsDisplayGroup = needsOwnDisplayGroup || info.type == Display.TYPE_INTERNAL
+ || info.type == Display.TYPE_EXTERNAL;
+ if (!needsDisplayGroup) {
if (oldGroup != null) {
oldGroup.removeDisplayLocked(display);
}
+ return;
+ }
+ if (groupId == Display.INVALID_DISPLAY_GROUP
+ || hasOwnDisplayGroup != needsOwnDisplayGroup) {
+ if (oldGroup != null) {
+ oldGroup.removeDisplayLocked(display);
+ }
+
+ final int newGroupId = assignDisplayGroupIdLocked(needsOwnDisplayGroup);
+ // Create a new group if needed
+ DisplayGroup newGroup = getDisplayGroupLocked(newGroupId);
+ if (newGroup == null) {
+ newGroup = new DisplayGroup(newGroupId);
+ mDisplayGroups.append(newGroupId, newGroup);
+ }
newGroup.addDisplayLocked(display);
- display.updateDisplayGroupIdLocked(groupId);
- Slog.i(TAG, "Setting new display group " + groupId + " for display "
+ display.updateDisplayGroupIdLocked(newGroupId);
+ Slog.i(TAG, "Setting new display group " + newGroupId + " for display "
+ displayId + ", from previous group: "
+ (oldGroup != null ? oldGroup.getGroupId() : "null"));
}
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java b/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java
index b4555f8..7d9b0aa 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java
@@ -28,7 +28,7 @@
+ " Shows this message.\n"
+ " set-saturation LEVEL\n"
+ " Sets the device saturation to the given LEVEL, 0-100 inclusive.\n"
- + " set-layer-saturation CALLER_PACKAGE TARGET_PACKAGE LEVEL\n"
+ + " set-layer-saturation LEVEL CALLER_PACKAGE TARGET_PACKAGE\n"
+ " Sets the saturation LEVEL for all layers of the TARGET_PACKAGE, attributed\n"
+ " to the CALLER_PACKAGE. The lowest LEVEL from any CALLER_PACKAGE is applied.\n";
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index cbe6e69..0925027 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -2606,6 +2606,11 @@
}
// Native callback
+ private void notifyDropWindow(IBinder token, float x, float y) {
+ mWindowManagerCallbacks.notifyDropWindow(token, x, y);
+ }
+
+ // Native callback
private void notifyUntrustedTouch(String packageName) {
// TODO(b/169067926): Remove toast after gathering feedback on dogfood.
if (!UNTRUSTED_TOUCHES_TOAST || ArrayUtils.contains(
@@ -3035,6 +3040,11 @@
* Called when the focused window has changed.
*/
void notifyFocusChanged(IBinder oldToken, IBinder newToken);
+
+ /**
+ * Called when the drag over window has changed.
+ */
+ void notifyDropWindow(IBinder token, float x, float y);
}
/**
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 0fa6283..350563f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -174,7 +174,6 @@
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
-import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
@@ -1217,10 +1216,11 @@
private static boolean updateCapabilityChange(SparseBooleanArray lastValues, boolean newValue,
Network network) {
- final boolean lastValue = lastValues.get(network.netId, false);
- final boolean changed = (lastValue != newValue) || lastValues.indexOfKey(network.netId) < 0;
+ final boolean lastValue = lastValues.get(network.getNetId(), false);
+ final boolean changed = (lastValue != newValue)
+ || lastValues.indexOfKey(network.getNetId()) < 0;
if (changed) {
- lastValues.put(network.netId, newValue);
+ lastValues.put(network.getNetId(), newValue);
}
return changed;
}
@@ -1243,7 +1243,7 @@
mNetworkRoaming, newRoaming, network);
if (meteredChanged || roamingChanged) {
- mLogger.meterednessChanged(network.netId, newMetered);
+ mLogger.meterednessChanged(network.getNetId(), newMetered);
updateNetworkRulesNL();
}
}
@@ -2009,7 +2009,7 @@
mNetIdToSubId.clear();
final ArrayMap<NetworkStateSnapshot, NetworkIdentity> identified = new ArrayMap<>();
for (final NetworkStateSnapshot snapshot : snapshots) {
- mNetIdToSubId.put(snapshot.network.netId, parseSubId(snapshot));
+ mNetIdToSubId.put(snapshot.network.getNetId(), parseSubId(snapshot));
// Policies matched by NPMS only match by subscriber ID or by ssid. Thus subtype
// in the object created here is never used and its value doesn't matter, so use
@@ -5778,7 +5778,7 @@
@GuardedBy("mNetworkPoliciesSecondLock")
private int getSubIdLocked(Network network) {
- return mNetIdToSubId.get(network.netId, INVALID_SUBSCRIPTION_ID);
+ return mNetIdToSubId.get(network.getNetId(), INVALID_SUBSCRIPTION_ID);
}
@GuardedBy("mNetworkPoliciesSecondLock")
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e588366..eb4f9d3 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3576,15 +3576,30 @@
pkg, uid, channelId, conversationId, true, includeDeleted);
}
+ // Returns 'true' if the given channel has a notification associated
+ // with an active foreground service.
+ private void enforceDeletingChannelHasNoFgService(String pkg, int userId,
+ String channelId) {
+ if (mAmi.hasForegroundServiceNotification(pkg, userId, channelId)) {
+ Slog.w(TAG, "Package u" + userId + "/" + pkg
+ + " may not delete notification channel '"
+ + channelId + "' with fg service");
+ throw new SecurityException("Not allowed to delete channel " + channelId
+ + " with a foreground service");
+ }
+ }
+
@Override
public void deleteNotificationChannel(String pkg, String channelId) {
checkCallerIsSystemOrSameApp(pkg);
final int callingUid = Binder.getCallingUid();
+ final int callingUser = UserHandle.getUserId(callingUid);
if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
throw new IllegalArgumentException("Cannot delete default channel");
}
+ enforceDeletingChannelHasNoFgService(pkg, callingUser, channelId);
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true,
- UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
+ callingUser, REASON_CHANNEL_BANNED, null);
mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, channelId);
mListeners.notifyNotificationChannelChanged(pkg,
UserHandle.getUserHandleForUid(callingUid),
@@ -3597,19 +3612,23 @@
public void deleteConversationNotificationChannels(String pkg, int uid,
String conversationId) {
checkCallerIsSystem();
- final int callingUid = Binder.getCallingUid();
List<NotificationChannel> channels =
mPreferencesHelper.getNotificationChannelsByConversationId(
pkg, uid, conversationId);
if (!channels.isEmpty()) {
+ // Preflight for fg service notifications in these channels: do nothing
+ // unless they're all eligible
+ final int appUserId = UserHandle.getUserId(uid);
for (NotificationChannel nc : channels) {
+ final String channelId = nc.getId();
+ mAmi.stopForegroundServicesForChannel(pkg, appUserId, channelId);
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, nc.getId(), 0, 0, true,
- UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
- mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, nc.getId());
+ appUserId, REASON_CHANNEL_BANNED, null);
+ mPreferencesHelper.deleteNotificationChannel(pkg, uid, channelId);
mListeners.notifyNotificationChannelChanged(pkg,
- UserHandle.getUserHandleForUid(callingUid),
+ UserHandle.getUserHandleForUid(uid),
mPreferencesHelper.getNotificationChannel(
- pkg, callingUid, nc.getId(), true),
+ pkg, uid, channelId, true),
NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
}
handleSavePolicyFile();
@@ -3640,13 +3659,20 @@
NotificationChannelGroup groupToDelete =
mPreferencesHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
if (groupToDelete != null) {
+ // Preflight for allowability
+ final int userId = UserHandle.getUserId(callingUid);
+ List<NotificationChannel> groupChannels = groupToDelete.getChannels();
+ for (int i = 0; i < groupChannels.size(); i++) {
+ enforceDeletingChannelHasNoFgService(pkg, userId,
+ groupChannels.get(i).getId());
+ }
List<NotificationChannel> deletedChannels =
mPreferencesHelper.deleteNotificationChannelGroup(pkg, callingUid, groupId);
for (int i = 0; i < deletedChannels.size(); i++) {
final NotificationChannel deletedChannel = deletedChannels.get(i);
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannel.getId(), 0, 0,
true,
- UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED,
+ userId, REASON_CHANNEL_BANNED,
null);
mListeners.notifyNotificationChannelChanged(pkg,
UserHandle.getUserHandleForUid(callingUid),
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index dbd1211..27b1648 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -103,7 +103,6 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
/**
@@ -312,7 +311,7 @@
// Initialize any users that can't be switched to, as their state would
// never be setup in onSwitchUser(). We will switch to the system user right
// after this, and its state will be setup there.
- updatePackageManager(mImpl.updateOverlaysForUser(users.get(i).id));
+ updatePackageManagerLocked(mImpl.updateOverlaysForUser(users.get(i).id));
}
}
}
@@ -329,9 +328,8 @@
// ensure overlays in the settings are up-to-date, and propagate
// any asset changes to the rest of the system
synchronized (mLock) {
- updateActivityManager(updatePackageManager(mImpl.updateOverlaysForUser(newUserId)));
+ updateTargetPackagesLocked(mImpl.updateOverlaysForUser(newUserId));
}
- persistSettings();
} finally {
traceEnd(TRACE_TAG_RRO);
}
@@ -415,7 +413,8 @@
packageName, userId);
if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
try {
- updateTargetPackages(mImpl.onPackageAdded(packageName, userId));
+ updateTargetPackagesLocked(
+ mImpl.onPackageAdded(packageName, userId));
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageAdded internal error", e);
}
@@ -437,7 +436,8 @@
packageName, userId);
if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
try {
- updateTargetPackages(mImpl.onPackageChanged(packageName, userId));
+ updateTargetPackagesLocked(
+ mImpl.onPackageChanged(packageName, userId));
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageChanged internal error", e);
}
@@ -459,7 +459,8 @@
packageName, userId);
if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
try {
- updateTargetPackages(mImpl.onPackageReplacing(packageName, userId));
+ updateTargetPackagesLocked(
+ mImpl.onPackageReplacing(packageName, userId));
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageReplacing internal error", e);
}
@@ -481,7 +482,8 @@
packageName, userId);
if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
try {
- updateTargetPackages(mImpl.onPackageReplaced(packageName, userId));
+ updateTargetPackagesLocked(
+ mImpl.onPackageReplaced(packageName, userId));
} catch (OperationFailedException e) {
Slog.e(TAG, "onPackageReplaced internal error", e);
}
@@ -500,7 +502,7 @@
for (int userId : userIds) {
synchronized (mLock) {
mPackageManager.onPackageRemoved(packageName, userId);
- updateTargetPackages(mImpl.onPackageRemoved(packageName, userId));
+ updateTargetPackagesLocked(mImpl.onPackageRemoved(packageName, userId));
}
}
} finally {
@@ -519,7 +521,7 @@
try {
traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED");
synchronized (mLock) {
- updatePackageManager(mImpl.updateOverlaysForUser(userId));
+ updatePackageManagerLocked(mImpl.updateOverlaysForUser(userId));
}
} finally {
traceEnd(TRACE_TAG_RRO);
@@ -624,7 +626,8 @@
try {
synchronized (mLock) {
try {
- updateTargetPackages(mImpl.setEnabled(overlay, enable, realUserId));
+ updateTargetPackagesLocked(
+ mImpl.setEnabled(overlay, enable, realUserId));
return true;
} catch (OperationFailedException e) {
return false;
@@ -656,9 +659,10 @@
try {
synchronized (mLock) {
try {
- mImpl.setEnabledExclusive(overlay,
- false /* withinCategory */, realUserId)
- .ifPresent(OverlayManagerService.this::updateTargetPackages);
+ mImpl.setEnabledExclusive(
+ overlay, false /* withinCategory */, realUserId)
+ .ifPresent(
+ OverlayManagerService.this::updateTargetPackagesLocked);
return true;
} catch (OperationFailedException e) {
return false;
@@ -693,7 +697,7 @@
try {
mImpl.setEnabledExclusive(overlay,
true /* withinCategory */, realUserId)
- .ifPresent(OverlayManagerService.this::updateTargetPackages);
+ .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);
return true;
} catch (OperationFailedException e) {
return false;
@@ -728,7 +732,7 @@
synchronized (mLock) {
try {
mImpl.setPriority(overlay, parentOverlay, realUserId)
- .ifPresent(OverlayManagerService.this::updateTargetPackages);
+ .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);
return true;
} catch (OperationFailedException e) {
return false;
@@ -759,7 +763,8 @@
try {
synchronized (mLock) {
try {
- updateTargetPackages(mImpl.setHighestPriority(overlay, realUserId));
+ updateTargetPackagesLocked(
+ mImpl.setHighestPriority(overlay, realUserId));
return true;
} catch (OperationFailedException e) {
return false;
@@ -791,7 +796,7 @@
synchronized (mLock) {
try {
mImpl.setLowestPriority(overlay, realUserId)
- .ifPresent(OverlayManagerService.this::updateTargetPackages);
+ .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);
return true;
} catch (OperationFailedException e) {
return false;
@@ -945,27 +950,12 @@
throw new IllegalArgumentException("null transaction");
}
- // map: userId -> set<package-name>: target packages of overlays in
- // this transaction
- final SparseArray<Set<String>> transactionTargets = new SparseArray<>();
-
- // map: userId -> set<package-name>: packages that need to reload
- // their resources due to changes to the overlays in this
- // transaction
- final SparseArray<List<String>> affectedPackagesToUpdate = new SparseArray<>();
-
synchronized (mLock) {
// execute the requests (as calling user)
+ Set<PackageAndUser> affectedPackagesToUpdate = null;
for (final OverlayManagerTransaction.Request request : transaction) {
- executeRequest(request).forEach(
- target -> {
- Set<String> userTargets = transactionTargets.get(target.userId);
- if (userTargets == null) {
- userTargets = new ArraySet<>();
- transactionTargets.put(target.userId, userTargets);
- }
- userTargets.add(target.packageName);
- });
+ affectedPackagesToUpdate = CollectionUtils.addAll(affectedPackagesToUpdate,
+ executeRequest(request));
}
// past the point of no return: the entire transaction has been
@@ -973,37 +963,11 @@
// system_server
final long ident = Binder.clearCallingIdentity();
try {
- persistSettings();
-
- // inform the package manager about the new paths
- for (int index = 0; index < transactionTargets.size(); index++) {
- final int userId = transactionTargets.keyAt(index);
- final List<String> affectedTargets =
- updatePackageManager(transactionTargets.valueAt(index), userId);
- affectedPackagesToUpdate.put(userId, affectedTargets);
- }
+ updateTargetPackagesLocked(affectedPackagesToUpdate);
} finally {
Binder.restoreCallingIdentity(ident);
}
- } // synchronized (mLock)
-
- FgThread.getHandler().post(() -> {
- final long ident = Binder.clearCallingIdentity();
- try {
- // schedule apps to refresh
- updateActivityManager(affectedPackagesToUpdate);
-
- // broadcast the ACTION_OVERLAY_CHANGED intents
- for (int index = 0; index < transactionTargets.size(); index++) {
- final int userId = transactionTargets.keyAt(index);
- for (String pkg: transactionTargets.valueAt(index)) {
- broadcastActionOverlayChanged(pkg, userId);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- });
+ }
}
@Override
@@ -1382,32 +1346,37 @@
}
}
- private void updateTargetPackages(@Nullable PackageAndUser updatedTarget) {
+ private void updateTargetPackagesLocked(@Nullable PackageAndUser updatedTarget) {
if (updatedTarget != null) {
- updateTargetPackages(Set.of(updatedTarget));
+ updateTargetPackagesLocked(Set.of(updatedTarget));
}
}
- private void updateTargetPackages(@Nullable Set<PackageAndUser> updatedTargets) {
+ private void updateTargetPackagesLocked(@Nullable Set<PackageAndUser> updatedTargets) {
if (CollectionUtils.isEmpty(updatedTargets)) {
return;
}
- persistSettings();
+ persistSettingsLocked();
final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(updatedTargets);
- FgThread.getHandler().post(() -> {
- for (int i = 0, n = userTargets.size(); i < n; i++) {
- final ArraySet<String> targets = userTargets.valueAt(i);
- final int userId = userTargets.keyAt(i);
+ for (int i = 0, n = userTargets.size(); i < n; i++) {
+ final ArraySet<String> targets = userTargets.valueAt(i);
+ final int userId = userTargets.keyAt(i);
+ final List<String> affectedPackages = updatePackageManagerLocked(targets, userId);
+ if (affectedPackages.isEmpty()) {
+ // The package manager paths are already up-to-date.
+ continue;
+ }
- // Update the overlay paths in package manager.
- final List<String> affectedPackages = updatePackageManager(targets, userId);
+ FgThread.getHandler().post(() -> {
+ // Send configuration changed events for all target packages that have been affected
+ // by overlay state changes.
updateActivityManager(affectedPackages, userId);
- // Overlays targeting shared libraries may cause more packages to need to be
- // refreshed.
+ // Do not send broadcasts for all affected targets. Overlays targeting the framework
+ // or shared libraries may cause too many broadcasts to be sent at once.
broadcastActionOverlayChanged(targets, userId);
- }
- });
+ });
+ }
}
@Nullable
@@ -1430,20 +1399,17 @@
private static void broadcastActionOverlayChanged(@NonNull final Set<String> targetPackages,
final int userId) {
- CollectionUtils.forEach(targetPackages,
- target -> broadcastActionOverlayChanged(target, userId));
- }
-
- private static void broadcastActionOverlayChanged(String targetPackage, final int userId) {
- final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
- Uri.fromParts("package", targetPackage, null));
- intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- try {
- ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null, null,
- null, android.app.AppOpsManager.OP_NONE, null, false, false, userId);
- } catch (RemoteException e) {
- // Intentionally left empty.
- }
+ CollectionUtils.forEach(targetPackages, target -> {
+ final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
+ Uri.fromParts("package", target, null));
+ intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ try {
+ ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null,
+ null, null, android.app.AppOpsManager.OP_NONE, null, false, false, userId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "broadcastActionOverlayChanged remote exception", e);
+ }
+ });
}
/**
@@ -1455,18 +1421,13 @@
try {
am.scheduleApplicationInfoChanged(targetPackageNames, userId);
} catch (RemoteException e) {
- // Intentionally left empty.
- }
- }
-
- private void updateActivityManager(@NonNull SparseArray<List<String>> targetPackageNames) {
- for (int i = 0, n = targetPackageNames.size(); i < n; i++) {
- updateActivityManager(targetPackageNames.valueAt(i), targetPackageNames.keyAt(i));
+ Slog.e(TAG, "updateActivityManager remote exception", e);
}
}
@NonNull
- private SparseArray<List<String>> updatePackageManager(@Nullable Set<PackageAndUser> targets) {
+ private SparseArray<List<String>> updatePackageManagerLocked(
+ @Nullable Set<PackageAndUser> targets) {
if (CollectionUtils.isEmpty(targets)) {
return new SparseArray<>();
}
@@ -1474,7 +1435,7 @@
final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(targets);
for (int i = 0, n = userTargets.size(); i < n; i++) {
final int userId = userTargets.keyAt(i);
- affectedTargets.put(userId, updatePackageManager(userTargets.valueAt(i), userId));
+ affectedTargets.put(userId, updatePackageManagerLocked(userTargets.valueAt(i), userId));
}
return affectedTargets;
}
@@ -1485,10 +1446,10 @@
* targetPackageNames: the target themselves and shared libraries)
*/
@NonNull
- private List<String> updatePackageManager(@NonNull Collection<String> targetPackageNames,
+ private List<String> updatePackageManagerLocked(@NonNull Collection<String> targetPackageNames,
final int userId) {
try {
- traceBegin(TRACE_TAG_RRO, "OMS#updatePackageManager " + targetPackageNames);
+ traceBegin(TRACE_TAG_RRO, "OMS#updatePackageManagerLocked " + targetPackageNames);
if (DEBUG) {
Slog.d(TAG, "Update package manager about changed overlays");
}
@@ -1535,20 +1496,18 @@
}
}
- private void persistSettings() {
+ private void persistSettingsLocked() {
if (DEBUG) {
Slog.d(TAG, "Writing overlay settings");
}
- synchronized (mLock) {
- FileOutputStream stream = null;
- try {
- stream = mSettingsFile.startWrite();
- mSettings.persist(stream);
- mSettingsFile.finishWrite(stream);
- } catch (IOException | XmlPullParserException e) {
- mSettingsFile.failWrite(stream);
- Slog.e(TAG, "failed to persist overlay state", e);
- }
+ FileOutputStream stream = null;
+ try {
+ stream = mSettingsFile.startWrite();
+ mSettings.persist(stream);
+ mSettingsFile.finishWrite(stream);
+ } catch (IOException | XmlPullParserException e) {
+ mSettingsFile.failWrite(stream);
+ Slog.e(TAG, "failed to persist overlay state", e);
}
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
index aae6ce4..791a105 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.WatchableIntentResolver;
+import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
import java.util.List;
@@ -28,7 +28,7 @@
* Used to find a list of {@link CrossProfileIntentFilter}s that match an intent.
*/
class CrossProfileIntentResolver
- extends WatchableIntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter>
+ extends WatchedIntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter>
implements Snappable {
@Override
protected CrossProfileIntentFilter[] newArray(int size) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ff042c2..43eeb2a5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -27324,31 +27324,8 @@
return PackageManagerService.this.getPackageStartability(
packageName, callingUid, userId) == PACKAGE_STARTABILITY_FROZEN;
}
-
- @Override
- public boolean isPackageUsesPermissionNeverForLocation(@NonNull String packageName,
- @NonNull String permissionName) {
- Objects.requireNonNull(packageName);
- Objects.requireNonNull(permissionName);
- final AndroidPackage pkg;
- synchronized (mLock) {
- pkg = mPackages.get(packageName);
- }
- if (pkg == null) return false;
- final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions();
- final int size = usesPermissions.size();
- for (int i = 0; i < size; i++) {
- final ParsedUsesPermission usesPermission = usesPermissions.get(i);
- if (Objects.equals(usesPermission.name, permissionName)) {
- return (usesPermission.usesPermissionFlags
- & ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0;
- }
- }
- return false;
- }
}
-
@GuardedBy("mLock")
private SparseArray<String> getAppsWithSharedUserIdsLocked() {
final SparseArray<String> sharedUserIds = new SparseArray<>();
diff --git a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
index c1bfcac..2b11a42 100644
--- a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
@@ -19,11 +19,11 @@
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.WatchableIntentResolver;
+import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
public class PersistentPreferredIntentResolver
- extends WatchableIntentResolver<PersistentPreferredActivity, PersistentPreferredActivity>
+ extends WatchedIntentResolver<PersistentPreferredActivity, PersistentPreferredActivity>
implements Snappable {
@Override
protected PersistentPreferredActivity[] newArray(int size) {
diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
index 0e3b85c..10a6b3f 100644
--- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
@@ -19,14 +19,14 @@
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.WatchableIntentResolver;
+import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
import java.io.PrintWriter;
import java.util.ArrayList;
public class PreferredIntentResolver
- extends WatchableIntentResolver<PreferredActivity, PreferredActivity>
+ extends WatchedIntentResolver<PreferredActivity, PreferredActivity>
implements Snappable {
@Override
protected PreferredActivity[] newArray(int size) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 8283ac6..fe19956 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2861,6 +2861,100 @@
}
}
+ @GuardedBy("mUsersLock")
+ @VisibleForTesting
+ void upgradeUserTypesLU(@NonNull List<UserTypeFactory.UserTypeUpgrade> upgradeOps,
+ @NonNull ArrayMap<String, UserTypeDetails> userTypes,
+ final int formerUserTypeVersion,
+ @NonNull Set<Integer> userIdsToWrite) {
+ for (UserTypeFactory.UserTypeUpgrade userTypeUpgrade : upgradeOps) {
+ if (DBG) {
+ Slog.i(LOG_TAG, "Upgrade: " + userTypeUpgrade.getFromType() + " to: "
+ + userTypeUpgrade.getToType() + " maxVersion: "
+ + userTypeUpgrade.getUpToVersion());
+ }
+
+ // upgrade user type if version up to getUpToVersion()
+ if (formerUserTypeVersion <= userTypeUpgrade.getUpToVersion()) {
+ for (int i = 0; i < mUsers.size(); i++) {
+ UserData userData = mUsers.valueAt(i);
+ if (userTypeUpgrade.getFromType().equals(userData.info.userType)) {
+ final UserTypeDetails newUserType = userTypes.get(
+ userTypeUpgrade.getToType());
+
+ if (newUserType == null) {
+ throw new IllegalStateException(
+ "Upgrade destination user type not defined: "
+ + userTypeUpgrade.getToType());
+ }
+
+ upgradeProfileToTypeLU(userData.info, newUserType);
+ userIdsToWrite.add(userData.info.id);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Changes the user type of a profile to a new user type.
+ * @param userInfo The user to be updated.
+ * @param newUserType The new user type.
+ */
+ @GuardedBy("mUsersLock")
+ @VisibleForTesting
+ void upgradeProfileToTypeLU(@NonNull UserInfo userInfo, @NonNull UserTypeDetails newUserType) {
+ Slog.i(LOG_TAG, "Upgrading user " + userInfo.id
+ + " from " + userInfo.userType
+ + " to " + newUserType.getName());
+
+ if (!userInfo.isProfile()) {
+ throw new IllegalStateException(
+ "Can only upgrade profile types. " + userInfo.userType
+ + " is not a profile type.");
+ }
+
+ // Exceeded maximum profiles for parent user: log error, but allow upgrade
+ if (!canAddMoreProfilesToUser(newUserType.getName(), userInfo.profileGroupId, false)) {
+ Slog.w(LOG_TAG,
+ "Exceeded maximum profiles of type " + newUserType.getName() + " for user "
+ + userInfo.id + ". Maximum allowed= "
+ + newUserType.getMaxAllowedPerParent());
+ }
+
+ final UserTypeDetails oldUserType = mUserTypes.get(userInfo.userType);
+ final int oldFlags;
+ if (oldUserType != null) {
+ oldFlags = oldUserType.getDefaultUserInfoFlags();
+ } else {
+ // if oldUserType is missing from config_user_types.xml -> can only assume FLAG_PROFILE
+ oldFlags = UserInfo.FLAG_PROFILE;
+ }
+
+ //convert userData to newUserType
+ userInfo.userType = newUserType.getName();
+ // remove old default flags and add newUserType's default flags
+ userInfo.flags = newUserType.getDefaultUserInfoFlags() | (userInfo.flags ^ oldFlags);
+
+ // merge existing base restrictions with the new type's default restrictions
+ synchronized (mRestrictionsLock) {
+ if (!BundleUtils.isEmpty(newUserType.getDefaultRestrictions())) {
+ final Bundle newRestrictions = BundleUtils.clone(
+ mBaseUserRestrictions.getRestrictions(userInfo.id));
+ UserRestrictionsUtils.merge(newRestrictions,
+ newUserType.getDefaultRestrictions());
+ updateUserRestrictionsInternalLR(newRestrictions, userInfo.id);
+ if (DBG) {
+ Slog.i(LOG_TAG, "Updated user " + userInfo.id
+ + " restrictions to " + newRestrictions);
+ }
+ }
+ }
+
+ // re-compute badge index
+ userInfo.profileBadge = getFreeProfileBadgeLU(userInfo.profileGroupId, userInfo.userType);
+ }
+
@GuardedBy({"mPackagesLock", "mRestrictionsLock"})
private void fallbackToSingleUserLP() {
int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
@@ -5759,98 +5853,4 @@
}
return mDevicePolicyManagerInternal;
}
-
- @GuardedBy("mUsersLock")
- @VisibleForTesting
- void upgradeUserTypesLU(@NonNull List<UserTypeFactory.UserTypeUpgrade> upgradeOps,
- @NonNull ArrayMap<String, UserTypeDetails> userTypes,
- final int formerUserTypeVersion,
- @NonNull Set<Integer> userIdsToWrite) {
- for (UserTypeFactory.UserTypeUpgrade userTypeUpgrade : upgradeOps) {
- if (DBG) {
- Slog.i(LOG_TAG, "Upgrade: " + userTypeUpgrade.getFromType() + " to: "
- + userTypeUpgrade.getToType() + " maxVersion: "
- + userTypeUpgrade.getUpToVersion());
- }
-
- // upgrade user type if version up to getUpToVersion()
- if (formerUserTypeVersion <= userTypeUpgrade.getUpToVersion()) {
- for (int i = 0; i < mUsers.size(); i++) {
- UserData userData = mUsers.valueAt(i);
- if (userTypeUpgrade.getFromType().equals(userData.info.userType)) {
- final UserTypeDetails newUserType = userTypes.get(
- userTypeUpgrade.getToType());
-
- if (newUserType == null) {
- throw new IllegalStateException(
- "Upgrade destination user type not defined: "
- + userTypeUpgrade.getToType());
- }
-
- upgradeProfileToTypeLU(userData.info, newUserType);
- userIdsToWrite.add(userData.info.id);
- }
- }
- }
- }
- }
-
- /**
- * Changes the user type of a profile to a new user type.
- * @param userInfo The user to be updated.
- * @param newUserType The new user type.
- */
- @GuardedBy("mUsersLock")
- @VisibleForTesting
- void upgradeProfileToTypeLU(@NonNull UserInfo userInfo, @NonNull UserTypeDetails newUserType) {
- Slog.i(LOG_TAG, "Upgrading user " + userInfo.id
- + " from " + userInfo.userType
- + " to " + newUserType.getName());
-
- if (!userInfo.isProfile()) {
- throw new IllegalStateException(
- "Can only upgrade profile types. " + userInfo.userType
- + " is not a profile type.");
- }
-
- // Exceeded maximum profiles for parent user: log error, but allow upgrade
- if (!canAddMoreProfilesToUser(newUserType.getName(), userInfo.profileGroupId, false)) {
- Slog.w(LOG_TAG,
- "Exceeded maximum profiles of type " + newUserType.getName() + " for user "
- + userInfo.id + ". Maximum allowed= "
- + newUserType.getMaxAllowedPerParent());
- }
-
- final UserTypeDetails oldUserType = mUserTypes.get(userInfo.userType);
- final int oldFlags;
- if (oldUserType != null) {
- oldFlags = oldUserType.getDefaultUserInfoFlags();
- } else {
- // if oldUserType is missing from config_user_types.xml -> can only assume FLAG_PROFILE
- oldFlags = UserInfo.FLAG_PROFILE;
- }
-
- //convert userData to newUserType
- userInfo.userType = newUserType.getName();
- // remove old default flags and add newUserType's default flags
- userInfo.flags = newUserType.getDefaultUserInfoFlags() | (userInfo.flags ^ oldFlags);
-
- // merge existing base restrictions with the new type's default restrictions
- synchronized (mRestrictionsLock) {
- if (!BundleUtils.isEmpty(newUserType.getDefaultRestrictions())) {
- final Bundle newRestrictions = BundleUtils.clone(
- mBaseUserRestrictions.getRestrictions(userInfo.id));
- UserRestrictionsUtils.merge(newRestrictions,
- newUserType.getDefaultRestrictions());
- updateUserRestrictionsInternalLR(newRestrictions, userInfo.id);
- if (DBG) {
- Slog.i(LOG_TAG, "Updated user " + userInfo.id
- + " restrictions to " + newRestrictions);
- }
- }
- }
-
- // re-compute badge index
- userInfo.profileBadge = getFreeProfileBadgeLU(userInfo.profileGroupId, userInfo.userType);
- }
}
diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
index 0c8e36b..c8dc1b1 100644
--- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
+++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
@@ -146,47 +146,11 @@
uid,
compilationReason,
compilerFilter,
- ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_DEX_CODE_BYTES,
- getDexBytes(path),
- dexMetadataType);
- logger.write(
- sessionId,
- uid,
- compilationReason,
- compilerFilter,
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME,
compileTime,
dexMetadataType);
}
- private static long getDexBytes(String apkPath) {
- StrictJarFile jarFile = null;
- long dexBytes = 0;
- try {
- jarFile = new StrictJarFile(apkPath,
- /*verify=*/ false,
- /*signatureSchemeRollbackProtectionsEnforced=*/ false);
- Iterator<ZipEntry> it = jarFile.iterator();
- while (it.hasNext()) {
- ZipEntry entry = it.next();
- if (entry.getName().matches("classes(\\d)*[.]dex")) {
- dexBytes += entry.getSize();
- }
- }
- return dexBytes;
- } catch (IOException ignore) {
- Slog.e(TAG, "Error when parsing APK " + apkPath);
- return -1L;
- } finally {
- try {
- if (jarFile != null) {
- jarFile.close();
- }
- } catch (IOException ignore) {
- }
- }
- }
-
private static int getDexMetadataType(String dexMetadataPath) {
if (dexMetadataPath == null) {
return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE;
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index fd2d8e1..beebb31 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -16,6 +16,8 @@
package com.android.server.recoverysystem;
+import static android.os.UserHandle.USER_SYSTEM;
+
import android.annotation.IntDef;
import android.content.Context;
import android.content.IntentSender;
@@ -33,12 +35,14 @@
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.SystemProperties;
+import android.provider.DeviceConfig;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.LockSettingsInternal;
import com.android.internal.widget.RebootEscrowListener;
import com.android.server.LocalServices;
@@ -52,6 +56,8 @@
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
/**
* The recovery system service is responsible for coordinating recovery related
@@ -127,10 +133,28 @@
/**
* The action to perform upon resume on reboot clear request for a given client.
*/
- @IntDef({ROR_NOT_REQUESTED,
+ @IntDef({ ROR_NOT_REQUESTED,
ROR_REQUESTED_NEED_CLEAR,
ROR_REQUESTED_SKIP_CLEAR})
- private @interface ResumeOnRebootActionsOnClear{}
+ private @interface ResumeOnRebootActionsOnClear {}
+
+ /**
+ * The error code for reboots initiated by resume on reboot clients.
+ */
+ private static final int REBOOT_ERROR_NONE = 0;
+ private static final int REBOOT_ERROR_UNKNOWN = 1;
+ private static final int REBOOT_ERROR_INVALID_PACKAGE_NAME = 2;
+ private static final int REBOOT_ERROR_LSKF_NOT_CAPTURED = 3;
+ private static final int REBOOT_ERROR_SLOT_MISMATCH = 4;
+ private static final int REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE = 5;
+
+ @IntDef({ REBOOT_ERROR_NONE,
+ REBOOT_ERROR_UNKNOWN,
+ REBOOT_ERROR_INVALID_PACKAGE_NAME,
+ REBOOT_ERROR_LSKF_NOT_CAPTURED,
+ REBOOT_ERROR_SLOT_MISMATCH,
+ REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE})
+ private @interface ResumeOnRebootRebootErrorCode {}
static class Injector {
protected final Context mContext;
@@ -202,6 +226,35 @@
public void threadSleep(long millis) throws InterruptedException {
Thread.sleep(millis);
}
+
+ public int getUidFromPackageName(String packageName) {
+ try {
+ return mContext.getPackageManager().getPackageUidAsUser(packageName, USER_SYSTEM);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.w(TAG, "Failed to find uid for " + packageName);
+ }
+ return -1;
+ }
+
+ public void reportRebootEscrowPreparationMetrics(int uid,
+ @ResumeOnRebootActionsOnRequest int requestResult, int requestedClientCount) {
+ FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_PREPARATION_REPORTED, uid,
+ requestResult, requestedClientCount);
+ }
+
+ public void reportRebootEscrowLskfCapturedMetrics(int uid, int requestedClientCount,
+ int requestedToLskfCapturedDurationInSeconds) {
+ FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_LSKF_CAPTURE_REPORTED, uid,
+ requestedClientCount, requestedToLskfCapturedDurationInSeconds);
+ }
+
+ public void reportRebootEscrowRebootMetrics(int errorCode, int uid,
+ int preparedClientCount, int requestCount, boolean slotSwitch, boolean serverBased,
+ int lskfCapturedToRebootDurationInSeconds, int lskfCapturedCounts) {
+ FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_REBOOT_REPORTED, errorCode,
+ uid, preparedClientCount, requestCount, slotSwitch, serverBased,
+ lskfCapturedToRebootDurationInSeconds, lskfCapturedCounts);
+ }
}
/**
@@ -367,6 +420,16 @@
}
}
+ private void reportMetricsOnRequestLskf(String packageName, int requestResult) {
+ int uid = mInjector.getUidFromPackageName(packageName);
+ int pendingRequestCount;
+ synchronized (this) {
+ pendingRequestCount = mCallerPendingRequest.size();
+ }
+
+ mInjector.reportRebootEscrowPreparationMetrics(uid, requestResult, pendingRequestCount);
+ }
+
@Override // Binder call
public boolean requestLskf(String packageName, IntentSender intentSender) {
enforcePermissionForResumeOnReboot();
@@ -378,6 +441,8 @@
@ResumeOnRebootActionsOnRequest int action = updateRoRPreparationStateOnNewRequest(
packageName, intentSender);
+ reportMetricsOnRequestLskf(packageName, action);
+
switch (action) {
case ROR_SKIP_PREPARATION_AND_NOTIFY:
// We consider the preparation done if someone else has prepared.
@@ -420,12 +485,26 @@
return needPreparation ? ROR_NEED_PREPARATION : ROR_SKIP_PREPARATION_NOT_NOTIFY;
}
+ private void reportMetricsOnPreparedForReboot() {
+ List<String> preparedClients;
+ synchronized (this) {
+ preparedClients = new ArrayList<>(mCallerPreparedForReboot);
+ }
+
+ for (String packageName : preparedClients) {
+ int uid = mInjector.getUidFromPackageName(packageName);
+ mInjector.reportRebootEscrowLskfCapturedMetrics(uid, preparedClients.size(),
+ -1 /* duration */);
+ }
+ }
+
@Override
public void onPreparedForReboot(boolean ready) {
if (!ready) {
return;
}
updateRoRPreparationStateOnPreparedForReboot();
+ reportMetricsOnPreparedForReboot();
}
private synchronized void updateRoRPreparationStateOnPreparedForReboot() {
@@ -548,22 +627,49 @@
return true;
}
- private boolean rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) {
+ private @ResumeOnRebootRebootErrorCode int armRebootEscrow(String packageName,
+ boolean slotSwitch) {
if (packageName == null) {
Slog.w(TAG, "Missing packageName when rebooting with lskf.");
- return false;
+ return REBOOT_ERROR_INVALID_PACKAGE_NAME;
}
if (!isLskfCaptured(packageName)) {
- return false;
+ return REBOOT_ERROR_LSKF_NOT_CAPTURED;
}
if (!verifySlotForNextBoot(slotSwitch)) {
- return false;
+ return REBOOT_ERROR_SLOT_MISMATCH;
}
- // TODO(xunchang) write the vbmeta digest along with the escrowKey before reboot.
if (!mInjector.getLockSettingsService().armRebootEscrow()) {
Slog.w(TAG, "Failure to escrow key for reboot");
+ return REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE;
+ }
+
+ return REBOOT_ERROR_NONE;
+ }
+
+ private void reportMetricsOnRebootWithLskf(String packageName, boolean slotSwitch,
+ @ResumeOnRebootRebootErrorCode int errorCode) {
+ int uid = mInjector.getUidFromPackageName(packageName);
+ boolean serverBased = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA,
+ "server_based_ror_enabled", false);
+ int preparedClientCount;
+ synchronized (this) {
+ preparedClientCount = mCallerPreparedForReboot.size();
+ }
+
+ // TODO(b/179105110) report the true value of duration and counts
+ mInjector.reportRebootEscrowRebootMetrics(errorCode, uid, preparedClientCount,
+ 1 /* request count */, slotSwitch, serverBased,
+ -1 /* duration */, 1 /* lskf capture count */);
+ }
+
+ private boolean rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) {
+ @ResumeOnRebootRebootErrorCode int errorCode = armRebootEscrow(packageName, slotSwitch);
+ reportMetricsOnRebootWithLskf(packageName, slotSwitch, errorCode);
+
+ if (errorCode != REBOOT_ERROR_NONE) {
return false;
}
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
index 8dcc547..6ff8d6f 100644
--- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
+++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
@@ -290,25 +290,6 @@
maybeNotifyCallback();
}
- private void handleNetworkSuspended(@NonNull Network network, boolean isSuspended) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to isSuspended");
- return;
- }
-
- final NetworkCapabilities newCaps =
- new NetworkCapabilities(mRecordInProgress.getNetworkCapabilities());
- if (isSuspended) {
- newCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
- } else {
- newCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
- }
-
- handleCapabilitiesChanged(network, newCaps);
- }
-
private void handlePropertiesChanged(
@NonNull Network network, @NonNull LinkProperties linkProperties) {
mVcnContext.ensureRunningOnLooperThread();
@@ -366,20 +347,11 @@
@Override
public void onCapabilitiesChanged(
@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
+ if (networkCapabilities.equals(mRecordInProgress.getNetworkCapabilities())) return;
handleCapabilitiesChanged(network, networkCapabilities);
}
@Override
- public void onNetworkSuspended(@NonNull Network network) {
- handleNetworkSuspended(network, true /* isSuspended */);
- }
-
- @Override
- public void onNetworkResumed(@NonNull Network network) {
- handleNetworkSuspended(network, false /* isSuspended */);
- }
-
- @Override
public void onLinkPropertiesChanged(
@NonNull Network network, @NonNull LinkProperties linkProperties) {
handlePropertiesChanged(network, linkProperties);
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 69a153f..9589505 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -42,7 +42,6 @@
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkAgent;
-import android.net.NetworkAgent.ValidationStatus;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.RouteInfo;
@@ -1442,17 +1441,16 @@
caps,
lp,
Vcn.getNetworkScore(),
- new NetworkAgentConfig(),
+ new NetworkAgentConfig.Builder().build(),
mVcnContext.getVcnNetworkProvider()) {
@Override
- public void unwanted() {
+ public void onNetworkUnwanted() {
Slog.d(TAG, "NetworkAgent was unwanted");
teardownAsynchronously();
}
@Override
- public void onValidationStatus(
- @ValidationStatus int status, @Nullable Uri redirectUri) {
+ public void onValidationStatus(int status, @Nullable Uri redirectUri) {
if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
clearFailedAttemptCounterAndSafeModeAlarm();
}
@@ -1798,8 +1796,10 @@
lp.addDnsServer(addr);
}
- lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
- lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
+ lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null /*gateway*/,
+ null /*iface*/, RouteInfo.RTN_UNICAST));
+ lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null /*gateway*/,
+ null /*iface*/, RouteInfo.RTN_UNICAST));
lp.setMtu(gatewayConnectionConfig.getMaxMtu());
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5884102..4517ef5 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -438,10 +438,6 @@
final String packageName;
// the intent component, or target of an alias.
final ComponentName mActivityComponent;
- // Has a wallpaper window as a background.
- // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
- // mOccludesParent field.
- final boolean hasWallpaper;
// Input application handle used by the input dispatcher.
private InputApplicationHandle mInputApplicationHandle;
@@ -1104,19 +1100,25 @@
return;
}
- boolean isLetterboxed = isLetterboxed(mainWin);
- pw.println(prefix + "isLetterboxed=" + isLetterboxed);
- if (!isLetterboxed) {
+ boolean areBoundsLetterboxed = mainWin.isLetterboxedAppWindow();
+ pw.println(prefix + "areBoundsLetterboxed=" + areBoundsLetterboxed);
+ if (!areBoundsLetterboxed) {
return;
}
pw.println(prefix + " letterboxReason=" + getLetterboxReasonString(mainWin));
+ pw.println(prefix + " letterboxAspectRatio=" + computeAspectRatio(getBounds()));
+
+ boolean isLetterboxUiShown = isLetterboxed(mainWin);
+ pw.println(prefix + "isLetterboxUiShown=" + isLetterboxUiShown);
+
+ if (!isLetterboxUiShown) {
+ return;
+ }
pw.println(prefix + " letterboxBackgroundColor=" + Integer.toHexString(
getLetterboxBackgroundColor().toArgb()));
pw.println(prefix + " letterboxBackgroundType="
+ letterboxBackgroundTypeToString(mWmService.getLetterboxBackgroundType()));
- pw.println(prefix + " letterboxAspectRatio="
- + computeAspectRatio(getBounds()));
}
/**
@@ -1463,9 +1465,17 @@
"Unexpected letterbox background type: " + letterboxBackgroundType);
}
- /** @return {@code true} when main window is letterboxed and activity isn't transparent. */
- private boolean isLetterboxed(WindowState mainWindow) {
- return mainWindow.isLetterboxedAppWindow() && fillsParent();
+ /**
+ * @return {@code true} when the main window is letterboxed, this activity isn't transparent
+ * and doesn't show a wallpaper.
+ */
+ @VisibleForTesting
+ boolean isLetterboxed(WindowState mainWindow) {
+ return mainWindow.isLetterboxedAppWindow() && fillsParent()
+ // Check for FLAG_SHOW_WALLPAPER explicitly instead of using
+ // WindowContainer#showWallpaper because the later will return true when this
+ // activity is using blurred wallpaper for letterbox backgroud.
+ && (mainWindow.mAttrs.flags & FLAG_SHOW_WALLPAPER) == 0;
}
private void updateRoundedCorners(WindowState mainWindow) {
@@ -1655,11 +1665,12 @@
realTheme, com.android.internal.R.styleable.Window, mUserId);
if (ent != null) {
- mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
- hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
+ mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array)
+ // This style is propagated to the main window attributes with
+ // FLAG_SHOW_WALLPAPER from PhoneWindow#generateLayout.
+ || ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
} else {
- hasWallpaper = false;
noDisplay = false;
}
@@ -2468,7 +2479,7 @@
if (!includingFinishing && finishing) {
return false;
}
- return mOccludesParent;
+ return mOccludesParent || showWallpaper();
}
boolean setOccludesParent(boolean occludesParent) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index e858fe1..060323c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -32,6 +32,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.service.voice.IVoiceInteractionSession;
+import android.util.Pair;
import android.util.proto.ProtoOutputStream;
import android.window.TaskSnapshot;
@@ -162,10 +163,10 @@
IVoiceInteractor mInteractor);
/**
- * Returns the top activity from each of the currently visible root tasks. The first entry
- * will be the focused activity.
+ * Returns the top activity from each of the currently visible root tasks, and the related task
+ * id. The first entry will be the focused activity.
*/
- public abstract List<IBinder> getTopVisibleActivities();
+ public abstract List<Pair<IBinder, Integer>> getTopVisibleActivities();
/**
* Returns whether {@code uid} has any resumed activity.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 52d110c..09f5c93 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -215,6 +215,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -5074,7 +5075,7 @@
}
@Override
- public List<IBinder> getTopVisibleActivities() {
+ public List<Pair<IBinder, Integer>> getTopVisibleActivities() {
synchronized (mGlobalLock) {
return mRootWindowContainer.getTopVisibleActivities();
}
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 1120a07..d12d07a 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -283,11 +283,7 @@
return;
}
- if (keepHandling) {
- mDragState.notifyMoveLocked(newX, newY);
- } else {
- mDragState.notifyDropLocked(newX, newY);
- }
+ mDragState.updateDragSurfaceLocked(keepHandling, newX, newY);
}
}
@@ -330,6 +326,12 @@
mDragState = null;
}
+ void reportDropWindow(IBinder token, float x, float y) {
+ synchronized (mService.mGlobalLock) {
+ mDragState.reportDropWindowLock(token, x, y);
+ }
+ }
+
private class DragHandler extends Handler {
/**
* Lock for window manager.
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 08d5e80..fd4bbd7 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -109,7 +109,6 @@
float mCurrentX, mCurrentY;
float mThumbOffsetX, mThumbOffsetY;
InputInterceptor mInputInterceptor;
- WindowState mTargetWindow;
ArrayList<WindowState> mNotifiedWindows;
boolean mDragInProgress;
/**
@@ -217,18 +216,18 @@
x = mCurrentX;
y = mCurrentY;
}
- DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
+ DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
x, y, mThumbOffsetX, mThumbOffsetY, null, null, null, null, null,
mDragResult);
try {
- ws.mClient.dispatchDragEvent(evt);
+ ws.mClient.dispatchDragEvent(event);
} catch (RemoteException e) {
Slog.w(TAG_WM, "Unable to drag-end window " + ws);
}
// if the current window is in the same process,
// the dispatch has already recycled the event
if (myPid != ws.mSession.mPid) {
- evt.recycle();
+ event.recycle();
}
}
mNotifiedWindows.clear();
@@ -270,6 +269,68 @@
mDragDropController.onDragStateClosedLocked(this);
}
+ /**
+ * Notify the drop target and tells it about the data. If the drop event is not sent to the
+ * target, invokes {@code endDragLocked} immediately.
+ */
+ void reportDropWindowLock(IBinder token, float x, float y) {
+ if (mAnimator != null) {
+ return;
+ }
+
+ final WindowState touchedWin = mService.mInputToWindowMap.get(token);
+ if (!isWindowNotified(touchedWin)) {
+ // "drop" outside a valid window -- no recipient to apply a
+ // timeout to, and we can send the drag-ended message immediately.
+ mDragResult = false;
+ endDragLocked();
+ if (DEBUG_DRAG) Slog.d(TAG_WM, "Drop outside a valid window " + touchedWin);
+ return;
+ }
+
+ if (DEBUG_DRAG) Slog.d(TAG_WM, "sending DROP to " + touchedWin);
+
+ final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
+
+ final DragAndDropPermissionsHandler dragAndDropPermissions;
+ if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0
+ && mData != null) {
+ dragAndDropPermissions = new DragAndDropPermissionsHandler(mService.mGlobalLock,
+ mData,
+ mUid,
+ touchedWin.getOwningPackage(),
+ mFlags & DRAG_FLAGS_URI_PERMISSIONS,
+ mSourceUserId,
+ targetUserId);
+ } else {
+ dragAndDropPermissions = null;
+ }
+ if (mSourceUserId != targetUserId) {
+ if (mData != null) {
+ mData.fixUris(mSourceUserId);
+ }
+ }
+ final int myPid = Process.myPid();
+ final IBinder clientToken = touchedWin.mClient.asBinder();
+ final DragEvent event = obtainDragEvent(DragEvent.ACTION_DROP, x, y,
+ true /* includeData */, targetInterceptsGlobalDrag(touchedWin),
+ dragAndDropPermissions);
+ try {
+ touchedWin.mClient.dispatchDragEvent(event);
+
+ // 5 second timeout for this window to respond to the drop
+ mDragDropController.sendTimeoutMessage(MSG_DRAG_END_TIMEOUT, clientToken);
+ } catch (RemoteException e) {
+ Slog.w(TAG_WM, "can't send drop notification to win " + touchedWin);
+ endDragLocked();
+ } finally {
+ if (myPid != touchedWin.mSession.mPid) {
+ event.recycle();
+ }
+ }
+ mToken = clientToken;
+ }
+
class InputInterceptor {
InputChannel mClientChannel;
DragInputEventReceiver mInputEventReceiver;
@@ -397,9 +458,9 @@
ClipDescription desc, ClipData data) {
final boolean interceptsGlobalDrag = targetInterceptsGlobalDrag(newWin);
if (mDragInProgress && isValidDropTarget(newWin, interceptsGlobalDrag)) {
- DragEvent event = obtainDragEvent(newWin, DragEvent.ACTION_DRAG_STARTED,
- touchX, touchY, mThumbOffsetX, mThumbOffsetY, null, desc,
- interceptsGlobalDrag ? data : null, null, null, false);
+ DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, touchX, touchY,
+ interceptsGlobalDrag, false /* includeDragSurface */,
+ null /* dragAndDropPermission */);
try {
newWin.mClient.dispatchDragEvent(event);
// track each window that we've notified that the drag is starting
@@ -501,13 +562,17 @@
mAnimator = createCancelAnimationLocked();
}
- void notifyMoveLocked(float x, float y) {
+ void updateDragSurfaceLocked(boolean keepHandling, float x, float y) {
if (mAnimator != null) {
return;
}
mCurrentX = x;
mCurrentY = y;
+ if (!keepHandling) {
+ return;
+ }
+
// Move the surface to the given touch
if (SHOW_LIGHT_TRANSACTIONS) {
Slog.i(TAG_WM, ">>> OPEN TRANSACTION notifyMoveLocked");
@@ -518,71 +583,6 @@
}
/**
- * Finds the drop target and tells it about the data. If the drop event is not sent to the
- * target, invokes {@code endDragLocked} immediately.
- */
- void notifyDropLocked(float x, float y) {
- if (mAnimator != null) {
- return;
- }
- mCurrentX = x;
- mCurrentY = y;
-
- final WindowState touchedWin = mDisplayContent.getTouchableWinAtPointLocked(x, y);
-
- if (!isWindowNotified(touchedWin)) {
- // "drop" outside a valid window -- no recipient to apply a
- // timeout to, and we can send the drag-ended message immediately.
- mDragResult = false;
- endDragLocked();
- return;
- }
-
- if (DEBUG_DRAG) Slog.d(TAG_WM, "sending DROP to " + touchedWin);
-
- final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
-
- final DragAndDropPermissionsHandler dragAndDropPermissions;
- if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0
- && mData != null) {
- dragAndDropPermissions = new DragAndDropPermissionsHandler(mService.mGlobalLock,
- mData,
- mUid,
- touchedWin.getOwningPackage(),
- mFlags & DRAG_FLAGS_URI_PERMISSIONS,
- mSourceUserId,
- targetUserId);
- } else {
- dragAndDropPermissions = null;
- }
- if (mSourceUserId != targetUserId){
- if (mData != null) {
- mData.fixUris(mSourceUserId);
- }
- }
- final int myPid = Process.myPid();
- final IBinder token = touchedWin.mClient.asBinder();
- final DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DROP, x, y,
- mThumbOffsetX, mThumbOffsetY, null, null, mData,
- targetInterceptsGlobalDrag(touchedWin) ? mSurfaceControl : null,
- dragAndDropPermissions, false);
- try {
- touchedWin.mClient.dispatchDragEvent(evt);
-
- // 5 second timeout for this window to respond to the drop
- mDragDropController.sendTimeoutMessage(MSG_DRAG_END_TIMEOUT, token);
- } catch (RemoteException e) {
- Slog.w(TAG_WM, "can't send drop notification to win " + touchedWin);
- endDragLocked();
- } finally {
- if (myPid != touchedWin.mSession.mPid) {
- evt.recycle();
- }
- }
- mToken = token;
- }
-
- /**
* Returns true if it has sent DRAG_STARTED broadcast out but has not been sent DRAG_END
* broadcast.
*/
@@ -590,14 +590,12 @@
return mDragInProgress;
}
- private static DragEvent obtainDragEvent(WindowState win, int action, float x, float y,
- float offsetX, float offsetY, Object localState, ClipDescription description,
- ClipData data, SurfaceControl dragSurface,
- IDragAndDropPermissions dragAndDropPermissions, boolean result) {
- final float winX = win.translateToWindowX(x);
- final float winY = win.translateToWindowY(y);
- return DragEvent.obtain(action, winX, winY, offsetX, offsetY, localState, description, data,
- dragSurface, dragAndDropPermissions, result);
+ private DragEvent obtainDragEvent(int action, float x, float y, boolean includeData,
+ boolean includeDragSurface, IDragAndDropPermissions dragAndDropPermissions) {
+ return DragEvent.obtain(action, x, y, mThumbOffsetX, mThumbOffsetY,
+ null /* localState */, mDataDescription,
+ includeData ? mData : null, includeDragSurface ? mSurfaceControl : null,
+ dragAndDropPermissions, false /* result */);
}
private ValueAnimator createReturnAnimationLocked() {
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 6e89581..84616c0 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -229,6 +229,12 @@
mService::reportFocusChanged, oldToken, newToken));
}
+ @Override
+ public void notifyDropWindow(IBinder token, float x, float y) {
+ mService.mH.sendMessage(PooledLambda.obtainMessage(
+ mService.mDragDropController::reportDropWindow, token, x, y));
+ }
+
/** Waits until the built-in input devices have been configured. */
public boolean waitForInputDevicesReady(long timeoutMillis) {
synchronized (mInputDevicesReadyMonitor) {
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
index f0629fa..520bd8b 100644
--- a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -126,7 +126,7 @@
/**
* @return {@code true} if we need to wake-up SurfaceFlinger earlier during this animation.
*
- * @see Transaction#setEarlyWakeup
+ * @see Transaction#setEarlyWakeupStart and Transaction#setEarlyWakeupEnd
*/
default boolean needsEarlyWakeup() { return false; }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 422d4e7..857217f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1814,11 +1814,11 @@
}
/**
- * @return a list of activities which are the top ones in each visible root task. The first
- * entry will be the focused activity.
+ * @return a list of pairs, containing activities and their task id which are the top ones in
+ * each visible root task. The first entry will be the focused activity.
*/
- List<IBinder> getTopVisibleActivities() {
- final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
+ List<Pair<IBinder, Integer>> getTopVisibleActivities() {
+ final ArrayList<Pair<IBinder, Integer>> topVisibleActivities = new ArrayList<>();
final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
// Traverse all displays.
forAllRootTasks(rootTask -> {
@@ -1826,15 +1826,17 @@
if (rootTask.shouldBeVisible(null /* starting */)) {
final ActivityRecord top = rootTask.getTopNonFinishingActivity();
if (top != null) {
+ Pair<IBinder, Integer> visibleActivity = new Pair<>(top.appToken,
+ top.getTask().mTaskId);
if (rootTask == topFocusedRootTask) {
- topActivityTokens.add(0, top.appToken);
+ topVisibleActivities.add(0, visibleActivity);
} else {
- topActivityTokens.add(top.appToken);
+ topVisibleActivities.add(visibleActivity);
}
}
}
});
- return topActivityTokens;
+ return topVisibleActivities;
}
@Nullable
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 09a8e4f..a4a0866 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3595,7 +3595,7 @@
return false;
}
- if (r.occludesParent() || r.hasWallpaper) {
+ if (r.occludesParent()) {
// Root task isn't translucent if it has at least one fullscreen activity
// that is visible.
return true;
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 375b3f4..565804f 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -153,7 +153,9 @@
// }
try {
mTaskOrganizer.removeStartingWindow(task.mTaskId, firstWindowLeash, mainFrame,
- prepareAnimation);
+ /* TODO(183004107) Revert this when jankiness is solved
+ prepareAnimation); */ false);
+
} catch (RemoteException e) {
Slog.e(TAG, "Exception sending onStartTaskFinished callback", e);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 74337c2..0840441 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -44,7 +44,7 @@
static final boolean DEBUG_STARTING_WINDOW_VERBOSE = false;
static final boolean DEBUG_WALLPAPER = false;
static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
- static final boolean DEBUG_DRAG = false;
+ static final boolean DEBUG_DRAG = true;
static final boolean DEBUG_SCREENSHOT = false;
static final boolean DEBUG_LAYOUT_REPEATS = false;
static final boolean DEBUG_WINDOW_TRACE = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index a46a8d5..64a26ec 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.os.Build.IS_USER;
+import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
@@ -135,6 +136,8 @@
return runGetLetterboxBackgroundColor(pw);
case "reset":
return runReset(pw);
+ case "disable-blur":
+ return runSetBlurDisabled(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -214,6 +217,33 @@
return 0;
}
+ private int runSetBlurDisabled(PrintWriter pw) throws RemoteException {
+ String arg = getNextArg();
+ if (arg == null) {
+ pw.println("Blur supported on device: " + CROSS_WINDOW_BLUR_SUPPORTED);
+ pw.println("Blur enabled: " + mInternal.mBlurController.mBlurEnabled);
+ return 0;
+ }
+
+ final boolean disableBlur;
+ switch (arg) {
+ case "true":
+ case "1":
+ disableBlur = true;
+ break;
+ case "false":
+ case "0":
+ disableBlur = false;
+ break;
+ default:
+ getErrPrintWriter().println("Error: expected true, 1, false, 0, but got " + arg);
+ return -1;
+ }
+
+ mInterface.setForceCrossWindowBlurDisabled(disableBlur);
+ return 0;
+ }
+
private void printInitialDisplayDensity(PrintWriter pw , int displayId) {
try {
final int initialDensity = mInterface.getInitialDisplayDensity(displayId);
@@ -725,6 +755,7 @@
pw.println(" Set display scaling mode.");
pw.println(" dismiss-keyguard");
pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
+ pw.println(" disable-blur [true|1|false|0]");
pw.println(" user-rotation [-d DISPLAY_ID] [free|lock] [rotation]");
pw.println(" Print or set user rotation mode and user rotation.");
pw.println(" dump-visible-window-views");
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index be06d03..3a674c4 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -131,6 +131,7 @@
jmethodID getDeviceAlias;
jmethodID getTouchCalibrationForInputDevice;
jmethodID getContextForDisplay;
+ jmethodID notifyDropWindow;
} gServiceClassInfo;
static struct {
@@ -335,6 +336,7 @@
bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid, int32_t injectorUid) override;
void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override;
void setPointerCapture(bool enabled) override;
+ void notifyDropWindow(const sp<IBinder>& token, float x, float y) override;
/* --- PointerControllerPolicyInterface implementation --- */
@@ -905,6 +907,20 @@
checkAndClearExceptionFromCallback(env, "notifyFocusChanged");
}
+void NativeInputManager::notifyDropWindow(const sp<IBinder>& token, float x, float y) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+ ALOGD("notifyDropWindow");
+#endif
+ ATRACE_CALL();
+
+ JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
+
+ jobject tokenObj = javaObjectForIBinder(env, token);
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyDropWindow, tokenObj, x, y);
+ checkAndClearExceptionFromCallback(env, "notifyDropWindow");
+}
+
void NativeInputManager::notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
const std::vector<float>& values) {
@@ -2350,6 +2366,8 @@
GET_METHOD_ID(gServiceClassInfo.notifyFocusChanged, clazz,
"notifyFocusChanged", "(Landroid/os/IBinder;Landroid/os/IBinder;)V");
+ GET_METHOD_ID(gServiceClassInfo.notifyDropWindow, clazz, "notifyDropWindow",
+ "(Landroid/os/IBinder;FF)V");
GET_METHOD_ID(gServiceClassInfo.notifySensorEvent, clazz, "notifySensorEvent", "(IIIJ[F)V");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a8131e4..283895b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,7 @@
import static android.app.admin.DevicePolicyManager.DELEGATION_NETWORK_LOGGING;
import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
+import static android.app.admin.DevicePolicyManager.DELEGATION_SECURITY_LOGGING;
import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
@@ -430,6 +431,7 @@
DELEGATION_INSTALL_EXISTING_PACKAGE,
DELEGATION_KEEP_UNINSTALLED_PACKAGES,
DELEGATION_NETWORK_LOGGING,
+ DELEGATION_SECURITY_LOGGING,
DELEGATION_CERT_SELECTION,
};
@@ -440,9 +442,18 @@
DELEGATION_NETWORK_LOGGING,
});
+ // Subset of delegations that can only be delegated by Device Owner or Profile Owner of an
+ // organization-owned and managed profile.
+ private static final List<String>
+ DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS =
+ Arrays.asList(new String[]{
+ DELEGATION_SECURITY_LOGGING,
+ });
+
// Subset of delegations that only one single package within a given user can hold
private static final List<String> EXCLUSIVE_DELEGATIONS = Arrays.asList(new String[] {
DELEGATION_NETWORK_LOGGING,
+ DELEGATION_SECURITY_LOGGING,
DELEGATION_CERT_SELECTION,
});
@@ -6024,6 +6035,10 @@
if (!Collections.disjoint(scopes, DEVICE_OWNER_OR_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| (isProfileOwner(caller) && isManagedProfile(caller.getUserId())));
+ } else if (!Collections.disjoint(
+ scopes, DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ || isProfileOwnerOfOrganizationOwnedDevice(caller));
} else {
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
}
@@ -7658,6 +7673,10 @@
receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action,
deviceOwnerUserId);
}
+ if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
+ receiverComponent = resolveDelegateReceiver(DELEGATION_SECURITY_LOGGING, action,
+ deviceOwnerUserId);
+ }
if (receiverComponent == null) {
synchronized (getLockObject()) {
receiverComponent = mOwners.getDeviceOwnerComponent();
@@ -7674,6 +7693,10 @@
if (action.equals(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)) {
receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action, userId);
}
+ if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
+ receiverComponent = resolveDelegateReceiver(
+ DELEGATION_SECURITY_LOGGING, action, userId);
+ }
if (receiverComponent == null) {
receiverComponent = getOwnerComponent(userId);
}
@@ -13920,16 +13943,24 @@
}
@Override
- public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) {
+ public void setSecurityLoggingEnabled(ComponentName admin, String packageName,
+ boolean enabled) {
if (!mHasFeature) {
return;
}
- Objects.requireNonNull(admin);
- final CallerIdentity caller = getCallerIdentity(admin);
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
synchronized (getLockObject()) {
- Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)
- || isDeviceOwner(caller));
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
+
if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) {
return;
}
@@ -13949,17 +13980,23 @@
}
@Override
- public boolean isSecurityLoggingEnabled(ComponentName admin) {
+ public boolean isSecurityLoggingEnabled(ComponentName admin, String packageName) {
if (!mHasFeature) {
return false;
}
synchronized (getLockObject()) {
if (!isCallerWithSystemUid()) {
- Objects.requireNonNull(admin);
- final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(
- isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller));
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
}
return mInjector.securityLogGetLoggingEnabledProperty();
}
@@ -13977,15 +14014,23 @@
}
@Override
- public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin,
+ String packageName) {
if (!mHasFeature) {
return null;
}
- Objects.requireNonNull(admin, "ComponentName is null");
- final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
+
Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
|| areAllUsersAffiliatedWithDeviceLocked());
@@ -14015,15 +14060,22 @@
}
@Override
- public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin,
+ String packageName) {
if (!mHasFeature) {
return null;
}
- Objects.requireNonNull(admin, "ComponentName is null");
- final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ final CallerIdentity caller = getCallerIdentity(admin, packageName);
+ if (admin != null) {
+ Preconditions.checkCallAuthorization(
+ isProfileOwnerOfOrganizationOwnedDevice(caller)
+ || isDeviceOwner(caller));
+ } else {
+ // A delegate app passes a null admin component, which is expected
+ Preconditions.checkCallAuthorization(
+ isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+ }
Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
|| areAllUsersAffiliatedWithDeviceLocked());
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index 9869b07..63488f9 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -118,9 +118,10 @@
binder::Status BinderIncrementalService::createStorage(
const ::std::string& path, const ::android::content::pm::DataLoaderParamsParcel& params,
int32_t createMode, int32_t* _aidl_return) {
- *_aidl_return = mImpl.createStorage(path, params,
- android::incremental::IncrementalService::CreateOptions(
- createMode));
+ *_aidl_return =
+ mImpl.createStorage(path, const_cast<content::pm::DataLoaderParamsParcel&&>(params),
+ android::incremental::IncrementalService::CreateOptions(
+ createMode));
return ok();
}
@@ -144,9 +145,8 @@
bool* _aidl_return) {
*_aidl_return =
mImpl.startLoading(storageId, const_cast<content::pm::DataLoaderParamsParcel&&>(params),
- statusListener,
- const_cast<StorageHealthCheckParams&&>(healthCheckParams),
- healthListener, perUidReadTimeouts);
+ statusListener, healthCheckParams, healthListener,
+ perUidReadTimeouts);
return ok();
}
@@ -266,8 +266,7 @@
binder::Status BinderIncrementalService::getLoadingProgress(int32_t storageId,
float* _aidl_return) {
- *_aidl_return =
- mImpl.getLoadingProgress(storageId, /*stopOnFirstIncomplete=*/false).getProgress();
+ *_aidl_return = mImpl.getLoadingProgress(storageId).getProgress();
return ok();
}
@@ -280,8 +279,8 @@
}
static FileId toFileId(const std::vector<uint8_t>& id) {
- FileId fid;
- memcpy(&fid, id.data(), id.size());
+ FileId fid = {};
+ memcpy(&fid, id.data(), std::min(sizeof(fid), id.size()));
return fid;
}
@@ -335,10 +334,8 @@
int32_t storageId,
const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
const ::android::sp<IStorageHealthListener>& healthListener, bool* _aidl_return) {
- *_aidl_return = mImpl.registerStorageHealthListener(storageId,
- const_cast<StorageHealthCheckParams&&>(
- healthCheckParams),
- healthListener);
+ *_aidl_return =
+ mImpl.registerStorageHealthListener(storageId, healthCheckParams, healthListener);
return ok();
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 34253f9..a88f2b4 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -247,14 +247,17 @@
}
template <class Func>
-static auto makeCleanup(Func&& f) {
+static auto makeCleanup(Func&& f) requires(!std::is_lvalue_reference_v<Func>) {
auto deleter = [f = std::move(f)](auto) { f(); };
// &f is a dangling pointer here, but we actually never use it as deleter moves it in.
return std::unique_ptr<Func, decltype(deleter)>(&f, std::move(deleter));
}
-static std::unique_ptr<DIR, decltype(&::closedir)> openDir(const char* dir) {
- return {::opendir(dir), ::closedir};
+static auto openDir(const char* dir) {
+ struct DirCloser {
+ void operator()(DIR* d) const noexcept { ::closedir(d); }
+ };
+ return std::unique_ptr<DIR, DirCloser>(::opendir(dir));
}
static auto openDir(std::string_view dir) {
@@ -390,9 +393,7 @@
dprintf(fd, " storages (%d): {\n", int(mnt.storages.size()));
for (auto&& [storageId, storage] : mnt.storages) {
dprintf(fd, " [%d] -> [%s] (%d %% loaded) \n", storageId, storage.name.c_str(),
- (int)(getLoadingProgressFromPath(mnt, storage.name.c_str(),
- /*stopOnFirstIncomplete=*/false)
- .getProgress() *
+ (int)(getLoadingProgressFromPath(mnt, storage.name.c_str()).getProgress() *
100));
}
dprintf(fd, " }\n");
@@ -425,21 +426,7 @@
return true;
}
- // Check all permanent binds.
- for (auto&& [_, bindPoint] : ifs.bindPoints) {
- if (bindPoint.kind != BindKind::Permanent) {
- continue;
- }
- const auto progress = getLoadingProgressFromPath(ifs, bindPoint.sourceDir,
- /*stopOnFirstIncomplete=*/true);
- if (!progress.isError() && !progress.fullyLoaded()) {
- LOG(INFO) << "Non system mount: [" << bindPoint.sourceDir
- << "], partial progress: " << progress.getProgress() * 100 << "%";
- return true;
- }
- }
-
- return false;
+ return mIncFs->isEverythingFullyLoaded(ifs.control) == incfs::LoadingState::MissingBlocks;
}
void IncrementalService::onSystemReady() {
@@ -487,9 +474,9 @@
}
}
-StorageId IncrementalService::createStorage(
- std::string_view mountPoint, const content::pm::DataLoaderParamsParcel& dataLoaderParams,
- CreateOptions options) {
+StorageId IncrementalService::createStorage(std::string_view mountPoint,
+ content::pm::DataLoaderParamsParcel dataLoaderParams,
+ CreateOptions options) {
LOG(INFO) << "createStorage: " << mountPoint << " | " << int(options);
if (!path::isAbsolute(mountPoint)) {
LOG(ERROR) << "path is not absolute: " << mountPoint;
@@ -576,7 +563,7 @@
std::make_shared<IncFsMount>(std::move(mountRoot), mountId, std::move(control), *this);
// Now it's the |ifs|'s responsibility to clean up after itself, and the only cleanup we need
// is the removal of the |ifs|.
- firstCleanupOnFailure.release();
+ (void)firstCleanupOnFailure.release();
auto secondCleanup = [this, &l](auto itPtr) {
if (!l.owns_lock()) {
@@ -597,9 +584,9 @@
metadata::Mount m;
m.mutable_storage()->set_id(ifs->mountId);
m.mutable_loader()->set_type((int)dataLoaderParams.type);
- m.mutable_loader()->set_package_name(dataLoaderParams.packageName);
- m.mutable_loader()->set_class_name(dataLoaderParams.className);
- m.mutable_loader()->set_arguments(dataLoaderParams.arguments);
+ m.mutable_loader()->set_package_name(std::move(dataLoaderParams.packageName));
+ m.mutable_loader()->set_class_name(std::move(dataLoaderParams.className));
+ m.mutable_loader()->set_arguments(std::move(dataLoaderParams.arguments));
const auto metadata = m.SerializeAsString();
if (auto err =
mIncFs->makeFile(ifs->control,
@@ -622,7 +609,7 @@
}
// Done here as well, all data structures are in good state.
- secondCleanupOnFailure.release();
+ (void)secondCleanupOnFailure.release();
mountIt->second = std::move(ifs);
l.unlock();
@@ -674,14 +661,14 @@
}
bool IncrementalService::startLoading(StorageId storageId,
- content::pm::DataLoaderParamsParcel&& dataLoaderParams,
- const DataLoaderStatusListener& statusListener,
- StorageHealthCheckParams&& healthCheckParams,
- const StorageHealthListener& healthListener,
- const std::vector<PerUidReadTimeouts>& perUidReadTimeouts) {
+ content::pm::DataLoaderParamsParcel dataLoaderParams,
+ DataLoaderStatusListener statusListener,
+ const StorageHealthCheckParams& healthCheckParams,
+ StorageHealthListener healthListener,
+ std::vector<PerUidReadTimeouts> perUidReadTimeouts) {
// Per Uid timeouts.
if (!perUidReadTimeouts.empty()) {
- setUidReadTimeouts(storageId, perUidReadTimeouts);
+ setUidReadTimeouts(storageId, std::move(perUidReadTimeouts));
}
// Re-initialize DataLoader.
@@ -697,8 +684,9 @@
l.unlock();
// DataLoader.
- auto dataLoaderStub = prepareDataLoader(*ifs, std::move(dataLoaderParams), &statusListener,
- std::move(healthCheckParams), &healthListener);
+ auto dataLoaderStub =
+ prepareDataLoader(*ifs, std::move(dataLoaderParams), std::move(statusListener),
+ healthCheckParams, std::move(healthListener));
CHECK(dataLoaderStub);
if (dataLoaderStub->isSystemDataLoader()) {
@@ -840,7 +828,7 @@
}
std::lock_guard l(mMountOperationLock);
- const auto status = mVold->setIncFsMountOptions(control, enableReadLogs);
+ auto status = mVold->setIncFsMountOptions(control, enableReadLogs);
if (status.isOk()) {
// Store enabled state.
ifs.setReadLogsEnabled(enableReadLogs);
@@ -1209,8 +1197,8 @@
return mIncFs->getMetadata(ifs->control, node);
}
-void IncrementalService::setUidReadTimeouts(
- StorageId storage, const std::vector<PerUidReadTimeouts>& perUidReadTimeouts) {
+void IncrementalService::setUidReadTimeouts(StorageId storage,
+ std::vector<PerUidReadTimeouts>&& perUidReadTimeouts) {
using microseconds = std::chrono::microseconds;
using milliseconds = std::chrono::milliseconds;
@@ -1257,13 +1245,13 @@
}
// Still loading?
- const auto progress = getLoadingProgress(storage, /*stopOnFirstIncomplete=*/true);
- if (progress.isError()) {
+ const auto state = isMountFullyLoaded(storage);
+ if (int(state) < 0) {
// Something is wrong, abort.
return clearUidReadTimeouts(storage);
}
- if (progress.started() && progress.fullyLoaded()) {
+ if (state == incfs::LoadingState::Full) {
// Fully loaded, check readLogs collection.
const auto ifs = getIfs(storage);
if (!ifs->readLogsEnabled()) {
@@ -1350,7 +1338,7 @@
auto ifs = std::make_shared<IncFsMount>(std::string(expectedRoot), mountId,
std::move(control), *this);
- cleanupFiles.release(); // ifs will take care of that now
+ (void)cleanupFiles.release(); // ifs will take care of that now
// Check if marker file present.
if (checkReadLogsDisabledMarker(root)) {
@@ -1455,7 +1443,7 @@
}
mVold->unmountIncFs(std::string(target));
}
- cleanupMounts.release(); // ifs now manages everything
+ (void)cleanupMounts.release(); // ifs now manages everything
if (ifs->bindPoints.empty()) {
LOG(WARNING) << "No valid bind points for mount " << expectedRoot;
@@ -1628,19 +1616,18 @@
}
IncrementalService::DataLoaderStubPtr IncrementalService::prepareDataLoader(
- IncFsMount& ifs, DataLoaderParamsParcel&& params,
- const DataLoaderStatusListener* statusListener,
- StorageHealthCheckParams&& healthCheckParams, const StorageHealthListener* healthListener) {
+ IncFsMount& ifs, DataLoaderParamsParcel&& params, DataLoaderStatusListener&& statusListener,
+ const StorageHealthCheckParams& healthCheckParams, StorageHealthListener&& healthListener) {
std::unique_lock l(ifs.lock);
- prepareDataLoaderLocked(ifs, std::move(params), statusListener, std::move(healthCheckParams),
- healthListener);
+ prepareDataLoaderLocked(ifs, std::move(params), std::move(statusListener), healthCheckParams,
+ std::move(healthListener));
return ifs.dataLoaderStub;
}
void IncrementalService::prepareDataLoaderLocked(IncFsMount& ifs, DataLoaderParamsParcel&& params,
- const DataLoaderStatusListener* statusListener,
- StorageHealthCheckParams&& healthCheckParams,
- const StorageHealthListener* healthListener) {
+ DataLoaderStatusListener&& statusListener,
+ const StorageHealthCheckParams& healthCheckParams,
+ StorageHealthListener&& healthListener) {
if (ifs.dataLoaderStub) {
LOG(INFO) << "Skipped data loader preparation because it already exists";
return;
@@ -1658,8 +1645,8 @@
ifs.dataLoaderStub =
new DataLoaderStub(*this, ifs.mountId, std::move(params), std::move(fsControlParcel),
- statusListener, std::move(healthCheckParams), healthListener,
- path::join(ifs.root, constants().mount));
+ std::move(statusListener), healthCheckParams,
+ std::move(healthListener), path::join(ifs.root, constants().mount));
}
template <class Duration>
@@ -2007,7 +1994,7 @@
}
IncrementalService::LoadingProgress IncrementalService::getLoadingProgress(
- StorageId storage, bool stopOnFirstIncomplete) const {
+ StorageId storage) const {
std::unique_lock l(mLock);
const auto ifs = getIfsLocked(storage);
if (!ifs) {
@@ -2020,12 +2007,11 @@
return {-EINVAL, -EINVAL};
}
l.unlock();
- return getLoadingProgressFromPath(*ifs, storageInfo->second.name, stopOnFirstIncomplete);
+ return getLoadingProgressFromPath(*ifs, storageInfo->second.name);
}
IncrementalService::LoadingProgress IncrementalService::getLoadingProgressFromPath(
- const IncFsMount& ifs, std::string_view storagePath,
- const bool stopOnFirstIncomplete) const {
+ const IncFsMount& ifs, std::string_view storagePath) const {
ssize_t totalBlocks = 0, filledBlocks = 0, error = 0;
mFs->listFilesRecursive(storagePath, [&, this](auto filePath) {
const auto [filledBlocksCount, totalBlocksCount] =
@@ -2038,24 +2024,21 @@
}
if (filledBlocksCount < 0) {
LOG(ERROR) << "getLoadingProgress failed to get filled blocks count for: " << filePath
- << " errno: " << filledBlocksCount;
+ << ", errno: " << filledBlocksCount;
error = filledBlocksCount;
return false;
}
totalBlocks += totalBlocksCount;
filledBlocks += filledBlocksCount;
- if (stopOnFirstIncomplete && filledBlocks < totalBlocks) {
- return false;
- }
return true;
});
return error ? LoadingProgress{error, error} : LoadingProgress{filledBlocks, totalBlocks};
}
-bool IncrementalService::updateLoadingProgress(
- StorageId storage, const StorageLoadingProgressListener& progressListener) {
- const auto progress = getLoadingProgress(storage, /*stopOnFirstIncomplete=*/false);
+bool IncrementalService::updateLoadingProgress(StorageId storage,
+ StorageLoadingProgressListener&& progressListener) {
+ const auto progress = getLoadingProgress(storage);
if (progress.isError()) {
// Failed to get progress from incfs, abort.
return false;
@@ -2067,15 +2050,15 @@
}
addTimedJob(*mProgressUpdateJobQueue, storage,
Constants::progressUpdateInterval /* repeat after 1s */,
- [storage, progressListener, this]() {
- updateLoadingProgress(storage, progressListener);
+ [storage, progressListener = std::move(progressListener), this]() mutable {
+ updateLoadingProgress(storage, std::move(progressListener));
});
return true;
}
bool IncrementalService::registerLoadingProgressListener(
- StorageId storage, const StorageLoadingProgressListener& progressListener) {
- return updateLoadingProgress(storage, progressListener);
+ StorageId storage, StorageLoadingProgressListener progressListener) {
+ return updateLoadingProgress(storage, std::move(progressListener));
}
bool IncrementalService::unregisterLoadingProgressListener(StorageId storage) {
@@ -2083,8 +2066,8 @@
}
bool IncrementalService::registerStorageHealthListener(
- StorageId storage, StorageHealthCheckParams&& healthCheckParams,
- const StorageHealthListener& healthListener) {
+ StorageId storage, const StorageHealthCheckParams& healthCheckParams,
+ StorageHealthListener healthListener) {
DataLoaderStubPtr dataLoaderStub;
{
std::unique_lock l(mLock);
@@ -2097,14 +2080,12 @@
return false;
}
}
- dataLoaderStub->setHealthListener(std::move(healthCheckParams), &healthListener);
+ dataLoaderStub->setHealthListener(healthCheckParams, std::move(healthListener));
return true;
}
void IncrementalService::unregisterStorageHealthListener(StorageId storage) {
- StorageHealthCheckParams invalidCheckParams;
- invalidCheckParams.blockedTimeoutMs = -1;
- registerStorageHealthListener(storage, std::move(invalidCheckParams), {});
+ registerStorageHealthListener(storage, {}, {});
}
bool IncrementalService::perfLoggingEnabled() {
@@ -2229,26 +2210,23 @@
return ifs->dataLoaderStub->elapsedMsSinceOldestPendingRead();
}
-IncrementalService::DataLoaderStub::DataLoaderStub(IncrementalService& service, MountId id,
- DataLoaderParamsParcel&& params,
- FileSystemControlParcel&& control,
- const DataLoaderStatusListener* statusListener,
- StorageHealthCheckParams&& healthCheckParams,
- const StorageHealthListener* healthListener,
- std::string&& healthPath)
+IncrementalService::DataLoaderStub::DataLoaderStub(
+ IncrementalService& service, MountId id, DataLoaderParamsParcel&& params,
+ FileSystemControlParcel&& control, DataLoaderStatusListener&& statusListener,
+ const StorageHealthCheckParams& healthCheckParams, StorageHealthListener&& healthListener,
+ std::string&& healthPath)
: mService(service),
mId(id),
mParams(std::move(params)),
mControl(std::move(control)),
- mStatusListener(statusListener ? *statusListener : DataLoaderStatusListener()),
- mHealthListener(healthListener ? *healthListener : StorageHealthListener()),
+ mStatusListener(std::move(statusListener)),
+ mHealthListener(std::move(healthListener)),
mHealthPath(std::move(healthPath)),
- mHealthCheckParams(std::move(healthCheckParams)) {
- if (mHealthListener) {
- if (!isHealthParamsValid()) {
- mHealthListener = {};
- }
- } else {
+ mHealthCheckParams(healthCheckParams) {
+ if (mHealthListener && !isHealthParamsValid()) {
+ mHealthListener = {};
+ }
+ if (!mHealthListener) {
// Disable advanced health check statuses.
mHealthCheckParams.blockedTimeoutMs = -1;
}
@@ -2592,7 +2570,7 @@
mHealthCheckParams.blockedTimeoutMs < mHealthCheckParams.unhealthyTimeoutMs;
}
-void IncrementalService::DataLoaderStub::onHealthStatus(StorageHealthListener healthListener,
+void IncrementalService::DataLoaderStub::onHealthStatus(const StorageHealthListener& healthListener,
int healthStatus) {
LOG(DEBUG) << id() << ": healthStatus: " << healthStatus;
if (healthListener) {
@@ -2817,14 +2795,12 @@
}
void IncrementalService::DataLoaderStub::setHealthListener(
- StorageHealthCheckParams&& healthCheckParams, const StorageHealthListener* healthListener) {
+ const StorageHealthCheckParams& healthCheckParams, StorageHealthListener&& healthListener) {
std::lock_guard lock(mMutex);
- mHealthCheckParams = std::move(healthCheckParams);
- if (healthListener == nullptr) {
- // reset listener and params
- mHealthListener = {};
- } else {
- mHealthListener = *healthListener;
+ mHealthCheckParams = healthCheckParams;
+ mHealthListener = std::move(healthListener);
+ if (!mHealthListener) {
+ mHealthCheckParams.blockedTimeoutMs = -1;
}
}
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index aa80bd4..4a5db06 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -136,17 +136,17 @@
void onSystemReady();
StorageId createStorage(std::string_view mountPoint,
- const content::pm::DataLoaderParamsParcel& dataLoaderParams,
+ content::pm::DataLoaderParamsParcel dataLoaderParams,
CreateOptions options);
StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
CreateOptions options = CreateOptions::Default);
StorageId openStorage(std::string_view path);
- bool startLoading(StorageId storage, content::pm::DataLoaderParamsParcel&& dataLoaderParams,
- const DataLoaderStatusListener& statusListener,
- StorageHealthCheckParams&& healthCheckParams,
- const StorageHealthListener& healthListener,
- const std::vector<PerUidReadTimeouts>& perUidReadTimeouts);
+ bool startLoading(StorageId storage, content::pm::DataLoaderParamsParcel dataLoaderParams,
+ DataLoaderStatusListener statusListener,
+ const StorageHealthCheckParams& healthCheckParams,
+ StorageHealthListener healthListener,
+ std::vector<PerUidReadTimeouts> perUidReadTimeouts);
int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
int unbind(StorageId storage, std::string_view target);
@@ -167,14 +167,14 @@
incfs::LoadingState isFileFullyLoaded(StorageId storage, std::string_view filePath) const;
incfs::LoadingState isMountFullyLoaded(StorageId storage) const;
- LoadingProgress getLoadingProgress(StorageId storage, bool stopOnFirstIncomplete) const;
+ LoadingProgress getLoadingProgress(StorageId storage) const;
bool registerLoadingProgressListener(StorageId storage,
- const StorageLoadingProgressListener& progressListener);
+ StorageLoadingProgressListener progressListener);
bool unregisterLoadingProgressListener(StorageId storage);
bool registerStorageHealthListener(StorageId storage,
- StorageHealthCheckParams&& healthCheckParams,
- const StorageHealthListener& healthListener);
+ const StorageHealthCheckParams& healthCheckParams,
+ StorageHealthListener healthListener);
void unregisterStorageHealthListener(StorageId storage);
RawMetadata getMetadata(StorageId storage, std::string_view path) const;
RawMetadata getMetadata(StorageId storage, FileId node) const;
@@ -216,9 +216,9 @@
DataLoaderStub(IncrementalService& service, MountId id,
content::pm::DataLoaderParamsParcel&& params,
content::pm::FileSystemControlParcel&& control,
- const DataLoaderStatusListener* statusListener,
- StorageHealthCheckParams&& healthCheckParams,
- const StorageHealthListener* healthListener, std::string&& healthPath);
+ DataLoaderStatusListener&& statusListener,
+ const StorageHealthCheckParams& healthCheckParams,
+ StorageHealthListener&& healthListener, std::string&& healthPath);
~DataLoaderStub();
// Cleans up the internal state and invalidates DataLoaderStub. Any subsequent calls will
// result in an error.
@@ -233,8 +233,8 @@
MountId id() const { return mId.load(std::memory_order_relaxed); }
const content::pm::DataLoaderParamsParcel& params() const { return mParams; }
bool isSystemDataLoader() const;
- void setHealthListener(StorageHealthCheckParams&& healthCheckParams,
- const StorageHealthListener* healthListener);
+ void setHealthListener(const StorageHealthCheckParams& healthCheckParams,
+ StorageHealthListener&& healthListener);
long elapsedMsSinceOldestPendingRead();
private:
@@ -255,7 +255,7 @@
bool fsmStep();
- void onHealthStatus(StorageHealthListener healthListener, int healthStatus);
+ void onHealthStatus(const StorageHealthListener& healthListener, int healthStatus);
void updateHealthStatus(bool baseline = false);
bool isValid() const { return id() != kInvalidStorageId; }
@@ -364,7 +364,7 @@
static bool perfLoggingEnabled();
void setUidReadTimeouts(StorageId storage,
- const std::vector<PerUidReadTimeouts>& perUidReadTimeouts);
+ std::vector<PerUidReadTimeouts>&& perUidReadTimeouts);
void clearUidReadTimeouts(StorageId storage);
void updateUidReadTimeouts(StorageId storage, Clock::time_point timeLimit);
@@ -389,13 +389,13 @@
DataLoaderStubPtr prepareDataLoader(IncFsMount& ifs,
content::pm::DataLoaderParamsParcel&& params,
- const DataLoaderStatusListener* statusListener = nullptr,
- StorageHealthCheckParams&& healthCheckParams = {},
- const StorageHealthListener* healthListener = nullptr);
+ DataLoaderStatusListener&& statusListener = {},
+ const StorageHealthCheckParams& healthCheckParams = {},
+ StorageHealthListener&& healthListener = {});
void prepareDataLoaderLocked(IncFsMount& ifs, content::pm::DataLoaderParamsParcel&& params,
- const DataLoaderStatusListener* statusListener = nullptr,
- StorageHealthCheckParams&& healthCheckParams = {},
- const StorageHealthListener* healthListener = nullptr);
+ DataLoaderStatusListener&& statusListener = {},
+ const StorageHealthCheckParams& healthCheckParams = {},
+ StorageHealthListener&& healthListener = {});
BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
StorageId findStorageId(std::string_view path) const;
@@ -413,8 +413,7 @@
int setStorageParams(IncFsMount& ifs, StorageId storageId, bool enableReadLogs);
binder::Status applyStorageParams(IncFsMount& ifs, bool enableReadLogs);
- LoadingProgress getLoadingProgressFromPath(const IncFsMount& ifs, std::string_view path,
- bool stopOnFirstIncomplete) const;
+ LoadingProgress getLoadingProgressFromPath(const IncFsMount& ifs, std::string_view path) const;
int setFileContent(const IfsMountPtr& ifs, const incfs::FileId& fileId,
std::string_view debugFilePath, std::span<const uint8_t> data) const;
@@ -433,7 +432,7 @@
bool addTimedJob(TimedQueueWrapper& timedQueue, MountId id, Milliseconds after, Job what);
bool removeTimedJobs(TimedQueueWrapper& timedQueue, MountId id);
bool updateLoadingProgress(int32_t storageId,
- const StorageLoadingProgressListener& progressListener);
+ StorageLoadingProgressListener&& progressListener);
long getMillsSinceOldestPendingRead(StorageId storage);
private:
@@ -455,7 +454,7 @@
BindPathMap mBindsByPath;
std::mutex mCallbacksLock;
- std::map<std::string, sp<AppOpsListener>> mCallbackRegistered;
+ std::unordered_map<std::string, sp<AppOpsListener>> mCallbackRegistered;
std::atomic_bool mSystemReady = false;
StorageId mNextId = 0;
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 7e85f9d..3465499 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -255,7 +255,7 @@
static JNIEnv* getOrAttachJniEnv(JavaVM* jvm);
-class RealTimedQueueWrapper : public TimedQueueWrapper {
+class RealTimedQueueWrapper final : public TimedQueueWrapper {
public:
RealTimedQueueWrapper(JavaVM* jvm) {
mThread = std::thread([this, jvm]() {
@@ -268,11 +268,11 @@
CHECK(!mThread.joinable()) << "call stop first";
}
- void addJob(MountId id, Milliseconds after, Job what) final {
+ void addJob(MountId id, Milliseconds timeout, Job what) final {
const auto now = Clock::now();
{
std::unique_lock lock(mMutex);
- mJobs.insert(TimedJob{id, now + after, std::move(what)});
+ mJobs.insert(TimedJob{id, now + timeout, std::move(what)});
}
mCondition.notify_all();
}
@@ -293,29 +293,28 @@
private:
void runTimers() {
static constexpr TimePoint kInfinityTs{Clock::duration::max()};
- TimePoint nextJobTs = kInfinityTs;
std::unique_lock lock(mMutex);
for (;;) {
- mCondition.wait_until(lock, nextJobTs, [this, nextJobTs]() {
+ const TimePoint nextJobTs = mJobs.empty() ? kInfinityTs : mJobs.begin()->when;
+ mCondition.wait_until(lock, nextJobTs, [this, oldNextJobTs = nextJobTs]() {
const auto now = Clock::now();
- const auto firstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
- return !mRunning || firstJobTs <= now || firstJobTs < nextJobTs;
+ const auto newFirstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
+ return newFirstJobTs <= now || newFirstJobTs < oldNextJobTs || !mRunning;
});
if (!mRunning) {
return;
}
const auto now = Clock::now();
- auto it = mJobs.begin();
- // Always acquire begin(). We can't use it after unlock as mTimedJobs can change.
- for (; it != mJobs.end() && it->when <= now; it = mJobs.begin()) {
+ // Always re-acquire begin(). We can't use it after unlock as mTimedJobs can change.
+ for (auto it = mJobs.begin(); it != mJobs.end() && it->when <= now;
+ it = mJobs.begin()) {
auto jobNode = mJobs.extract(it);
lock.unlock();
jobNode.value().what();
lock.lock();
}
- nextJobTs = it != mJobs.end() ? it->when : kInfinityTs;
}
}
@@ -328,7 +327,7 @@
}
};
bool mRunning = true;
- std::set<TimedJob> mJobs;
+ std::multiset<TimedJob> mJobs;
std::condition_variable mCondition;
std::mutex mMutex;
std::thread mThread;
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index fb3a8a0..54bc95d 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -1606,9 +1606,7 @@
int storageId =
mIncrementalService->createStorage(tempDir.path, mDataLoaderParcel,
IncrementalService::CreateOptions::CreateNew);
- ASSERT_EQ(1,
- mIncrementalService->getLoadingProgress(storageId, /*stopOnFirstIncomplete=*/false)
- .getProgress());
+ ASSERT_EQ(1, mIncrementalService->getLoadingProgress(storageId).getProgress());
}
TEST_F(IncrementalServiceTest, testGetLoadingProgressFailsWithFailedRanges) {
@@ -1620,9 +1618,7 @@
mIncrementalService->createStorage(tempDir.path, mDataLoaderParcel,
IncrementalService::CreateOptions::CreateNew);
EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(1);
- ASSERT_EQ(-1,
- mIncrementalService->getLoadingProgress(storageId, /*stopOnFirstIncomplete=*/false)
- .getProgress());
+ ASSERT_EQ(-1, mIncrementalService->getLoadingProgress(storageId).getProgress());
}
TEST_F(IncrementalServiceTest, testGetLoadingProgressSuccessWithEmptyRanges) {
@@ -1634,9 +1630,7 @@
mIncrementalService->createStorage(tempDir.path, mDataLoaderParcel,
IncrementalService::CreateOptions::CreateNew);
EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(3);
- ASSERT_EQ(1,
- mIncrementalService->getLoadingProgress(storageId, /*stopOnFirstIncomplete=*/false)
- .getProgress());
+ ASSERT_EQ(1, mIncrementalService->getLoadingProgress(storageId).getProgress());
}
TEST_F(IncrementalServiceTest, testGetLoadingProgressSuccess) {
@@ -1648,9 +1642,7 @@
mIncrementalService->createStorage(tempDir.path, mDataLoaderParcel,
IncrementalService::CreateOptions::CreateNew);
EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(3);
- ASSERT_EQ(0.5,
- mIncrementalService->getLoadingProgress(storageId, /*stopOnFirstIncomplete=*/false)
- .getProgress());
+ ASSERT_EQ(0.5, mIncrementalService->getLoadingProgress(storageId).getProgress());
}
TEST_F(IncrementalServiceTest, testRegisterLoadingProgressListenerSuccess) {
@@ -1833,8 +1825,12 @@
.WillOnce(Invoke(&checkPerUidTimeoutsEmpty));
EXPECT_CALL(*mTimedQueue, addJob(_, _, _)).Times(3);
- // Empty storage.
- mIncFs->countFilledBlocksEmpty();
+ // Loading storage.
+ EXPECT_CALL(*mIncFs, isEverythingFullyLoaded(_))
+ .WillOnce(Return(incfs::LoadingState::MissingBlocks))
+ .WillOnce(Return(incfs::LoadingState::MissingBlocks))
+ .WillOnce(Return(incfs::LoadingState::Full))
+ .WillOnce(Return(incfs::LoadingState::Full));
// Mark DataLoader as 'system' so that readlogs don't pollute the timed queue.
mDataLoaderParcel.packageName = "android";
@@ -1855,22 +1851,18 @@
const auto timedCallback = mTimedQueue->mWhat;
mTimedQueue->clearJob(storageId);
- // Still loading.
- mIncFs->countFilledBlocksSuccess();
-
// Call it again.
timedCallback();
}
{
- // Still present -> 0.5 progress.
+ // Still present -> some progress.
ASSERT_EQ(storageId, mTimedQueue->mId);
ASSERT_GE(mTimedQueue->mAfter, std::chrono::seconds(1));
const auto timedCallback = mTimedQueue->mWhat;
mTimedQueue->clearJob(storageId);
// Fully loaded but readlogs collection enabled.
- mIncFs->countFilledBlocksFullyLoaded();
ASSERT_GE(mDataLoader->setStorageParams(true), 0);
// Call it again.
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 281c1aa..f73af53 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -52,6 +52,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
@@ -66,7 +67,10 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ServiceInfo;
import android.os.BatteryManager;
@@ -142,6 +146,8 @@
@Mock
private JobSchedulerService mJobSchedulerService;
@Mock
+ private PackageManager mPackageManager;
+ @Mock
private PackageManagerInternal mPackageManagerInternal;
@Mock
private PowerAllowlistInternal mPowerAllowlistInternal;
@@ -201,6 +207,8 @@
-> mDeviceConfigPropertiesBuilder.build())
.when(() -> DeviceConfig.getProperties(
eq(DeviceConfig.NAMESPACE_JOB_SCHEDULER), ArgumentMatchers.<String>any()));
+ // Used in QuotaController.onSystemServicesReady
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
// Freeze the clocks at 24 hours after this moment in time. Several tests create sessions
// in the past, and QuotaController sometimes floors values at 0, so if the test time
@@ -2704,7 +2712,8 @@
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 1 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 30 * MINUTE_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, 27 * MINUTE_IN_MILLIS);
- setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, 10 * HOUR_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, 7 * HOUR_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, 10 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_WINDOW_SIZE_MS, 12 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 10 * MINUTE_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 87 * SECOND_IN_MILLIS);
@@ -2745,7 +2754,8 @@
assertEquals(HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
assertEquals(30 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
assertEquals(27 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
- assertEquals(10 * HOUR_IN_MILLIS, mQuotaController.getEjLimitSpecialAdditionMs());
+ assertEquals(7 * HOUR_IN_MILLIS, mQuotaController.getEjLimitAdditionInstallerMs());
+ assertEquals(10 * HOUR_IN_MILLIS, mQuotaController.getEjLimitAdditionSpecialMs());
assertEquals(12 * HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJTopAppTimeChunkSizeMs());
assertEquals(87 * SECOND_IN_MILLIS, mQuotaController.getEJRewardTopAppMs());
@@ -2786,7 +2796,8 @@
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, -1);
- setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, -1);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, -1);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_WINDOW_SIZE_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, -1);
setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, -1);
@@ -2823,7 +2834,8 @@
assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
assertEquals(10 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
- assertEquals(0, mQuotaController.getEjLimitSpecialAdditionMs());
+ assertEquals(0, mQuotaController.getEjLimitAdditionInstallerMs());
+ assertEquals(0, mQuotaController.getEjLimitAdditionSpecialMs());
assertEquals(HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
assertEquals(1, mQuotaController.getEJTopAppTimeChunkSizeMs());
assertEquals(10 * SECOND_IN_MILLIS, mQuotaController.getEJRewardTopAppMs());
@@ -2858,7 +2870,8 @@
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_FREQUENT_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RESTRICTED_MS, 25 * HOUR_IN_MILLIS);
- setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_SPECIAL_ADDITION_MS, 25 * HOUR_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_INSTALLER_MS, 25 * HOUR_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_ADDITION_SPECIAL_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_WINDOW_SIZE_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 25 * HOUR_IN_MILLIS);
@@ -2885,7 +2898,8 @@
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[FREQUENT_INDEX]);
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[RARE_INDEX]);
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitsMs()[RESTRICTED_INDEX]);
- assertEquals(0, mQuotaController.getEjLimitSpecialAdditionMs());
+ assertEquals(0, mQuotaController.getEjLimitAdditionInstallerMs());
+ assertEquals(0, mQuotaController.getEjLimitAdditionSpecialMs());
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getEJLimitWindowSizeMs());
assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJTopAppTimeChunkSizeMs());
assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getEJRewardTopAppMs());
@@ -3957,9 +3971,16 @@
}
@Test
- public void testGetRemainingEJExecutionTimeLocked_SpecialApp() {
- doReturn(new String[]{SOURCE_PACKAGE}).when(mPackageManagerInternal)
- .getKnownPackageNames(eq(PackageManagerInternal.PACKAGE_VERIFIER), anyInt());
+ public void testGetRemainingEJExecutionTimeLocked_Installer() {
+ PackageInfo pi = new PackageInfo();
+ pi.packageName = SOURCE_PACKAGE;
+ pi.requestedPermissions = new String[]{Manifest.permission.INSTALL_PACKAGES};
+ pi.requestedPermissionsFlags = new int[]{PackageInfo.REQUESTED_PERMISSION_GRANTED};
+ pi.applicationInfo = new ApplicationInfo();
+ pi.applicationInfo.uid = mSourceUid;
+ doReturn(List.of(pi)).when(mPackageManager).getInstalledPackagesAsUser(anyInt(), anyInt());
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mContext).checkPermission(
+ eq(Manifest.permission.INSTALL_PACKAGES), anyInt(), eq(mSourceUid));
mQuotaController.onSystemServicesReady();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -3980,7 +4001,7 @@
setStandbyBucket(i);
assertEquals("Got wrong remaining EJ execution time for bucket #" + i,
i == NEVER_INDEX ? 0
- : (limits[i] + mQuotaController.getEjLimitSpecialAdditionMs()
+ : (limits[i] + mQuotaController.getEjLimitAdditionInstallerMs()
- 5 * MINUTE_IN_MILLIS),
mQuotaController.getRemainingEJExecutionTimeLocked(
SOURCE_USER_ID, SOURCE_PACKAGE));
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS
index 5a4431e..5492dc8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS
@@ -1,2 +1 @@
-calin@google.com
-ngeoffray@google.com
+include platform/art:/OWNERS
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index a6d146e..3cbc226 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -151,7 +151,8 @@
eq(userId),
eq(mSensorReceiver),
eq(TEST_PACKAGE),
- eq(sensor.getCookie()));
+ eq(sensor.getCookie()),
+ anyBoolean() /* allowBackgroundAuthentication */);
}
final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 0c95e05..abc8737 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -456,7 +456,8 @@
anyInt() /* userId */,
any(IBiometricSensorReceiver.class),
anyString() /* opPackageName */,
- cookieCaptor.capture() /* cookie */);
+ cookieCaptor.capture() /* cookie */,
+ anyBoolean() /* allowBackgroundAuthentication */);
// onReadyForAuthentication, mCurrentAuthSession state OK
mBiometricService.mImpl.onReadyForAuthentication(cookieCaptor.getValue());
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index bc86d1d..4295172 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -93,7 +93,9 @@
private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
private static final String VIRTUAL_DISPLAY_NAME = "Test Virtual Display";
private static final String PACKAGE_NAME = "com.android.frameworks.servicestests";
-
+ private static final long ALL_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -355,29 +357,13 @@
// Find the display id of the added FakeDisplayDevice
DisplayManagerService.BinderService bs = displayManager.new BinderService();
- final int[] displayIds = bs.getDisplayIds();
- assertTrue(displayIds.length > 0);
- int displayId = Display.INVALID_DISPLAY;
- for (int i = 0; i < displayIds.length; i++) {
- DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayIds[i]);
- if (displayDeviceInfo.equals(ddi)) {
- displayId = displayIds[i];
- break;
- }
- }
- assertFalse(displayId == Display.INVALID_DISPLAY);
-
+ int displayId = getDisplayIdForDisplayDevice(displayManager, bs, displayDevice);
// Setup override DisplayInfo
DisplayInfo overrideInfo = bs.getDisplayInfo(displayId);
displayManager.setDisplayInfoOverrideFromWindowManagerInternal(displayId, overrideInfo);
- Handler handler = displayManager.getDisplayHandler();
- handler.runWithScissors(() -> {
- }, 0 /* now */);
-
- // register display listener callback
- FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId);
- bs.registerCallback(callback);
+ FakeDisplayManagerCallback callback = registerDisplayListenerCallback(
+ displayManager, bs, displayDevice);
// Simulate DisplayDevice change
DisplayDeviceInfo displayDeviceInfo2 = new DisplayDeviceInfo();
@@ -387,9 +373,9 @@
displayManager.getDisplayDeviceRepository()
.onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED);
- handler.runWithScissors(() -> {
- }, 0 /* now */);
- assertTrue(callback.mCalled);
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+ assertTrue(callback.mDisplayChangedCalled);
}
/**
@@ -400,7 +386,7 @@
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
Handler handler = displayManager.getDisplayHandler();
- handler.runWithScissors(() -> {}, 0 /* now */);
+ waitForIdleHandler(handler);
try {
displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
@@ -616,7 +602,7 @@
}
/**
- * Tests that there should be a display change notification if the frame rate overrides
+ * Tests that there is a display change notification if the frame rate override
* list is updated.
*/
@Test
@@ -637,7 +623,7 @@
new DisplayEventReceiver.FrameRateOverride[]{
new DisplayEventReceiver.FrameRateOverride(myUid, 30f),
});
- assertTrue(callback.mCalled);
+ assertTrue(callback.mDisplayChangedCalled);
callback.clear();
updateFrameRateOverride(displayManager, displayDevice,
@@ -645,7 +631,7 @@
new DisplayEventReceiver.FrameRateOverride(myUid, 30f),
new DisplayEventReceiver.FrameRateOverride(1234, 30f),
});
- assertFalse(callback.mCalled);
+ assertFalse(callback.mDisplayChangedCalled);
updateFrameRateOverride(displayManager, displayDevice,
new DisplayEventReceiver.FrameRateOverride[]{
@@ -653,7 +639,7 @@
new DisplayEventReceiver.FrameRateOverride(1234, 30f),
new DisplayEventReceiver.FrameRateOverride(5678, 30f),
});
- assertTrue(callback.mCalled);
+ assertTrue(callback.mDisplayChangedCalled);
callback.clear();
updateFrameRateOverride(displayManager, displayDevice,
@@ -661,14 +647,14 @@
new DisplayEventReceiver.FrameRateOverride(1234, 30f),
new DisplayEventReceiver.FrameRateOverride(5678, 30f),
});
- assertTrue(callback.mCalled);
+ assertTrue(callback.mDisplayChangedCalled);
callback.clear();
updateFrameRateOverride(displayManager, displayDevice,
new DisplayEventReceiver.FrameRateOverride[]{
new DisplayEventReceiver.FrameRateOverride(5678, 30f),
});
- assertFalse(callback.mCalled);
+ assertFalse(callback.mDisplayChangedCalled);
}
/**
@@ -760,6 +746,136 @@
/*compatChangeEnabled*/ true);
}
+ /**
+ * Tests that EVENT_DISPLAY_ADDED is sent when a display is added.
+ */
+ @Test
+ public void testShouldNotifyDisplayAdded_WhenNewDisplayDeviceIsAdded() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+
+ // register display listener callback
+ FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+ displayManagerBinderService.registerCallbackWithEventMask(callback, ALL_DISPLAY_EVENTS);
+
+ waitForIdleHandler(handler);
+
+ createFakeDisplayDevice(displayManager, new float[]{60f});
+
+ waitForIdleHandler(handler);
+
+ assertFalse(callback.mDisplayChangedCalled);
+ assertFalse(callback.mDisplayRemovedCalled);
+ assertTrue(callback.mDisplayAddedCalled);
+ }
+
+ /**
+ * Tests that EVENT_DISPLAY_ADDED is not sent when a display is added and the
+ * client has a callback which is not subscribed to this event type.
+ */
+ @Test
+ public void testShouldNotNotifyDisplayAdded_WhenClientIsNotSubscribed() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+
+ // register display listener callback
+ FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+ long allEventsExceptDisplayAdded = ALL_DISPLAY_EVENTS
+ & ~DisplayManager.EVENT_FLAG_DISPLAY_ADDED;
+ displayManagerBinderService.registerCallbackWithEventMask(callback,
+ allEventsExceptDisplayAdded);
+
+ waitForIdleHandler(handler);
+
+ createFakeDisplayDevice(displayManager, new float[]{60f});
+
+ waitForIdleHandler(handler);
+
+ assertFalse(callback.mDisplayChangedCalled);
+ assertFalse(callback.mDisplayRemovedCalled);
+ assertFalse(callback.mDisplayAddedCalled);
+ }
+
+ /**
+ * Tests that EVENT_DISPLAY_REMOVED is sent when a display is removed.
+ */
+ @Test
+ public void testShouldNotifyDisplayRemoved_WhenDisplayDeviceIsRemoved() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+
+ FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
+ new float[]{60f});
+
+ waitForIdleHandler(handler);
+
+ FakeDisplayManagerCallback callback = registerDisplayListenerCallback(
+ displayManager, displayManagerBinderService, displayDevice);
+
+ waitForIdleHandler(handler);
+
+ displayManager.getDisplayDeviceRepository()
+ .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
+
+ waitForIdleHandler(handler);
+
+ assertFalse(callback.mDisplayChangedCalled);
+ assertTrue(callback.mDisplayRemovedCalled);
+ assertFalse(callback.mDisplayAddedCalled);
+ }
+
+ /**
+ * Tests that EVENT_DISPLAY_REMOVED is not sent when a display is added and the
+ * client has a callback which is not subscribed to this event type.
+ */
+ @Test
+ public void testShouldNotNotifyDisplayRemoved_WhenClientIsNotSubscribed() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+
+ Handler handler = displayManager.getDisplayHandler();
+ waitForIdleHandler(handler);
+
+ FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
+ new float[]{60f});
+
+ waitForIdleHandler(handler);
+
+ FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+ long allEventsExceptDisplayRemoved = ALL_DISPLAY_EVENTS
+ & ~DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
+ displayManagerBinderService.registerCallbackWithEventMask(callback,
+ allEventsExceptDisplayRemoved);
+
+ waitForIdleHandler(handler);
+
+ displayManager.getDisplayDeviceRepository()
+ .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
+
+ waitForIdleHandler(handler);
+
+ assertFalse(callback.mDisplayChangedCalled);
+ assertFalse(callback.mDisplayRemovedCalled);
+ assertFalse(callback.mDisplayAddedCalled);
+ }
+
private void testDisplayInfoFrameRateOverrideModeCompat(boolean compatChangeEnabled)
throws Exception {
DisplayManagerService displayManager =
@@ -879,8 +995,7 @@
displayManager.getDisplayDeviceRepository()
.onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED);
Handler handler = displayManager.getDisplayHandler();
- handler.runWithScissors(() -> {
- }, 0 /* now */);
+ waitForIdleHandler(handler);
}
private void updateFrameRateOverride(DisplayManagerService displayManager,
@@ -906,18 +1021,15 @@
DisplayManagerService.BinderService displayManagerBinderService,
FakeDisplayDevice displayDevice) {
// Find the display id of the added FakeDisplayDevice
- DisplayDeviceInfo displayDeviceInfo = displayDevice.getDisplayDeviceInfoLocked();
-
int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
displayDevice);
Handler handler = displayManager.getDisplayHandler();
- handler.runWithScissors(() -> {
- }, 0 /* now */);
+ waitForIdleHandler(handler);
// register display listener callback
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId);
- displayManagerBinderService.registerCallback(callback);
+ displayManagerBinderService.registerCallbackWithEventMask(callback, ALL_DISPLAY_EVENTS);
return callback;
}
@@ -951,6 +1063,10 @@
// Would prefer to call displayManager.onStart() directly here but it performs binderService
// registration which triggers security exceptions when running from a test.
handler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
+ waitForIdleHandler(handler);
+ }
+
+ private void waitForIdleHandler(Handler handler) {
waitForIdleHandler(handler, Duration.ofSeconds(1));
}
@@ -971,21 +1087,41 @@
private class FakeDisplayManagerCallback extends IDisplayManagerCallback.Stub {
int mDisplayId;
- boolean mCalled = false;
+ boolean mDisplayAddedCalled = false;
+ boolean mDisplayChangedCalled = false;
+ boolean mDisplayRemovedCalled = false;
FakeDisplayManagerCallback(int displayId) {
mDisplayId = displayId;
}
+ FakeDisplayManagerCallback() {
+ mDisplayId = -1;
+ }
+
@Override
public void onDisplayEvent(int displayId, int event) {
- if (displayId == mDisplayId && event == DisplayManagerGlobal.EVENT_DISPLAY_CHANGED) {
- mCalled = true;
+ if (mDisplayId != -1 && displayId != mDisplayId) {
+ return;
+ }
+
+ if (event == DisplayManagerGlobal.EVENT_DISPLAY_ADDED) {
+ mDisplayAddedCalled = true;
+ }
+
+ if (event == DisplayManagerGlobal.EVENT_DISPLAY_CHANGED) {
+ mDisplayChangedCalled = true;
+ }
+
+ if (event == DisplayManagerGlobal.EVENT_DISPLAY_REMOVED) {
+ mDisplayRemovedCalled = true;
}
}
public void clear() {
- mCalled = false;
+ mDisplayAddedCalled = false;
+ mDisplayChangedCalled = false;
+ mDisplayRemovedCalled = false;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index bcd853c..dcb2c15 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -186,11 +186,14 @@
LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0));
LogicalDisplay display3 = add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0));
+ // Physical displays should be automatically put into the default group.
assertEquals(Display.DEFAULT_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1)));
assertEquals(Display.DEFAULT_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2)));
- assertEquals(Display.DEFAULT_DISPLAY_GROUP,
+
+ // Virtual displays should belong to no group by default.
+ assertEquals(Display.INVALID_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
}
@@ -212,13 +215,13 @@
assertNotEquals(Display.DEFAULT_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
- // Now switch it back to the default group by removing the flag and issuing an update
+ // Now switch it to the invalid group by removing the flag and issuing an update
DisplayDeviceInfo info = device3.getSourceInfo();
info.flags = info.flags & ~DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP;
mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
- // Verify the new group is correct.
- assertEquals(Display.DEFAULT_DISPLAY_GROUP,
+ // Verify the virtual display has not been placed into a group.
+ assertEquals(Display.INVALID_DISPLAY_GROUP,
mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
index 55cd772..94e67d1 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
@@ -23,15 +23,14 @@
import android.content.om.OverlayIdentifier;
import android.content.om.OverlayInfo;
-import android.util.ArraySet;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.Arrays;
-import java.util.function.BiConsumer;
+import java.util.Set;
+import java.util.function.Consumer;
@RunWith(AndroidJUnit4.class)
public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceImplTestsBase {
@@ -45,51 +44,47 @@
private static final OverlayIdentifier IDENTIFIER2 = new OverlayIdentifier(OVERLAY2);
@Test
- public void testUpdateOverlaysForUser() {
+ public void alwaysInitializeAllPackages() {
final OverlayManagerServiceImpl impl = getImpl();
final String otherTarget = "some.other.target";
addPackage(target(TARGET), USER);
addPackage(target(otherTarget), USER);
addPackage(overlay(OVERLAY, TARGET), USER);
- // do nothing, expect no change
- final ArraySet<PackageAndUser> a = impl.updateOverlaysForUser(USER);
- assertEquals(3, a.size());
- assertTrue(a.containsAll(Arrays.asList(
- new PackageAndUser(TARGET, USER),
- new PackageAndUser(otherTarget, USER),
- new PackageAndUser(OVERLAY, USER))));
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER),
+ new PackageAndUser(otherTarget, USER),
+ new PackageAndUser(OVERLAY, USER));
- final ArraySet<PackageAndUser> b = impl.updateOverlaysForUser(USER);
- assertEquals(3, b.size());
- assertTrue(b.containsAll(Arrays.asList(
- new PackageAndUser(TARGET, USER),
- new PackageAndUser(otherTarget, USER),
- new PackageAndUser(OVERLAY, USER))));
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
}
@Test
- public void testImmutableEnabledChange() throws Exception {
+ public void testImmutableEnabledChange() {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
- configureSystemOverlay(OVERLAY, false /* mutable */, false /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER));
+
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_DISABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o1);
assertFalse(o1.isEnabled());
assertFalse(o1.isMutable);
- configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_ENABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o2 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o2);
assertTrue(o2.isEnabled());
assertFalse(o2.isMutable);
- configureSystemOverlay(OVERLAY, false /* mutable */, false /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_DISABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o3 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o3);
assertFalse(o3.isEnabled());
@@ -97,27 +92,30 @@
}
@Test
- public void testMutableEnabledChangeHasNoEffect() throws Exception {
+ public void testMutableEnabledChangeHasNoEffect() {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_DISABLED, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER));
+
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o1);
assertFalse(o1.isEnabled());
assertTrue(o1.isMutable);
- configureSystemOverlay(OVERLAY, true /* mutable */, true /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_ENABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o2 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o2);
assertFalse(o2.isEnabled());
assertTrue(o2.isMutable);
- configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_DISABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o3 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o3);
assertFalse(o3.isEnabled());
@@ -125,59 +123,68 @@
}
@Test
- public void testMutableEnabledToImmutableEnabled() throws Exception {
+ public void testMutableEnabledToImmutableEnabled() {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
- final BiConsumer<Boolean, Boolean> setOverlay = (mutable, enabled) -> {
- configureSystemOverlay(OVERLAY, mutable, enabled, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER));
+
+ final Consumer<ConfigState> setOverlay = (state -> {
+ configureSystemOverlay(OVERLAY, state, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o);
- assertEquals(enabled, o.isEnabled());
- assertEquals(mutable, o.isMutable);
- };
+ assertEquals(o.isEnabled(), state == ConfigState.IMMUTABLE_ENABLED
+ || state == ConfigState.MUTABLE_ENABLED);
+ assertEquals(o.isMutable, state == ConfigState.MUTABLE_DISABLED
+ || state == ConfigState.MUTABLE_ENABLED);
+ });
// Immutable/enabled -> mutable/enabled
- setOverlay.accept(false /* mutable */, true /* enabled */);
- setOverlay.accept(true /* mutable */, true /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_ENABLED);
+ setOverlay.accept(ConfigState.MUTABLE_ENABLED);
// Mutable/enabled -> immutable/enabled
- setOverlay.accept(false /* mutable */, true /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_ENABLED);
// Immutable/enabled -> mutable/disabled
- setOverlay.accept(true /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.MUTABLE_DISABLED);
// Mutable/disabled -> immutable/enabled
- setOverlay.accept(false /* mutable */, true /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_ENABLED);
// Immutable/enabled -> immutable/disabled
- setOverlay.accept(false /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_DISABLED);
// Immutable/disabled -> mutable/enabled
- setOverlay.accept(true /* mutable */, true /* enabled */);
+ setOverlay.accept(ConfigState.MUTABLE_ENABLED);
// Mutable/enabled -> immutable/disabled
- setOverlay.accept(false /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_DISABLED);
// Immutable/disabled -> mutable/disabled
- setOverlay.accept(true /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.MUTABLE_DISABLED);
// Mutable/disabled -> immutable/disabled
- setOverlay.accept(false /* mutable */, false /* enabled */);
+ setOverlay.accept(ConfigState.IMMUTABLE_DISABLED);
}
@Test
public void testMutablePriorityChange() throws Exception {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
- configureSystemOverlay(OVERLAY2, true /* mutable */, false /* enabled */, 1 /* priority */);
- impl.updateOverlaysForUser(USER);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(overlay(OVERLAY2, TARGET), USER);
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_DISABLED, 0 /* priority */);
+ configureSystemOverlay(OVERLAY2, ConfigState.MUTABLE_DISABLED, 1 /* priority */);
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER),
+ new PackageAndUser(OVERLAY2, USER));
+
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o1);
assertEquals(0, o1.priority);
@@ -193,10 +200,9 @@
impl.setEnabled(IDENTIFIER, true, USER);
// Reorder the overlays
- configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 1 /* priority */);
- configureSystemOverlay(OVERLAY2, true /* mutable */, false /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
-
+ configureSystemOverlay(OVERLAY, ConfigState.MUTABLE_DISABLED, 1 /* priority */);
+ configureSystemOverlay(OVERLAY2, ConfigState.MUTABLE_DISABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o3 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o3);
assertEquals(1, o3.priority);
@@ -211,13 +217,17 @@
@Test
public void testImmutablePriorityChange() throws Exception {
final OverlayManagerServiceImpl impl = getImpl();
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 0 /* priority */);
- configureSystemOverlay(OVERLAY2, false /* mutable */, true /* enabled */, 1 /* priority */);
- impl.updateOverlaysForUser(USER);
+ addPackage(target(TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(overlay(OVERLAY2, TARGET), USER);
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_ENABLED, 0 /* priority */);
+ configureSystemOverlay(OVERLAY2, ConfigState.IMMUTABLE_ENABLED, 1 /* priority */);
+ final Set<PackageAndUser> allPackages =
+ Set.of(new PackageAndUser(TARGET, USER), new PackageAndUser(OVERLAY, USER),
+ new PackageAndUser(OVERLAY2, USER));
+
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o1);
assertEquals(0, o1.priority);
@@ -229,10 +239,9 @@
assertTrue(o2.isEnabled());
// Reorder the overlays
- configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 1 /* priority */);
- configureSystemOverlay(OVERLAY2, false /* mutable */, true /* enabled */, 0 /* priority */);
- impl.updateOverlaysForUser(USER);
-
+ configureSystemOverlay(OVERLAY, ConfigState.IMMUTABLE_ENABLED, 1 /* priority */);
+ configureSystemOverlay(OVERLAY2, ConfigState.IMMUTABLE_ENABLED, 0 /* priority */);
+ assertEquals(allPackages, impl.updateOverlaysForUser(USER));
final OverlayInfo o3 = impl.getOverlayInfo(IDENTIFIER, USER);
assertNotNull(o3);
assertEquals(1, o3.priority);
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index 45f82a3..f69141d 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -65,7 +65,8 @@
@Test
public void testGetOverlayInfo() throws Exception {
- installPackage(overlay(OVERLAY, TARGET), USER);
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final OverlayManagerServiceImpl impl = getImpl();
final OverlayInfo oi = impl.getOverlayInfo(IDENTIFIER, USER);
@@ -77,9 +78,12 @@
@Test
public void testGetOverlayInfosForTarget() throws Exception {
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- installPackage(overlay(OVERLAY3, TARGET), USER2);
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY2, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY2, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY3, TARGET), USER2,
+ Set.of(new PackageAndUser(OVERLAY3, USER2), new PackageAndUser(TARGET, USER2)));
final OverlayManagerServiceImpl impl = getImpl();
final List<OverlayInfo> ois = impl.getOverlayInfosForTarget(TARGET, USER);
@@ -102,10 +106,14 @@
@Test
public void testGetOverlayInfosForUser() throws Exception {
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- installPackage(overlay(OVERLAY3, TARGET2), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY2, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY2, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY3, TARGET2), USER,
+ Set.of(new PackageAndUser(OVERLAY3, USER), new PackageAndUser(TARGET2, USER)));
final OverlayManagerServiceImpl impl = getImpl();
final Map<String, List<OverlayInfo>> everything = impl.getOverlaysForUser(USER);
@@ -129,9 +137,12 @@
@Test
public void testPriority() throws Exception {
- installPackage(overlay(OVERLAY, TARGET), USER);
- installPackage(overlay(OVERLAY2, TARGET), USER);
- installPackage(overlay(OVERLAY3, TARGET), USER);
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY2, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY2, USER), new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY3, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY3, USER), new PackageAndUser(TARGET, USER)));
final OverlayManagerServiceImpl impl = getImpl();
final OverlayInfo o1 = impl.getOverlayInfo(IDENTIFIER, USER);
@@ -158,11 +169,12 @@
final OverlayManagerServiceImpl impl = getImpl();
assertNull(impl.getOverlayInfo(IDENTIFIER, USER));
- installPackage(overlay(OVERLAY, TARGET), USER);
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
assertState(STATE_MISSING_TARGET, IDENTIFIER, USER);
- final FakeDeviceState.PackageBuilder target = target(TARGET);
- installPackage(target, USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_DISABLED, IDENTIFIER, USER);
assertEquals(impl.setEnabled(IDENTIFIER, true, USER),
@@ -170,32 +182,35 @@
assertState(STATE_ENABLED, IDENTIFIER, USER);
// target upgrades do not change the state of the overlay
- upgradePackage(target, USER);
+ upgradeAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)),
+ Set.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_ENABLED, IDENTIFIER, USER);
- uninstallPackage(TARGET, USER);
+ uninstallAndAssert(TARGET, USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_MISSING_TARGET, IDENTIFIER, USER);
- installPackage(target, USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
assertState(STATE_ENABLED, IDENTIFIER, USER);
}
@Test
public void testOnOverlayPackageUpgraded() throws Exception {
- final FakeDeviceState.PackageBuilder target = target(TARGET);
- final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
- installPackage(target, USER);
- installPackage(overlay, USER);
- upgradePackage(overlay, USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ upgradeAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)),
+ Set.of(new PackageAndUser(TARGET, USER)));
// upgrade to a version where the overlay has changed its target
- final FakeDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
- final Pair<Set<PackageAndUser>, Set<PackageAndUser>> pair = upgradePackage(overlay2, USER);
- assertEquals(pair.first, Set.of(new PackageAndUser(TARGET, USER)));
- assertEquals(
+ upgradeAndAssert(overlay(OVERLAY, TARGET2), USER,
+ Set.of(new PackageAndUser(TARGET, USER)),
Set.of(new PackageAndUser(TARGET, USER),
- new PackageAndUser("some.other.target", USER)),
- pair.second);
+ new PackageAndUser(TARGET2, USER)));
}
@Test
@@ -206,13 +221,15 @@
// request succeeded, and there was a change that needs to be
// propagated to the rest of the system
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET), USER);
- assertEquals(impl.setEnabled(IDENTIFIER, true, USER),
+ installAndAssert(target(TARGET), USER,
Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
+ assertEquals(Set.of(new PackageAndUser(TARGET, USER)),
+ impl.setEnabled(IDENTIFIER, true, USER));
// request succeeded, but nothing changed
- assertTrue(impl.setEnabled(IDENTIFIER, true, USER).isEmpty());
+ assertEquals(Set.of(), impl.setEnabled(IDENTIFIER, true, USER));
}
@Test
@@ -221,16 +238,18 @@
reinitializeImpl();
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
- String overlayPath = state.select(OVERLAY, USER).apkPath;
+ final String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == CONFIG_SIGNATURE);
+ final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertEquals(CONFIG_SIGNATURE, CONFIG_SIGNATURE & idmap.policies);
}
@Test
@@ -239,45 +258,51 @@
reinitializeImpl();
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
- String overlayPath = state.select(OVERLAY, USER).apkPath;
+ final String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
}
@Test
public void testConfigSignaturePolicyNoConfig() throws Exception {
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
- String overlayPath = state.select(OVERLAY, USER).apkPath;
+ final String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
}
@Test
public void testConfigSignaturePolicyNoRefPkg() throws Exception {
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
- String overlayPath = state.select(OVERLAY, USER).apkPath;
+ final String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ final FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
}
@Test
@@ -286,8 +311,10 @@
reinitializeImpl();
addPackage(app(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
- installPackage(target(TARGET), USER);
- installPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+ installAndAssert(target(TARGET), USER,
+ Set.of(new PackageAndUser(TARGET, USER)));
+ installAndAssert(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER,
+ Set.of(new PackageAndUser(OVERLAY, USER), new PackageAndUser(TARGET, USER)));
final FakeIdmapDaemon idmapd = getIdmapd();
final FakeDeviceState state = getState();
@@ -295,6 +322,6 @@
assertTrue(idmapd.idmapExists(overlayPath, USER));
FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
- assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ assertEquals(0, CONFIG_SIGNATURE & idmap.policies);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
index 16e0329..29ff9f4 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -139,8 +139,19 @@
mState.add(pkg, userId);
}
- void configureSystemOverlay(String packageName, boolean mutable, boolean enabled,
+ enum ConfigState {
+ IMMUTABLE_DISABLED,
+ IMMUTABLE_ENABLED,
+ MUTABLE_DISABLED,
+ MUTABLE_ENABLED
+ }
+
+ void configureSystemOverlay(@NonNull String packageName, @NonNull ConfigState state,
int priority) {
+ final boolean mutable = state == ConfigState.MUTABLE_DISABLED
+ || state == ConfigState.MUTABLE_ENABLED;
+ final boolean enabled = state == ConfigState.IMMUTABLE_ENABLED
+ || state == ConfigState.MUTABLE_ENABLED;
when(mOverlayConfig.getPriority(packageName)).thenReturn(priority);
when(mOverlayConfig.isEnabled(packageName)).thenReturn(enabled);
when(mOverlayConfig.isMutable(packageName)).thenReturn(mutable);
@@ -154,13 +165,14 @@
*
* @throws IllegalStateException if the package is currently installed
*/
- Set<PackageAndUser> installPackage(FakeDeviceState.PackageBuilder pkg, int userId)
+ void installAndAssert(@NonNull FakeDeviceState.PackageBuilder pkg, int userId,
+ @NonNull Set<PackageAndUser> onAddedUpdatedPackages)
throws OperationFailedException {
if (mState.select(pkg.packageName, userId) != null) {
throw new IllegalStateException("package " + pkg.packageName + " already installed");
}
mState.add(pkg, userId);
- return CollectionUtils.emptyIfNull(mImpl.onPackageAdded(pkg.packageName, userId));
+ assertEquals(onAddedUpdatedPackages, mImpl.onPackageAdded(pkg.packageName, userId));
}
/**
@@ -172,25 +184,20 @@
* {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
* {@link android.content.Intent#EXTRA_REPLACING} extra.
*
- * @return the two Optional<PackageAndUser> objects from starting and finishing the upgrade
- *
* @throws IllegalStateException if the package is not currently installed
*/
- Pair<Set<PackageAndUser>, Set<PackageAndUser>> upgradePackage(
- FakeDeviceState.PackageBuilder pkg, int userId) throws OperationFailedException {
+ void upgradeAndAssert(FakeDeviceState.PackageBuilder pkg, int userId,
+ @NonNull Set<PackageAndUser> onReplacingUpdatedPackages,
+ @NonNull Set<PackageAndUser> onReplacedUpdatedPackages)
+ throws OperationFailedException {
final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
if (replacedPackage == null) {
throw new IllegalStateException("package " + pkg.packageName + " not installed");
}
- final Set<PackageAndUser> updatedPackages1 =
- CollectionUtils.emptyIfNull(mImpl.onPackageReplacing(pkg.packageName, userId));
-
+ assertEquals(onReplacingUpdatedPackages, mImpl.onPackageReplacing(pkg.packageName, userId));
mState.add(pkg, userId);
- final Set<PackageAndUser> updatedPackages2 =
- CollectionUtils.emptyIfNull(mImpl.onPackageReplaced(pkg.packageName, userId));
-
- return Pair.create(updatedPackages1, updatedPackages2);
+ assertEquals(onReplacedUpdatedPackages, mImpl.onPackageReplaced(pkg.packageName, userId));
}
/**
@@ -201,13 +208,14 @@
*
* @throws IllegalStateException if the package is not currently installed
*/
- Set<PackageAndUser> uninstallPackage(String packageName, int userId) {
+ void uninstallAndAssert(@NonNull String packageName, int userId,
+ @NonNull Set<PackageAndUser> onRemovedUpdatedPackages) {
final FakeDeviceState.Package pkg = mState.select(packageName, userId);
if (pkg == null) {
- throw new IllegalStateException("package " + packageName+ " not installed");
+ throw new IllegalStateException("package " + packageName + " not installed");
}
mState.remove(pkg.packageName);
- return CollectionUtils.emptyIfNull(mImpl.onPackageRemoved(packageName, userId));
+ assertEquals(onRemovedUpdatedPackages, mImpl.onPackageRemoved(pkg.packageName, userId));
}
/** Represents the state of packages installed on a fake device. */
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
index e605d75..13d75a7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
@@ -245,14 +245,6 @@
UID,
COMPILATION_REASON,
COMPILER_FILTER,
- ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_DEX_CODE_BYTES,
- DEX_CONTENT.length,
- dexMetadataType);
- inorder.verify(mockLogger).write(
- SESSION_ID,
- UID,
- COMPILATION_REASON,
- COMPILER_FILTER,
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME,
COMPILE_TIME,
dexMetadataType);
diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
index 9b8a2a8..324e592 100644
--- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
@@ -18,6 +18,7 @@
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
+import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -70,6 +71,7 @@
private FileWriter mUncryptUpdateFileWriter;
private LockSettingsInternal mLockSettingsInternal;
private IBootControl mIBootControl;
+ private RecoverySystemServiceTestable.IMetricsReporter mMetricsReporter;
private static final String FAKE_OTA_PACKAGE_NAME = "fake.ota.package";
private static final String FAKE_OTHER_PACKAGE_NAME = "fake.other.package";
@@ -94,9 +96,11 @@
when(mIBootControl.getCurrentSlot()).thenReturn(0);
when(mIBootControl.getActiveBootSlot()).thenReturn(1);
+ mMetricsReporter = mock(RecoverySystemServiceTestable.IMetricsReporter.class);
+
mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties,
powerManager, mUncryptUpdateFileWriter, mUncryptSocket, mLockSettingsInternal,
- mIBootControl);
+ mIBootControl, mMetricsReporter);
}
@Test
@@ -227,12 +231,24 @@
}
@Test
+ public void requestLskf_reportMetrics() throws Exception {
+ IntentSender intentSender = mock(IntentSender.class);
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+ is(true));
+ verify(mMetricsReporter).reportRebootEscrowPreparationMetrics(
+ eq(1000), eq(0) /* need preparation */, eq(1) /* client count */);
+ }
+
+
+ @Test
public void requestLskf_success() throws Exception {
IntentSender intentSender = mock(IntentSender.class);
assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
is(true));
mRecoverySystemService.onPreparedForReboot(true);
verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
+ verify(mMetricsReporter).reportRebootEscrowLskfCapturedMetrics(
+ eq(1000), eq(1) /* client count */, anyInt() /* duration */);
}
@Test
@@ -255,6 +271,8 @@
assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
is(true));
verify(intentSender, never()).sendIntent(any(), anyInt(), any(), any(), any());
+ verify(mMetricsReporter, never()).reportRebootEscrowLskfCapturedMetrics(
+ anyInt(), anyInt(), anyInt());
}
@Test
@@ -337,6 +355,9 @@
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true),
is(true));
verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
+ verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000),
+ eq(1) /* client count */, eq(1) /* request count */, eq(true) /* slot switch */,
+ anyBoolean(), anyInt(), eq(1) /* lskf capture count */);
}
@@ -373,6 +394,20 @@
verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
}
+ @Test
+ public void rebootWithLskf_multiClient_success_reportMetrics() throws Exception {
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
+ mRecoverySystemService.onPreparedForReboot(true);
+
+ // Client B's clear won't affect client A's preparation.
+ assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true),
+ is(true));
+ verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
+ verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000),
+ eq(2) /* client count */, eq(1) /* request count */, eq(true) /* slot switch */,
+ anyBoolean(), anyInt(), eq(1) /* lskf capture count */);
+ }
@Test
public void rebootWithLskf_multiClient_ClientBSuccess() throws Exception {
@@ -384,12 +419,18 @@
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true),
is(false));
verifyNoMoreInteractions(mIPowerManager);
+ verify(mMetricsReporter).reportRebootEscrowRebootMetrics(not(eq(0)), eq(1000),
+ eq(1) /* client count */, eq(1) /* request count */, eq(true) /* slot switch */,
+ anyBoolean(), anyInt(), eq(1) /* lskf capture count */);
assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
assertThat(
mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true),
is(true));
verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
+ verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(2000),
+ eq(1) /* client count */, eq(1) /* request count */, eq(true) /* slot switch */,
+ anyBoolean(), anyInt(), eq(1) /* lskf capture count */);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java
index 0727e5a..a894178 100644
--- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java
@@ -32,11 +32,12 @@
private final UncryptSocket mUncryptSocket;
private final LockSettingsInternal mLockSettingsInternal;
private final IBootControl mIBootControl;
+ private final IMetricsReporter mIMetricsReporter;
MockInjector(Context context, FakeSystemProperties systemProperties,
PowerManager powerManager, FileWriter uncryptPackageFileWriter,
UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal,
- IBootControl bootControl) {
+ IBootControl bootControl, IMetricsReporter metricsReporter) {
super(context);
mSystemProperties = systemProperties;
mPowerManager = powerManager;
@@ -44,6 +45,7 @@
mUncryptSocket = uncryptSocket;
mLockSettingsInternal = lockSettingsInternal;
mIBootControl = bootControl;
+ mIMetricsReporter = metricsReporter;
}
@Override
@@ -94,14 +96,45 @@
public IBootControl getBootControl() {
return mIBootControl;
}
+ @Override
+ public int getUidFromPackageName(String packageName) {
+ if ("fake.ota.package".equals(packageName)) {
+ return 1000;
+ }
+ if ("fake.other.package".equals(packageName)) {
+ return 2000;
+ }
+ return 3000;
+ }
+
+ @Override
+ public void reportRebootEscrowPreparationMetrics(int uid, int requestResult,
+ int requestedClientCount) {
+ mIMetricsReporter.reportRebootEscrowPreparationMetrics(uid, requestResult,
+ requestedClientCount);
+ }
+
+ public void reportRebootEscrowLskfCapturedMetrics(int uid, int requestedClientCount,
+ int requestedToLskfCapturedDurationInSeconds) {
+ mIMetricsReporter.reportRebootEscrowLskfCapturedMetrics(uid, requestedClientCount,
+ requestedToLskfCapturedDurationInSeconds);
+ }
+
+ public void reportRebootEscrowRebootMetrics(int errorCode, int uid, int preparedClientCount,
+ int requestCount, boolean slotSwitch, boolean serverBased,
+ int lskfCapturedToRebootDurationInSeconds, int lskfCapturedCounts) {
+ mIMetricsReporter.reportRebootEscrowRebootMetrics(errorCode, uid, preparedClientCount,
+ requestCount, slotSwitch, serverBased, lskfCapturedToRebootDurationInSeconds,
+ lskfCapturedCounts);
+ }
}
RecoverySystemServiceTestable(Context context, FakeSystemProperties systemProperties,
PowerManager powerManager, FileWriter uncryptPackageFileWriter,
UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal,
- IBootControl bootControl) {
+ IBootControl bootControl, IMetricsReporter metricsReporter) {
super(new MockInjector(context, systemProperties, powerManager, uncryptPackageFileWriter,
- uncryptSocket, lockSettingsInternal, bootControl));
+ uncryptSocket, lockSettingsInternal, bootControl, metricsReporter));
}
public static class FakeSystemProperties {
@@ -131,4 +164,17 @@
return mCtlStart;
}
}
+
+ public interface IMetricsReporter {
+ void reportRebootEscrowPreparationMetrics(int uid, int requestResult,
+ int requestedClientCount);
+
+ void reportRebootEscrowLskfCapturedMetrics(int uid, int requestedClientCount,
+ int requestedToLskfCapturedDurationInSeconds);
+
+ void reportRebootEscrowRebootMetrics(int errorCode, int uid, int preparedClientCount,
+ int requestCount, boolean slotSwitch, boolean serverBased,
+ int lskfCapturedToRebootDurationInSeconds, int lskfCapturedCounts);
+ }
+
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 624c3de..86b1620 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -1390,6 +1390,21 @@
}
@Test
+ public void testRestrictApp_MainReason() throws Exception {
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
+ REASON_MAIN_DEFAULT);
+ mInjector.mElapsedRealtime += 4 * RESTRICTED_THRESHOLD;
+
+ mController.restrictApp(PACKAGE_1, USER_ID, REASON_MAIN_PREDICTED, 0);
+ // Call should be ignored.
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
+
+ mController.restrictApp(PACKAGE_1, USER_ID, REASON_MAIN_FORCED_BY_USER, 0);
+ // Call should go through
+ assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
+ }
+
+ @Test
public void testAddActiveDeviceAdmin() throws Exception {
assertActiveAdmins(USER_ID, (String[]) null);
assertActiveAdmins(USER_ID2, (String[]) null);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 7f9e7da..4e2697a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -134,6 +134,7 @@
null, TYPE_BASE_APPLICATION, activity, name, ownerId, false, new TestIWindow());
window.mInputChannel = new InputChannel();
window.mHasSurface = true;
+ mWm.mInputToWindowMap.put(window.mInputChannelToken, window);
return window;
}
@@ -226,7 +227,7 @@
// Verify after consuming that the drag surface is relinquished
try {
mTarget.mDeferDragStateClosed = true;
-
+ mTarget.reportDropWindow(mWindow.mInputChannelToken, 0, 0);
// Verify the drop event includes the drag surface
mTarget.handleMotionEvent(false, 0, 0);
final DragEvent dropEvent = dragEvents.get(dragEvents.size() - 1);
@@ -355,6 +356,7 @@
private void doDragAndDrop(int flags, ClipData data, float dropX, float dropY) {
startDrag(flags, data, () -> {
+ mTarget.reportDropWindow(mWindow.mInputChannelToken, dropX, dropY);
mTarget.handleMotionEvent(false, dropX, dropY);
mToken = mWindow.mClient.asBinder();
});
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 5c7e580..70c2971 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -27,6 +27,8 @@
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -325,6 +327,22 @@
}
@Test
+ public void testIsLetterboxed_activityShowsWallpaper_returnsFalse() {
+ setUpDisplaySizeWithApp(1000, 2500);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+ final WindowState window = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "window");
+
+ assertEquals(window, mActivity.findMainWindow());
+ assertTrue(mActivity.isLetterboxed(mActivity.findMainWindow()));
+
+ window.mAttrs.flags |= FLAG_SHOW_WALLPAPER;
+
+ assertFalse(mActivity.isLetterboxed(mActivity.findMainWindow()));
+ }
+
+ @Test
public void testAspectRatioMatchParentBoundsAndImeAttachable() {
setUpApp(new TestDisplayContent.Builder(mAtm, 1000, 2000)
.setSystemDecorations(true).build());
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 6c72249..bb9e24f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -198,11 +198,6 @@
}
@Override
- public SurfaceControl.Transaction setEarlyWakeup() {
- return this;
- }
-
- @Override
public SurfaceControl.Transaction setMetadata(SurfaceControl sc, int key, int data) {
return this;
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 5861610..05573f1 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -50,6 +50,7 @@
import android.service.voice.VoiceInteractionService;
import android.service.voice.VoiceInteractionServiceInfo;
import android.system.OsConstants;
+import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.view.IWindowManager;
@@ -186,17 +187,27 @@
mSessionComponentName, mUser, mContext, this,
mInfo.getServiceInfo().applicationInfo.uid, mHandler);
}
- List<IBinder> activityTokens = null;
+ List<Pair<IBinder, Integer>> allVisibleActivities =
+ LocalServices.getService(ActivityTaskManagerInternal.class)
+ .getTopVisibleActivities();
+
+ List<Pair<IBinder, Integer>> visibleActivities = null;
if (activityToken != null) {
- activityTokens = new ArrayList<>();
- activityTokens.add(activityToken);
+ visibleActivities = new ArrayList();
+ int activitiesCount = allVisibleActivities.size();
+ for (int i = 0; i < activitiesCount; i++) {
+ if (allVisibleActivities.get(i).first == activityToken) {
+ visibleActivities.add(
+ new Pair<>(activityToken, allVisibleActivities.get(i).second));
+ break;
+ }
+ }
} else {
- // Let's get top activities from all visible stacks
- activityTokens = LocalServices.getService(ActivityTaskManagerInternal.class)
+ visibleActivities = LocalServices.getService(ActivityTaskManagerInternal.class)
.getTopVisibleActivities();
}
return mActiveSession.showLocked(args, flags, mDisabledShowContext, showCallback,
- activityTokens);
+ visibleActivities);
}
public void getActiveServiceSupportedActions(List<String> commands,
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 84f4f6a..428d342 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -56,6 +56,7 @@
import android.service.voice.IVoiceInteractionSessionService;
import android.service.voice.VoiceInteractionService;
import android.service.voice.VoiceInteractionSession;
+import android.util.Pair;
import android.util.Slog;
import android.view.IWindowManager;
@@ -190,7 +191,8 @@
}
public boolean showLocked(Bundle args, int flags, int disabledContext,
- IVoiceInteractionSessionShowCallback showCallback, List<IBinder> topActivities) {
+ IVoiceInteractionSessionShowCallback showCallback,
+ List<Pair<IBinder, Integer>> topActivities) {
if (mBound) {
if (!mFullyBound) {
mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
@@ -205,17 +207,29 @@
mShowFlags = flags;
disabledContext |= getUserDisabledShowContextLocked();
- mAssistDataRequester.requestAssistData(topActivities,
- (flags & VoiceInteractionSession.SHOW_WITH_ASSIST) != 0,
- (flags & VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0,
- (disabledContext & VoiceInteractionSession.SHOW_WITH_ASSIST) == 0,
- (disabledContext & VoiceInteractionSession.SHOW_WITH_SCREENSHOT) == 0,
- mCallingUid, mSessionComponentName.getPackageName());
- boolean needDisclosure = mAssistDataRequester.getPendingDataCount() > 0
- || mAssistDataRequester.getPendingScreenshotCount() > 0;
- if (needDisclosure && AssistUtils.shouldDisclose(mContext, mSessionComponentName)) {
- mHandler.post(mShowAssistDisclosureRunnable);
+ boolean fetchData = (flags & VoiceInteractionSession.SHOW_WITH_ASSIST) != 0;
+ boolean fetchScreenshot = (flags & VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0;
+ boolean assistDataRequestNeeded = fetchData || fetchScreenshot;
+
+ if (assistDataRequestNeeded) {
+ int topActivitiesCount = topActivities.size();
+ final ArrayList<IBinder> topActivitiesToken = new ArrayList<>(topActivitiesCount);
+ for (int i = 0; i < topActivitiesCount; i++) {
+ topActivitiesToken.add(topActivities.get(i).first);
+ }
+ mAssistDataRequester.requestAssistData(topActivitiesToken,
+ fetchData,
+ fetchScreenshot,
+ (disabledContext & VoiceInteractionSession.SHOW_WITH_ASSIST) == 0,
+ (disabledContext & VoiceInteractionSession.SHOW_WITH_SCREENSHOT) == 0,
+ mCallingUid, mSessionComponentName.getPackageName());
+
+ boolean needDisclosure = mAssistDataRequester.getPendingDataCount() > 0
+ || mAssistDataRequester.getPendingScreenshotCount() > 0;
+ if (needDisclosure && AssistUtils.shouldDisclose(mContext, mSessionComponentName)) {
+ mHandler.post(mShowAssistDisclosureRunnable);
+ }
}
if (mSession != null) {
try {
@@ -224,7 +238,11 @@
mShowFlags = 0;
} catch (RemoteException e) {
}
- mAssistDataRequester.processPendingAssistData();
+ if (assistDataRequestNeeded) {
+ mAssistDataRequester.processPendingAssistData();
+ } else {
+ doHandleAssistWithoutData(topActivities);
+ }
} else if (showCallback != null) {
mPendingShowCallbacks.add(showCallback);
}
@@ -240,6 +258,28 @@
return false;
}
+ private void doHandleAssistWithoutData(List<Pair<IBinder, Integer>> topActivities) {
+ final int activityCount = topActivities.size();
+ for (int i = 0; i < activityCount; i++) {
+ final Pair<IBinder, Integer> topActivity = topActivities.get(i);
+ final IBinder activityId = topActivity.first;
+ final int taskId = topActivity.second;
+ final int activityIndex = i;
+ try {
+ mSession.handleAssist(
+ taskId,
+ activityId,
+ /* assistData = */ null,
+ /* assistStructure = */ null,
+ /* assistContent = */ null,
+ activityIndex,
+ activityCount);
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ }
+ }
+
@Override
public boolean canHandleReceivedAssistDataLocked() {
return mSession != null;
diff --git a/telecomm/java/android/telecom/CallDiagnosticService.java b/telecomm/java/android/telecom/CallDiagnosticService.java
index f5357b1..011dc17 100644
--- a/telecomm/java/android/telecom/CallDiagnosticService.java
+++ b/telecomm/java/android/telecom/CallDiagnosticService.java
@@ -27,6 +27,8 @@
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.RemoteException;
+
+import android.telephony.CallQuality;
import android.util.ArrayMap;
import com.android.internal.telecom.ICallDiagnosticService;
@@ -111,6 +113,12 @@
@NonNull DisconnectCause disconnectCause) throws RemoteException {
handleCallDisconnected(callId, disconnectCause);
}
+
+ @Override
+ public void callQualityChanged(String callId, CallQuality callQuality)
+ throws RemoteException {
+ handleCallQualityChanged(callId, callQuality);
+ }
}
/**
@@ -375,6 +383,21 @@
}
/**
+ * Handles a change reported by Telecom to the call quality for a call.
+ * @param callId the call ID the change applies to.
+ * @param callQuality The new call quality.
+ */
+ private void handleCallQualityChanged(@NonNull String callId,
+ @NonNull CallQuality callQuality) {
+ Log.i(this, "handleCallQualityChanged; call=%s, cq=%s", callId, callQuality);
+ CallDiagnostics callDiagnostics;
+ callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+ if (callDiagnostics != null) {
+ callDiagnostics.onCallQualityReceived(callQuality);
+ }
+ }
+
+ /**
* Handles a request from a {@link CallDiagnostics} to send a device to device message (received
* via {@link CallDiagnostics#sendDeviceToDeviceMessage(int, int)}.
* @param callDiagnostics
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 6dab6df..2dc18e8 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -44,6 +44,7 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.telephony.CallQuality;
import android.telephony.ims.ImsStreamMediaProfile;
import android.util.ArraySet;
import android.view.Surface;
@@ -978,6 +979,23 @@
public static final String EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE =
"android.telecom.extra.DEVICE_TO_DEVICE_MESSAGE_VALUE";
+ /**
+ * Connection event used to communicate a {@link android.telephony.CallQuality} report from
+ * telephony to Telecom for relaying to
+ * {@link DiagnosticCall#onCallQualityReceived(CallQuality)}.
+ * @hide
+ */
+ public static final String EVENT_CALL_QUALITY_REPORT =
+ "android.telecom.event.CALL_QUALITY_REPORT";
+
+ /**
+ * Extra sent with {@link #EVENT_CALL_QUALITY_REPORT} containing the
+ * {@link android.telephony.CallQuality} data.
+ * @hide
+ */
+ public static final String EXTRA_CALL_QUALITY_REPORT =
+ "android.telecom.extra.CALL_QUALITY_REPORT";
+
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
diff --git a/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl b/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl
index fc9879a..4bd369f 100644
--- a/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl
@@ -20,6 +20,7 @@
import android.telecom.CallAudioState;
import android.telecom.DisconnectCause;
import android.telecom.ParcelableCall;
+import android.telephony.CallQuality;
import com.android.internal.telecom.ICallDiagnosticServiceAdapter;
/**
@@ -34,6 +35,7 @@
void updateCallAudioState(in CallAudioState callAudioState);
void removeDiagnosticCall(in String callId);
void receiveDeviceToDeviceMessage(in String callId, int message, int value);
+ void callQualityChanged(in String callId, in CallQuality callQuality);
void receiveBluetoothCallQualityReport(in BluetoothCallQualityReport qualityReport);
void notifyCallDisconnected(in String callId, in DisconnectCause disconnectCause);
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 4926687..17af463 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -2207,7 +2208,9 @@
*
* @return the total number of SMS records which can be stored on the SIM card.
*/
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresPermission(anyOf = {android.Manifest.permission.READ_PHONE_STATE,
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
+ @IntRange(from = 0)
public int getSmsCapacityOnIcc() {
int ret = 0;
try {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 962200b..5a94a8a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -15100,6 +15100,11 @@
*/
public void registerTelephonyCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull TelephonyCallback callback) {
+
+ if (mContext == null) {
+ throw new IllegalStateException("telephony service is null.");
+ }
+
if (executor == null || callback == null) {
throw new IllegalArgumentException("TelephonyCallback and executor must be non-null");
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java
index f0e6299..c4b0072 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java
@@ -18,8 +18,6 @@
import android.app.Activity;
import android.os.Bundle;
-import android.widget.HorizontalScrollView;
-import android.widget.ScrollView;
public class EdgeEffectStretchActivity extends Activity {
@@ -27,10 +25,5 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stretch_layout);
- HorizontalScrollView hsv = findViewById(R.id.horizontal_scroll_view);
- hsv.setStretchDistance(50f);
-
- ScrollView sv = findViewById(R.id.scroll_view);
- sv.setStretchDistance(50f);
}
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java
index 65d7363..6b6287d 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java
@@ -75,11 +75,11 @@
// Although we could do this in a single call, the real one won't be - so mimic that
if (dir.x != 0f) {
node.stretch(0f, 0f, (float) getWidth(), (float) getHeight(),
- dir.x, 0f, maxStretchAmount);
+ dir.x, 0f, maxStretchAmount, maxStretchAmount);
}
if (dir.y != 0f) {
node.stretch(0f, 0f, (float) getWidth(), (float) getHeight(),
- 0f, dir.y, maxStretchAmount);
+ 0f, dir.y, maxStretchAmount, maxStretchAmount);
}
}
};
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java
index 9bd933a..912aee6 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java
@@ -415,6 +415,7 @@
bounds.height(),
mOverScrollX,
mOverScrollY,
+ mStretchDistance,
mStretchDistance
);
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java
index d604244..67b9be5 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java
@@ -99,7 +99,8 @@
super.onDraw(canvas);
RenderNode node = ((RecordingCanvas) canvas).mNode;
- node.stretch(0f, 0f, getWidth(), getHeight() / 2f, 0f, 1f, 400f);
+ node.stretch(0f, 0f, getWidth(), getHeight() / 2f, 0f,
+ 1f, 400f, 400f);
}
};
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index 0dfec75..a7ad695 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -69,6 +69,7 @@
import android.os.Build;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+import android.util.Range;
import androidx.test.runner.AndroidJUnit4;
@@ -240,72 +241,93 @@
@Test
public void testSetUids() {
final NetworkCapabilities netCap = new NetworkCapabilities();
- final Set<UidRange> uids = new ArraySet<>();
- uids.add(new UidRange(50, 100));
- uids.add(new UidRange(3000, 4000));
- netCap.setUids(uids);
- assertTrue(netCap.appliesToUid(50));
- assertTrue(netCap.appliesToUid(80));
- assertTrue(netCap.appliesToUid(100));
+ // Null uids match all UIDs
+ netCap.setUids(null);
+ assertTrue(netCap.appliesToUid(10));
+ assertTrue(netCap.appliesToUid(200));
assertTrue(netCap.appliesToUid(3000));
- assertTrue(netCap.appliesToUid(3001));
- assertFalse(netCap.appliesToUid(10));
- assertFalse(netCap.appliesToUid(25));
- assertFalse(netCap.appliesToUid(49));
- assertFalse(netCap.appliesToUid(101));
- assertFalse(netCap.appliesToUid(2000));
- assertFalse(netCap.appliesToUid(100000));
-
+ assertTrue(netCap.appliesToUid(10010));
assertTrue(netCap.appliesToUidRange(new UidRange(50, 100)));
assertTrue(netCap.appliesToUidRange(new UidRange(70, 72)));
assertTrue(netCap.appliesToUidRange(new UidRange(3500, 3912)));
- assertFalse(netCap.appliesToUidRange(new UidRange(1, 100)));
- assertFalse(netCap.appliesToUidRange(new UidRange(49, 100)));
- assertFalse(netCap.appliesToUidRange(new UidRange(1, 10)));
- assertFalse(netCap.appliesToUidRange(new UidRange(60, 101)));
- assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400)));
-
- NetworkCapabilities netCap2 = new NetworkCapabilities();
- // A new netcap object has null UIDs, so anything will satisfy it.
- assertTrue(netCap2.satisfiedByUids(netCap));
- // Still not equal though.
- assertFalse(netCap2.equalsUids(netCap));
- netCap2.setUids(uids);
- assertTrue(netCap2.satisfiedByUids(netCap));
- assertTrue(netCap.equalsUids(netCap2));
- assertTrue(netCap2.equalsUids(netCap));
-
- uids.add(new UidRange(600, 700));
- netCap2.setUids(uids);
- assertFalse(netCap2.satisfiedByUids(netCap));
- assertFalse(netCap.appliesToUid(650));
- assertTrue(netCap2.appliesToUid(650));
- netCap.combineCapabilities(netCap2);
- assertTrue(netCap2.satisfiedByUids(netCap));
- assertTrue(netCap.appliesToUid(650));
- assertFalse(netCap.appliesToUid(500));
-
- assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
- netCap.combineCapabilities(new NetworkCapabilities());
- assertTrue(netCap.appliesToUid(500));
assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000)));
- assertFalse(netCap2.appliesToUid(500));
- assertFalse(netCap2.appliesToUidRange(new UidRange(1, 100000)));
- assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
+
+ if (isAtLeastS()) {
+ final Set<Range<Integer>> uids = new ArraySet<>();
+ uids.add(uidRange(50, 100));
+ uids.add(uidRange(3000, 4000));
+ netCap.setUids(uids);
+ assertTrue(netCap.appliesToUid(50));
+ assertTrue(netCap.appliesToUid(80));
+ assertTrue(netCap.appliesToUid(100));
+ assertTrue(netCap.appliesToUid(3000));
+ assertTrue(netCap.appliesToUid(3001));
+ assertFalse(netCap.appliesToUid(10));
+ assertFalse(netCap.appliesToUid(25));
+ assertFalse(netCap.appliesToUid(49));
+ assertFalse(netCap.appliesToUid(101));
+ assertFalse(netCap.appliesToUid(2000));
+ assertFalse(netCap.appliesToUid(100000));
+
+ assertTrue(netCap.appliesToUidRange(new UidRange(50, 100)));
+ assertTrue(netCap.appliesToUidRange(new UidRange(70, 72)));
+ assertTrue(netCap.appliesToUidRange(new UidRange(3500, 3912)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(1, 100)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(49, 100)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(1, 10)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(60, 101)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400)));
+
+ NetworkCapabilities netCap2 = new NetworkCapabilities();
+ // A new netcap object has null UIDs, so anything will satisfy it.
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ // Still not equal though.
+ assertFalse(netCap2.equalsUids(netCap));
+ netCap2.setUids(uids);
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ assertTrue(netCap.equalsUids(netCap2));
+ assertTrue(netCap2.equalsUids(netCap));
+
+ uids.add(uidRange(600, 700));
+ netCap2.setUids(uids);
+ assertFalse(netCap2.satisfiedByUids(netCap));
+ assertFalse(netCap.appliesToUid(650));
+ assertTrue(netCap2.appliesToUid(650));
+ netCap.combineCapabilities(netCap2);
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ assertTrue(netCap.appliesToUid(650));
+ assertFalse(netCap.appliesToUid(500));
+
+ assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
+ netCap.combineCapabilities(new NetworkCapabilities());
+ assertTrue(netCap.appliesToUid(500));
+ assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000)));
+ assertFalse(netCap2.appliesToUid(500));
+ assertFalse(netCap2.appliesToUidRange(new UidRange(1, 100000)));
+ assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
+
+ // Null uids satisfies everything.
+ netCap.setUids(null);
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ assertTrue(netCap.satisfiedByUids(netCap2));
+ netCap2.setUids(null);
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ assertTrue(netCap.satisfiedByUids(netCap2));
+ }
}
@Test
public void testParcelNetworkCapabilities() {
- final Set<UidRange> uids = new ArraySet<>();
- uids.add(new UidRange(50, 100));
- uids.add(new UidRange(3000, 4000));
+ final Set<Range<Integer>> uids = new ArraySet<>();
+ uids.add(uidRange(50, 100));
+ uids.add(uidRange(3000, 4000));
final NetworkCapabilities netCap = new NetworkCapabilities()
.addCapability(NET_CAPABILITY_INTERNET)
- .setUids(uids)
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED);
if (isAtLeastS()) {
netCap.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2));
+ netCap.setUids(uids);
} else if (isAtLeastR()) {
netCap.setOwnerUid(123);
netCap.setAdministratorUids(new int[] {5, 11});
@@ -540,12 +562,16 @@
assertFalse(nc1.satisfiedByNetworkCapabilities(nc2));
}
- private ArraySet<UidRange> uidRange(int from, int to) {
- final ArraySet<UidRange> range = new ArraySet<>(1);
- range.add(new UidRange(from, to));
+ private ArraySet<Range<Integer>> uidRanges(int from, int to) {
+ final ArraySet<Range<Integer>> range = new ArraySet<>(1);
+ range.add(uidRange(from, to));
return range;
}
+ private Range<Integer> uidRange(int from, int to) {
+ return new Range<Integer>(from, to);
+ }
+
@Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testSetAdministratorUids() {
NetworkCapabilities nc =
@@ -601,23 +627,23 @@
} catch (IllegalStateException expected) {}
nc1.setSSID(TEST_SSID);
- nc1.setUids(uidRange(10, 13));
- assertNotEquals(nc1, nc2);
- nc2.combineCapabilities(nc1); // Everything + 10~13 is still everything.
- assertNotEquals(nc1, nc2);
- nc1.combineCapabilities(nc2); // 10~13 + everything is everything.
- assertEquals(nc1, nc2);
- nc1.setUids(uidRange(10, 13));
- nc2.setUids(uidRange(20, 23));
- assertNotEquals(nc1, nc2);
- nc1.combineCapabilities(nc2);
- assertTrue(nc1.appliesToUid(12));
- assertFalse(nc2.appliesToUid(12));
- assertTrue(nc1.appliesToUid(22));
- assertTrue(nc2.appliesToUid(22));
-
- // Verify the subscription id list can be combined only when they are equal.
if (isAtLeastS()) {
+ nc1.setUids(uidRanges(10, 13));
+ assertNotEquals(nc1, nc2);
+ nc2.combineCapabilities(nc1); // Everything + 10~13 is still everything.
+ assertNotEquals(nc1, nc2);
+ nc1.combineCapabilities(nc2); // 10~13 + everything is everything.
+ assertEquals(nc1, nc2);
+ nc1.setUids(uidRanges(10, 13));
+ nc2.setUids(uidRanges(20, 23));
+ assertNotEquals(nc1, nc2);
+ nc1.combineCapabilities(nc2);
+ assertTrue(nc1.appliesToUid(12));
+ assertFalse(nc2.appliesToUid(12));
+ assertTrue(nc1.appliesToUid(22));
+ assertTrue(nc2.appliesToUid(22));
+
+ // Verify the subscription id list can be combined only when they are equal.
nc1.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2));
nc2.setSubIds(Set.of(TEST_SUBID2));
assertThrows(IllegalStateException.class, () -> nc2.combineCapabilities(nc1));
@@ -773,8 +799,11 @@
if (isAtLeastR()) {
assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSsid()));
}
-
- nc1.setUids(uidRange(10, 13));
+ if (isAtLeastS()) {
+ nc1.setUids(uidRanges(10, 13));
+ } else {
+ nc1.setUids(null);
+ }
nc2.set(nc1); // Overwrites, as opposed to combineCapabilities
assertEquals(nc1, nc2);
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 2a2dc56..db49e0b 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -44,12 +44,10 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.ConnectivityService
-import com.android.server.LocalServices
import com.android.server.NetworkAgentWrapper
import com.android.server.TestNetIdManager
import com.android.server.connectivity.MockableSystemProperties
import com.android.server.connectivity.ProxyTracker
-import com.android.server.net.NetworkPolicyManagerInternal
import com.android.testutils.TestableNetworkCallback
import org.junit.After
import org.junit.Before
@@ -162,10 +160,6 @@
networkStackClient.init()
networkStackClient.start()
- LocalServices.removeServiceForTest(NetworkPolicyManagerInternal::class.java)
- LocalServices.addService(NetworkPolicyManagerInternal::class.java,
- mock(NetworkPolicyManagerInternal::class.java))
-
service = TestConnectivityService(makeDependencies())
cm = ConnectivityManager(context, service)
context.addMockSystemService(Context.CONNECTIVITY_SERVICE, cm)
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 01d8186..e2d43cb 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -44,11 +44,11 @@
import android.net.NetworkSpecifier;
import android.net.QosFilter;
import android.net.SocketKeepalive;
-import android.net.UidRange;
import android.os.ConditionVariable;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
+import android.util.Range;
import com.android.net.module.util.ArrayTrackRecord;
import com.android.server.connectivity.ConnectivityConstants;
@@ -222,7 +222,7 @@
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
- public void setUids(Set<UidRange> uids) {
+ public void setUids(Set<Range<Integer>> uids) {
mNetworkCapabilities.setUids(uids);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index d70572d..0b31999 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -268,12 +268,14 @@
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
+import android.util.Range;
import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.connectivity.resources.R;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.internal.util.ArrayUtils;
@@ -292,7 +294,6 @@
import com.android.server.connectivity.Vpn;
import com.android.server.connectivity.VpnProfileStore;
import com.android.server.net.NetworkPinner;
-import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.testutils.ExceptionUtils;
import com.android.testutils.HandlerUtils;
import com.android.testutils.RecorderCallback.CallbackEntry;
@@ -1158,7 +1159,7 @@
}
public void setUids(Set<UidRange> uids) {
- mNetworkCapabilities.setUids(uids);
+ mNetworkCapabilities.setUids(UidRange.toIntRanges(uids));
if (mAgentRegistered) {
mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true);
}
@@ -1448,6 +1449,8 @@
}
private static final int PRIMARY_USER = 0;
+ private static final UidRange PRIMARY_UIDRANGE =
+ UidRange.createForUser(UserHandle.of(PRIMARY_USER));
private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100);
private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101);
private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043);
@@ -1501,9 +1504,6 @@
mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
new FakeSettingsProvider());
mServiceContext.setUseRegisteredHandlers(true);
- LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
- LocalServices.addService(
- NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
mAlarmManagerThread = new HandlerThread("TestAlarmManager");
mAlarmManagerThread.start();
@@ -1575,6 +1575,14 @@
doReturn(com.android.connectivity.resources.R.array.config_networkSupportedKeepaliveCount)
.when(mResources).getIdentifier(eq("config_networkSupportedKeepaliveCount"),
eq("array"), any());
+ doReturn(com.android.connectivity.resources.R.array.network_switch_type_name)
+ .when(mResources).getIdentifier(eq("network_switch_type_name"),
+ eq("array"), any());
+
+ // We don't test the actual notification value strings, so just return an empty array.
+ // It doesn't matter what the values are as long as it's not null.
+ doReturn(new String[0]).when(mResources).getStringArray(R.array.network_switch_type_name);
+
final ConnectivityResources connRes = mock(ConnectivityResources.class);
doReturn(mResources).when(connRes).get();
doReturn(connRes).when(deps).getResources(any());
@@ -4337,6 +4345,7 @@
assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
}
+ @Ignore("Refactoring in progress b/178071397")
@Test
public void testAvoidBadWifi() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
@@ -6940,7 +6949,7 @@
final int uid = Process.myUid();
NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
assertNotNull("nc=" + nc, nc.getUids());
- assertEquals(nc.getUids(), uidRangesForUids(uid));
+ assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid)));
assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
// Set an underlying network and expect to see the VPN transports change.
@@ -6965,10 +6974,13 @@
// Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
// restricted user.
+ final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
+ final Range<Integer> restrictUidRange = new Range<Integer>(rRange.start, rRange.stop);
+ final Range<Integer> singleUidRange = new Range<Integer>(uid, uid);
callback.expectCapabilitiesThat(mMockVpn, (caps)
-> caps.getUids().size() == 2
- && caps.getUids().contains(new UidRange(uid, uid))
- && caps.getUids().contains(createUidRange(RESTRICTED_USER))
+ && caps.getUids().contains(singleUidRange)
+ && caps.getUids().contains(restrictUidRange)
&& caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_WIFI));
@@ -6977,8 +6989,8 @@
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
callback.expectCapabilitiesThat(mMockVpn, (caps)
-> caps.getUids().size() == 2
- && caps.getUids().contains(new UidRange(uid, uid))
- && caps.getUids().contains(createUidRange(RESTRICTED_USER))
+ && caps.getUids().contains(singleUidRange)
+ && caps.getUids().contains(restrictUidRange)
&& caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_WIFI));
@@ -6992,7 +7004,7 @@
// change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
callback.expectCapabilitiesThat(mMockVpn, (caps)
-> caps.getUids().size() == 1
- && caps.getUids().contains(new UidRange(uid, uid))
+ && caps.getUids().contains(singleUidRange)
&& caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_WIFI));
}
@@ -7650,7 +7662,7 @@
assertNotNull(underlying);
mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
// The legacy lockdown VPN only supports userId 0.
- final Set<UidRange> ranges = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> ranges = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.registerAgent(ranges);
mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
mMockVpn.connect(true);
@@ -8612,7 +8624,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.establish(lp, VPN_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
@@ -8640,7 +8652,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
@@ -8656,7 +8668,7 @@
lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
@@ -8671,7 +8683,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.establish(lp, VPN_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
@@ -8723,7 +8735,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
- final UidRange vpnRange = createUidRange(PRIMARY_USER);
+ final UidRange vpnRange = PRIMARY_UIDRANGE;
final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
mMockVpn.establish(lp, VPN_UID, vpnRanges);
assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -9004,7 +9016,7 @@
private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
throws Exception {
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.setVpnType(vpnType);
mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
@@ -9564,7 +9576,7 @@
lp.setInterfaceName("tun0");
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
- final UidRange vpnRange = createUidRange(PRIMARY_USER);
+ final UidRange vpnRange = PRIMARY_UIDRANGE;
Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
mMockVpn.establish(lp, VPN_UID, vpnRanges);
assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -9762,7 +9774,7 @@
.thenReturn(hasFeature);
}
- private UidRange getNriFirstUidRange(
+ private Range<Integer> getNriFirstUidRange(
@NonNull final ConnectivityService.NetworkRequestInfo nri) {
return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next();
}
@@ -9945,11 +9957,11 @@
pref));
// Sort by uid to access nris by index
- nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).start));
- assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).start);
- assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).stop);
- assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).start);
- assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).stop);
+ nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower()));
+ assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower());
+ assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper());
+ assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower());
+ assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper());
}
@Test
@@ -9979,17 +9991,17 @@
// UIDs for all users and all managed packages should be present.
// Two users each with two packages.
final int expectedUidSize = 2;
- final List<UidRange> uids =
+ final List<Range<Integer>> uids =
new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids());
assertEquals(expectedUidSize, uids.size());
// Sort by uid to access nris by index
- uids.sort(Comparator.comparingInt(uid -> uid.start));
+ uids.sort(Comparator.comparingInt(uid -> uid.getLower()));
final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
- assertEquals(TEST_PACKAGE_UID, uids.get(0).start);
- assertEquals(TEST_PACKAGE_UID, uids.get(0).stop);
- assertEquals(secondUserTestPackageUid, uids.get(1).start);
- assertEquals(secondUserTestPackageUid, uids.get(1).stop);
+ assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getLower());
+ assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getUpper());
+ assertEquals(secondUserTestPackageUid, (int) uids.get(1).getLower());
+ assertEquals(secondUserTestPackageUid, (int) uids.get(1).getUpper());
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/FullScoreTest.kt b/tests/net/java/com/android/server/connectivity/FullScoreTest.kt
new file mode 100644
index 0000000..eb3b4df
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/FullScoreTest.kt
@@ -0,0 +1,134 @@
+/*
+ * 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 com.android.server.connectivity
+
+import android.net.NetworkAgentConfig
+import android.net.NetworkCapabilities
+import android.text.TextUtils
+import android.util.ArraySet
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.server.connectivity.FullScore.MAX_CS_MANAGED_POLICY
+import com.android.server.connectivity.FullScore.POLICY_ACCEPT_UNVALIDATED
+import com.android.server.connectivity.FullScore.POLICY_EVER_USER_SELECTED
+import com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED
+import com.android.server.connectivity.FullScore.POLICY_IS_VPN
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.collections.minOfOrNull
+import kotlin.collections.maxOfOrNull
+import kotlin.reflect.full.staticProperties
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class FullScoreTest {
+ // Convenience methods
+ fun FullScore.withPolicies(
+ validated: Boolean = false,
+ vpn: Boolean = false,
+ onceChosen: Boolean = false,
+ acceptUnvalidated: Boolean = false
+ ): FullScore {
+ val nac = NetworkAgentConfig.Builder().apply {
+ setUnvalidatedConnectivityAcceptable(acceptUnvalidated)
+ setExplicitlySelected(onceChosen)
+ }.build()
+ val nc = NetworkCapabilities.Builder().apply {
+ if (vpn) addTransportType(NetworkCapabilities.TRANSPORT_VPN)
+ if (validated) addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+ }.build()
+ return mixInScore(nc, nac)
+ }
+
+ @Test
+ fun testGetLegacyInt() {
+ val ns = FullScore(50, 0L /* policy */)
+ assertEquals(10, ns.legacyInt) // -40 penalty for not being validated
+ assertEquals(50, ns.legacyIntAsValidated)
+
+ val vpnNs = FullScore(101, 0L /* policy */).withPolicies(vpn = true)
+ assertEquals(101, vpnNs.legacyInt) // VPNs are not subject to unvalidation penalty
+ assertEquals(101, vpnNs.legacyIntAsValidated)
+ assertEquals(101, vpnNs.withPolicies(validated = true).legacyInt)
+ assertEquals(101, vpnNs.withPolicies(validated = true).legacyIntAsValidated)
+
+ val validatedNs = ns.withPolicies(validated = true)
+ assertEquals(50, validatedNs.legacyInt) // No penalty, this is validated
+ assertEquals(50, validatedNs.legacyIntAsValidated)
+
+ val chosenNs = ns.withPolicies(onceChosen = true)
+ assertEquals(10, chosenNs.legacyInt)
+ assertEquals(100, chosenNs.legacyIntAsValidated)
+ assertEquals(10, chosenNs.withPolicies(acceptUnvalidated = true).legacyInt)
+ assertEquals(50, chosenNs.withPolicies(acceptUnvalidated = true).legacyIntAsValidated)
+ }
+
+ @Test
+ fun testToString() {
+ val string = FullScore(10, 0L /* policy */)
+ .withPolicies(vpn = true, acceptUnvalidated = true).toString()
+ assertTrue(string.contains("Score(10"), string)
+ assertTrue(string.contains("ACCEPT_UNVALIDATED"), string)
+ assertTrue(string.contains("IS_VPN"), string)
+ assertFalse(string.contains("IS_VALIDATED"), string)
+ val foundNames = ArraySet<String>()
+ getAllPolicies().forEach {
+ val name = FullScore.policyNameOf(it.get() as Int)
+ assertFalse(TextUtils.isEmpty(name))
+ assertFalse(foundNames.contains(name))
+ foundNames.add(name)
+ }
+ assertFailsWith<IllegalArgumentException> {
+ FullScore.policyNameOf(MAX_CS_MANAGED_POLICY + 1)
+ }
+ }
+
+ fun getAllPolicies() = Regex("POLICY_.*").let { nameRegex ->
+ FullScore::class.staticProperties.filter { it.name.matches(nameRegex) }
+ }
+
+ @Test
+ fun testHasPolicy() {
+ val ns = FullScore(50, 0L /* policy */)
+ assertFalse(ns.hasPolicy(POLICY_IS_VALIDATED))
+ assertFalse(ns.hasPolicy(POLICY_IS_VPN))
+ assertFalse(ns.hasPolicy(POLICY_EVER_USER_SELECTED))
+ assertFalse(ns.hasPolicy(POLICY_ACCEPT_UNVALIDATED))
+ assertTrue(ns.withPolicies(validated = true).hasPolicy(POLICY_IS_VALIDATED))
+ assertTrue(ns.withPolicies(vpn = true).hasPolicy(POLICY_IS_VPN))
+ assertTrue(ns.withPolicies(onceChosen = true).hasPolicy(POLICY_EVER_USER_SELECTED))
+ assertTrue(ns.withPolicies(acceptUnvalidated = true).hasPolicy(POLICY_ACCEPT_UNVALIDATED))
+ }
+
+ @Test
+ fun testMinMaxPolicyConstants() {
+ val policies = getAllPolicies()
+
+ policies.forEach { policy ->
+ assertTrue(policy.get() as Int >= FullScore.MIN_CS_MANAGED_POLICY)
+ assertTrue(policy.get() as Int <= FullScore.MAX_CS_MANAGED_POLICY)
+ }
+ assertEquals(FullScore.MIN_CS_MANAGED_POLICY,
+ policies.minOfOrNull { it.get() as Int })
+ assertEquals(FullScore.MAX_CS_MANAGED_POLICY,
+ policies.maxOfOrNull { it.get() as Int })
+ }
+}
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index ea2b362..9ab60a4 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -357,7 +357,7 @@
caps.addTransportType(transport);
NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info,
new LinkProperties(), caps, new NetworkScore.Builder().setLegacyInt(50).build(),
- mCtx, null, new NetworkAgentConfig() /* config */, mConnService, mNetd,
+ mCtx, null, new NetworkAgentConfig.Builder().build(), mConnService, mNetd,
mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(),
mQosCallbackTracker, new ConnectivityService.Dependencies());
nai.everValidated = true;
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index d01dc03..dde77b0 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -36,6 +36,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.net.ConnectivityResources;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.os.UserHandle;
@@ -45,9 +46,10 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.R;
+import com.android.connectivity.resources.R;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
+import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -134,12 +136,26 @@
when(mCtx.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
.thenReturn(mNotificationManager);
when(mNetworkInfo.getExtraInfo()).thenReturn(TEST_EXTRA_INFO);
+ ConnectivityResources.setResourcesContextForTest(mCtx);
when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B);
when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
+ // Come up with some credible-looking transport names. The actual values do not matter.
+ String[] transportNames = new String[NetworkCapabilities.MAX_TRANSPORT + 1];
+ for (int transport = 0; transport <= NetworkCapabilities.MAX_TRANSPORT; transport++) {
+ transportNames[transport] = NetworkCapabilities.transportNameOf(transport);
+ }
+ when(mResources.getStringArray(R.array.network_switch_type_name))
+ .thenReturn(transportNames);
+
mManager = new NetworkNotificationManager(mCtx, mTelephonyManager);
}
+ @After
+ public void tearDown() {
+ ConnectivityResources.setResourcesContextForTest(null);
+ }
+
private void verifyTitleByNetwork(final int id, final NetworkAgentInfo nai, final int title) {
final String tag = NetworkNotificationManager.tagFor(id);
mManager.showNotification(id, PRIVATE_DNS_BROKEN, nai, null, null, true);
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 11fcea6..6ad4900 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -23,6 +23,7 @@
import static android.net.ConnectivityManager.NetworkCallback;
import static android.net.INetd.IF_STATE_DOWN;
import static android.net.INetd.IF_STATE_UP;
+import static android.os.UserHandle.PER_USER_RANGE;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -74,7 +75,6 @@
import android.net.NetworkCapabilities;
import android.net.NetworkInfo.DetailedState;
import android.net.RouteInfo;
-import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.VpnManager;
import android.net.VpnService;
@@ -181,8 +181,7 @@
mPackages.put(PKGS[i], PKG_UIDS[i]);
}
}
- private static final UidRange PRI_USER_RANGE =
- UidRange.createForUser(UserHandle.of(primaryUser.id));
+ private static final Range<Integer> PRI_USER_RANGE = uidRangeForUser(primaryUser.id);
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
@Mock private UserManager mUserManager;
@@ -260,6 +259,21 @@
.thenReturn(tunnelResp);
}
+ private Set<Range<Integer>> rangeSet(Range<Integer> ... ranges) {
+ final Set<Range<Integer>> range = new ArraySet<>();
+ for (Range<Integer> r : ranges) range.add(r);
+
+ return range;
+ }
+
+ private static Range<Integer> uidRangeForUser(int userId) {
+ return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1);
+ }
+
+ private Range<Integer> uidRange(int start, int stop) {
+ return new Range<Integer>(start, stop);
+ }
+
@Test
public void testRestrictedProfilesAreAddedToVpn() {
setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB);
@@ -268,12 +282,10 @@
// Assume the user can have restricted profiles.
doReturn(true).when(mUserManager).canHaveRestrictedProfile();
- final Set<UidRange> ranges =
+ final Set<Range<Integer>> ranges =
vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- PRI_USER_RANGE, UidRange.createForUser(UserHandle.of(restrictedProfileA.id))
- })), ranges);
+ assertEquals(rangeSet(PRI_USER_RANGE, uidRangeForUser(restrictedProfileA.id)), ranges);
}
@Test
@@ -281,10 +293,10 @@
setMockedUsers(primaryUser, managedProfileA);
final Vpn vpn = createVpn(primaryUser.id);
- final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
+ final Set<Range<Integer>> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
null, null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
+ assertEquals(rangeSet(PRI_USER_RANGE), ranges);
}
@Test
@@ -292,35 +304,38 @@
setMockedUsers(primaryUser, restrictedProfileA, managedProfileA);
final Vpn vpn = createVpn(primaryUser.id);
- final Set<UidRange> ranges = new ArraySet<>();
+ final Set<Range<Integer>> ranges = new ArraySet<>();
vpn.addUserToRanges(ranges, primaryUser.id, null, null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
+ assertEquals(rangeSet(PRI_USER_RANGE), ranges);
}
@Test
public void testUidAllowAndDenylist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
- final UidRange user = PRI_USER_RANGE;
+ final Range<Integer> user = PRI_USER_RANGE;
+ final int userStart = user.getLower();
+ final int userStop = user.getUpper();
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
// Allowed list
- final Set<UidRange> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
- Arrays.asList(packages), null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- new UidRange(user.start + PKG_UIDS[0], user.start + PKG_UIDS[0]),
- new UidRange(user.start + PKG_UIDS[1], user.start + PKG_UIDS[2])
- })), allow);
+ final Set<Range<Integer>> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
+ Arrays.asList(packages), null /* disallowedApplications */);
+ assertEquals(rangeSet(
+ uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]),
+ uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2])),
+ allow);
// Denied list
- final Set<UidRange> disallow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
- null, Arrays.asList(packages));
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- new UidRange(user.start, user.start + PKG_UIDS[0] - 1),
- new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
- /* Empty range between UIDS[1] and UIDS[2], should be excluded, */
- new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
- })), disallow);
+ final Set<Range<Integer>> disallow =
+ vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
+ null /* allowedApplications */, Arrays.asList(packages));
+ assertEquals(rangeSet(
+ uidRange(userStart, userStart + PKG_UIDS[0] - 1),
+ uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
+ /* Empty range between UIDS[1] and UIDS[2], should be excluded, */
+ uidRange(userStart + PKG_UIDS[2] + 1, userStop)),
+ disallow);
}
@Test
@@ -350,84 +365,86 @@
@Test
public void testLockdownChangingPackage() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
- final UidRange user = PRI_USER_RANGE;
-
+ final Range<Integer> user = PRI_USER_RANGE;
+ final int userStart = user.getLower();
+ final int userStop = user.getUpper();
// Set always-on without lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null));
// Set always-on with lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
}));
// Switch to another app.
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop)
}));
}
@Test
public void testLockdownAllowlist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
- final UidRange user = PRI_USER_RANGE;
-
+ final Range<Integer> user = PRI_USER_RANGE;
+ final int userStart = user.getLower();
+ final int userStop = user.getUpper();
// Set always-on with lockdown and allow app PKGS[2] from lockdown.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[2])));
- verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
+ verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop)
}));
// Change allowed app list to PKGS[3].
assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[3])));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop)
}));
// Change the VPN app.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList(PKGS[3])));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1)
}));
// Remove the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop),
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop),
}));
// Add the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList(PKGS[1])));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
}));
// Try allowing a package with a comma, should be rejected.
@@ -439,12 +456,12 @@
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app")));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop)
}));
}
@@ -452,7 +469,7 @@
public void testLockdownRuleRepeatability() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] {
- new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)};
+ new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())};
// Given legacy lockdown is already enabled,
vpn.setLockdown(true);
verify(mConnectivityManager, times(1)).setRequireVpnForUids(true,
@@ -484,7 +501,7 @@
public void testLockdownRuleReversibility() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
final UidRangeParcel[] entireUser = {
- new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)
+ new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())
};
final UidRangeParcel[] exceptPkg0 = {
new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
index 1ef1a61..631c862 100644
--- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
@@ -328,7 +328,7 @@
public void testRecordTrackerCallbackNotifiedForNetworkSuspended() {
RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
- cb.onNetworkSuspended(mNetwork);
+ cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES);
UnderlyingNetworkRecord expectedRecord =
new UnderlyingNetworkRecord(
@@ -336,7 +336,11 @@
SUSPENDED_NETWORK_CAPABILITIES,
INITIAL_LINK_PROPERTIES,
false /* isBlocked */);
- verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ // onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't
+ // change.
+ cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES);
+ verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
}
@Test
@@ -344,7 +348,7 @@
RouteSelectionCallback cb =
verifyRegistrationOnAvailableAndGetCallback(SUSPENDED_NETWORK_CAPABILITIES);
- cb.onNetworkResumed(mNetwork);
+ cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
UnderlyingNetworkRecord expectedRecord =
new UnderlyingNetworkRecord(
@@ -352,7 +356,11 @@
INITIAL_NETWORK_CAPABILITIES,
INITIAL_LINK_PROPERTIES,
false /* isBlocked */);
- verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+ // onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't
+ // change.
+ cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
+ verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
}
@Test