Merge "Remove Logger classes from flicker" into main
diff --git a/cmds/hid/src/com/android/commands/hid/Event.java b/cmds/hid/src/com/android/commands/hid/Event.java
index 09ed528..3b02279 100644
--- a/cmds/hid/src/com/android/commands/hid/Event.java
+++ b/cmds/hid/src/com/android/commands/hid/Event.java
@@ -121,9 +121,9 @@
public String toString() {
return "Event{id=" + mId
- + ", command=" + String.valueOf(mCommand)
- + ", name=" + String.valueOf(mName)
- + ", uniq=" + String.valueOf(mUniq)
+ + ", command=" + mCommand
+ + ", name=" + mName
+ + ", uniq=" + mUniq
+ ", descriptor=" + Arrays.toString(mDescriptor)
+ ", vid=" + mVid
+ ", pid=" + mPid
diff --git a/core/api/current.txt b/core/api/current.txt
index 592cbfd..5772fb4 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -5395,7 +5395,7 @@
public final class AutomaticZenRule implements android.os.Parcelable {
ctor @Deprecated public AutomaticZenRule(String, android.content.ComponentName, android.net.Uri, int, boolean);
- ctor @Deprecated public AutomaticZenRule(@NonNull String, @Nullable android.content.ComponentName, @Nullable android.content.ComponentName, @NonNull android.net.Uri, @Nullable android.service.notification.ZenPolicy, int, boolean);
+ ctor public AutomaticZenRule(@NonNull String, @Nullable android.content.ComponentName, @Nullable android.content.ComponentName, @NonNull android.net.Uri, @Nullable android.service.notification.ZenPolicy, int, boolean);
ctor public AutomaticZenRule(android.os.Parcel);
method public int describeContents();
method public android.net.Uri getConditionId();
@@ -10731,7 +10731,6 @@
field public static final String DROPBOX_SERVICE = "dropbox";
field public static final String EUICC_SERVICE = "euicc";
field public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
- field public static final String FINGERPRINT_SERVICE = "fingerprint";
field public static final String GAME_SERVICE = "game";
field public static final String GRAMMATICAL_INFLECTION_SERVICE = "grammatical_inflection";
field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
@@ -18051,24 +18050,6 @@
method public android.graphics.pdf.PdfDocument.PageInfo.Builder setContentRect(android.graphics.Rect);
}
- public final class PdfRenderer implements java.lang.AutoCloseable {
- ctor public PdfRenderer(@NonNull android.os.ParcelFileDescriptor) throws java.io.IOException;
- method public void close();
- method public int getPageCount();
- method public android.graphics.pdf.PdfRenderer.Page openPage(int);
- method public boolean shouldScaleForPrinting();
- }
-
- public final class PdfRenderer.Page implements java.lang.AutoCloseable {
- method public void close();
- method public int getHeight();
- method public int getIndex();
- method public int getWidth();
- method public void render(@NonNull android.graphics.Bitmap, @Nullable android.graphics.Rect, @Nullable android.graphics.Matrix, int);
- field public static final int RENDER_MODE_FOR_DISPLAY = 1; // 0x1
- field public static final int RENDER_MODE_FOR_PRINT = 2; // 0x2
- }
-
}
package android.graphics.text {
@@ -20379,54 +20360,6 @@
}
-package android.hardware.fingerprint {
-
- @Deprecated public class FingerprintManager {
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.USE_BIOMETRIC, android.Manifest.permission.USE_FINGERPRINT}) public void authenticate(@Nullable android.hardware.fingerprint.FingerprintManager.CryptoObject, @Nullable android.os.CancellationSignal, int, @NonNull android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, @Nullable android.os.Handler);
- method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean hasEnrolledFingerprints();
- method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean isHardwareDetected();
- field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0
- field public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; // 0x3
- field public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; // 0x2
- field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1
- field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5
- field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4
- field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5
- field public static final int FINGERPRINT_ERROR_HW_NOT_PRESENT = 12; // 0xc
- field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
- field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7
- field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9
- field public static final int FINGERPRINT_ERROR_NO_FINGERPRINTS = 11; // 0xb
- field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
- field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
- field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
- field public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; // 0xa
- field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8
- }
-
- @Deprecated public abstract static class FingerprintManager.AuthenticationCallback {
- ctor @Deprecated public FingerprintManager.AuthenticationCallback();
- method @Deprecated public void onAuthenticationError(int, CharSequence);
- method @Deprecated public void onAuthenticationFailed();
- method @Deprecated public void onAuthenticationHelp(int, CharSequence);
- method @Deprecated public void onAuthenticationSucceeded(android.hardware.fingerprint.FingerprintManager.AuthenticationResult);
- }
-
- @Deprecated public static class FingerprintManager.AuthenticationResult {
- method @Deprecated public android.hardware.fingerprint.FingerprintManager.CryptoObject getCryptoObject();
- }
-
- @Deprecated public static final class FingerprintManager.CryptoObject {
- ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull java.security.Signature);
- ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull javax.crypto.Cipher);
- ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull javax.crypto.Mac);
- method @Deprecated public javax.crypto.Cipher getCipher();
- method @Deprecated public javax.crypto.Mac getMac();
- method @Deprecated public java.security.Signature getSignature();
- }
-
-}
-
package android.hardware.input {
public final class HostUsiVersion implements android.os.Parcelable {
diff --git a/core/api/removed.txt b/core/api/removed.txt
index 3c7c0d6..c61f163 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -35,6 +35,7 @@
method @Deprecated @Nullable public String getFeatureId();
method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
method public abstract java.io.File getSharedPreferencesPath(String);
+ field public static final String FINGERPRINT_SERVICE = "fingerprint";
}
public class ContextWrapper extends android.content.Context {
@@ -145,6 +146,54 @@
}
+package android.hardware.fingerprint {
+
+ @Deprecated public class FingerprintManager {
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.USE_BIOMETRIC, android.Manifest.permission.USE_FINGERPRINT}) public void authenticate(@Nullable android.hardware.fingerprint.FingerprintManager.CryptoObject, @Nullable android.os.CancellationSignal, int, @NonNull android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, @Nullable android.os.Handler);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean hasEnrolledFingerprints();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public boolean isHardwareDetected();
+ field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0
+ field public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3; // 0x3
+ field public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2; // 0x2
+ field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1
+ field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5
+ field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4
+ field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5
+ field public static final int FINGERPRINT_ERROR_HW_NOT_PRESENT = 12; // 0xc
+ field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
+ field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7
+ field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9
+ field public static final int FINGERPRINT_ERROR_NO_FINGERPRINTS = 11; // 0xb
+ field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
+ field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
+ field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
+ field public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; // 0xa
+ field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8
+ }
+
+ @Deprecated public abstract static class FingerprintManager.AuthenticationCallback {
+ ctor public FingerprintManager.AuthenticationCallback();
+ method public void onAuthenticationError(int, CharSequence);
+ method public void onAuthenticationFailed();
+ method public void onAuthenticationHelp(int, CharSequence);
+ method public void onAuthenticationSucceeded(android.hardware.fingerprint.FingerprintManager.AuthenticationResult);
+ }
+
+ @Deprecated public static class FingerprintManager.AuthenticationResult {
+ method public android.hardware.fingerprint.FingerprintManager.CryptoObject getCryptoObject();
+ }
+
+ @Deprecated public static final class FingerprintManager.CryptoObject {
+ ctor public FingerprintManager.CryptoObject(@NonNull java.security.Signature);
+ ctor public FingerprintManager.CryptoObject(@NonNull javax.crypto.Cipher);
+ ctor public FingerprintManager.CryptoObject(@NonNull javax.crypto.Mac);
+ method public javax.crypto.Cipher getCipher();
+ method public javax.crypto.Mac getMac();
+ method public java.security.Signature getSignature();
+ }
+
+}
+
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index cfdabc8..15f1eb4 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1710,15 +1710,6 @@
}
-package android.hardware.fingerprint {
-
- @Deprecated public class FingerprintManager {
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession createTestSession(int);
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties();
- }
-
-}
-
package android.hardware.hdmi {
public final class HdmiControlServiceWrapper {
diff --git a/core/api/test-removed.txt b/core/api/test-removed.txt
index d802177..2e44176 100644
--- a/core/api/test-removed.txt
+++ b/core/api/test-removed.txt
@@ -1 +1,10 @@
// Signature format: 2.0
+package android.hardware.fingerprint {
+
+ @Deprecated public class FingerprintManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession createTestSession(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties();
+ }
+
+}
+
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 44dc8e2..afbefca 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1126,8 +1126,8 @@
* @hide
*/
@Override
- public void updateStatusBarAppearance(int appearance) {
- mTaskDescription.setStatusBarAppearance(appearance);
+ public void updateSystemBarsAppearance(int appearance) {
+ mTaskDescription.setSystemBarsAppearance(appearance);
setTaskDescription(mTaskDescription);
}
@@ -5546,6 +5546,15 @@
}
a.recycle();
+ if (first && mTaskDescription.getSystemBarsAppearance() == 0
+ && mWindow != null && mWindow.getSystemBarAppearance() != 0) {
+ // When the theme is applied for the first time during the activity re-creation process,
+ // the attached window restores the system bars appearance from the old window/activity.
+ // Make sure to restore this appearance in TaskDescription too, to prevent the
+ // #setTaskDescription() call below from incorrectly sending an empty value to the
+ // server.
+ mTaskDescription.setSystemBarsAppearance(mWindow.getSystemBarAppearance());
+ }
setTaskDescription(mTaskDescription);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f358522..39823a8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1604,7 +1604,7 @@
private int mStatusBarColor;
private int mNavigationBarColor;
@Appearance
- private int mStatusBarAppearance;
+ private int mSystemBarsAppearance;
private boolean mEnsureStatusBarContrastWhenTransparent;
private boolean mEnsureNavigationBarContrastWhenTransparent;
private int mResizeMode;
@@ -1804,7 +1804,7 @@
public TaskDescription(@Nullable String label, @Nullable Icon icon,
int colorPrimary, int colorBackground,
int statusBarColor, int navigationBarColor,
- @Appearance int statusBarAppearance,
+ @Appearance int systemBarsAppearance,
boolean ensureStatusBarContrastWhenTransparent,
boolean ensureNavigationBarContrastWhenTransparent, int resizeMode, int minWidth,
int minHeight, int colorBackgroundFloating) {
@@ -1814,7 +1814,7 @@
mColorBackground = colorBackground;
mStatusBarColor = statusBarColor;
mNavigationBarColor = navigationBarColor;
- mStatusBarAppearance = statusBarAppearance;
+ mSystemBarsAppearance = systemBarsAppearance;
mEnsureStatusBarContrastWhenTransparent = ensureStatusBarContrastWhenTransparent;
mEnsureNavigationBarContrastWhenTransparent =
ensureNavigationBarContrastWhenTransparent;
@@ -1843,7 +1843,7 @@
mColorBackground = other.mColorBackground;
mStatusBarColor = other.mStatusBarColor;
mNavigationBarColor = other.mNavigationBarColor;
- mStatusBarAppearance = other.mStatusBarAppearance;
+ mSystemBarsAppearance = other.mSystemBarsAppearance;
mEnsureStatusBarContrastWhenTransparent = other.mEnsureStatusBarContrastWhenTransparent;
mEnsureNavigationBarContrastWhenTransparent =
other.mEnsureNavigationBarContrastWhenTransparent;
@@ -1873,8 +1873,8 @@
if (other.mNavigationBarColor != 0) {
mNavigationBarColor = other.mNavigationBarColor;
}
- if (other.mStatusBarAppearance != 0) {
- mStatusBarAppearance = other.mStatusBarAppearance;
+ if (other.mSystemBarsAppearance != 0) {
+ mSystemBarsAppearance = other.mSystemBarsAppearance;
}
mEnsureStatusBarContrastWhenTransparent = other.mEnsureStatusBarContrastWhenTransparent;
@@ -2148,8 +2148,8 @@
* @hide
*/
@Appearance
- public int getStatusBarAppearance() {
- return mStatusBarAppearance;
+ public int getSystemBarsAppearance() {
+ return mSystemBarsAppearance;
}
/**
@@ -2163,8 +2163,8 @@
/**
* @hide
*/
- public void setStatusBarAppearance(@Appearance int statusBarAppearance) {
- mStatusBarAppearance = statusBarAppearance;
+ public void setSystemBarsAppearance(@Appearance int systemBarsAppearance) {
+ mSystemBarsAppearance = systemBarsAppearance;
}
/**
@@ -2291,7 +2291,7 @@
dest.writeInt(mColorBackground);
dest.writeInt(mStatusBarColor);
dest.writeInt(mNavigationBarColor);
- dest.writeInt(mStatusBarAppearance);
+ dest.writeInt(mSystemBarsAppearance);
dest.writeBoolean(mEnsureStatusBarContrastWhenTransparent);
dest.writeBoolean(mEnsureNavigationBarContrastWhenTransparent);
dest.writeInt(mResizeMode);
@@ -2315,7 +2315,7 @@
mColorBackground = source.readInt();
mStatusBarColor = source.readInt();
mNavigationBarColor = source.readInt();
- mStatusBarAppearance = source.readInt();
+ mSystemBarsAppearance = source.readInt();
mEnsureStatusBarContrastWhenTransparent = source.readBoolean();
mEnsureNavigationBarContrastWhenTransparent = source.readBoolean();
mResizeMode = source.readInt();
@@ -2347,7 +2347,8 @@
? " (contrast when transparent)" : "")
+ " resizeMode: " + ActivityInfo.resizeModeToString(mResizeMode)
+ " minWidth: " + mMinWidth + " minHeight: " + mMinHeight
- + " colorBackgrounFloating: " + mColorBackgroundFloating;
+ + " colorBackgrounFloating: " + mColorBackgroundFloating
+ + " systemBarsAppearance: " + mSystemBarsAppearance;
}
@Override
@@ -2367,7 +2368,7 @@
result = result * 31 + mColorBackgroundFloating;
result = result * 31 + mStatusBarColor;
result = result * 31 + mNavigationBarColor;
- result = result * 31 + mStatusBarAppearance;
+ result = result * 31 + mSystemBarsAppearance;
result = result * 31 + (mEnsureStatusBarContrastWhenTransparent ? 1 : 0);
result = result * 31 + (mEnsureNavigationBarContrastWhenTransparent ? 1 : 0);
result = result * 31 + mResizeMode;
@@ -2390,7 +2391,7 @@
&& mColorBackground == other.mColorBackground
&& mStatusBarColor == other.mStatusBarColor
&& mNavigationBarColor == other.mNavigationBarColor
- && mStatusBarAppearance == other.mStatusBarAppearance
+ && mSystemBarsAppearance == other.mSystemBarsAppearance
&& mEnsureStatusBarContrastWhenTransparent
== other.mEnsureStatusBarContrastWhenTransparent
&& mEnsureNavigationBarContrastWhenTransparent
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 5e2397d..33d41d3 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -185,6 +185,8 @@
/**
* Creates an automatic zen rule.
*
+ * <p>Note: Prefer {@link AutomaticZenRule.Builder} to construct an {@link AutomaticZenRule}.
+ *
* @param name The name of the rule.
* @param owner The Condition Provider service that owns this rule. This can be null if you're
* using {@link NotificationManager#setAutomaticZenRuleState(String, Condition)}
@@ -206,10 +208,7 @@
* while this rule is active. This overrides the global policy while this rule is
* action ({@link Condition#STATE_TRUE}).
* @param enabled Whether the rule is enabled.
- *
- * @deprecated Use {@link AutomaticZenRule.Builder} to construct an {@link AutomaticZenRule}.
*/
- @Deprecated
public AutomaticZenRule(@NonNull String name, @Nullable ComponentName owner,
@Nullable ComponentName configurationActivity, @NonNull Uri conditionId,
@Nullable ZenPolicy policy, int interruptionFilter, boolean enabled) {
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index ab5395e..9f2e473 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -562,6 +562,12 @@
* audio attributes. Notification channels with an {@link #getImportance() importance} of at
* least {@link NotificationManager#IMPORTANCE_DEFAULT} should have a sound.
*
+ * Note: An app-specific sound can be provided in the Uri parameter, but because channels are
+ * persistent for the duration of the app install, and are backed up and restored, the Uri
+ * should be stable. For this reason it is not recommended to use a
+ * {@link ContentResolver#SCHEME_ANDROID_RESOURCE} uri, as resource ids can change on app
+ * upgrade.
+ *
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}.
*/
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c7e5d88..7f2ec53 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5067,6 +5067,7 @@
* {@link android.hardware.fingerprint.FingerprintManager} for handling management
* of fingerprints.
*
+ * @removed See {@link android.hardware.biometrics.BiometricPrompt}
* @see #getSystemService(String)
* @see android.hardware.fingerprint.FingerprintManager
*/
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 42dd87a..443aadd 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -8183,7 +8183,7 @@
// launch flags
else if (uri.startsWith("launchFlags=", i)) {
- intent.mFlags = Integer.decode(value);
+ intent.mFlags = decodeInteger(value);
if ((flags& URI_ALLOW_UNSAFE) == 0) {
intent.mFlags &= ~IMMUTABLE_FLAGS;
}
@@ -8191,7 +8191,7 @@
// extended flags
else if (uri.startsWith("extendedLaunchFlags=", i)) {
- intent.mExtendedFlags = Integer.decode(value);
+ intent.mExtendedFlags = decodeInteger(value);
}
// package
@@ -8401,7 +8401,7 @@
isIntentFragment = true;
i += 12;
int j = uri.indexOf(')', i);
- intent.mFlags = Integer.decode(uri.substring(i, j));
+ intent.mFlags = decodeInteger(uri.substring(i, j));
if ((flags& URI_ALLOW_UNSAFE) == 0) {
intent.mFlags &= ~IMMUTABLE_FLAGS;
}
@@ -8512,6 +8512,23 @@
return intent;
}
+ private static Integer decodeInteger(String value) {
+ try {
+ return Integer.decode(value);
+ } catch (NumberFormatException e) {
+ try {
+ if (value != null && value.startsWith("0x")) {
+ // In toUriInner, we do "0x".append(Integer.toHexString).
+ // Sometimes "decode" fails to parse, e.g. 0x90000000.
+ return Integer.parseUnsignedInt(value.substring(2), 16);
+ }
+ } catch (NumberFormatException ignored) {
+ // ignored, throw the original exception
+ }
+ throw e;
+ }
+ }
+
/** @hide */
public interface CommandOptionHandler {
boolean handleOption(String opt, ShellCommand cmd);
@@ -8577,7 +8594,7 @@
case "--ei": {
String key = cmd.getNextArgRequired();
String value = cmd.getNextArgRequired();
- intent.putExtra(key, Integer.decode(value));
+ intent.putExtra(key, decodeInteger(value));
}
break;
case "--eu": {
@@ -8601,7 +8618,7 @@
String[] strings = value.split(",");
int[] list = new int[strings.length];
for (int i = 0; i < strings.length; i++) {
- list[i] = Integer.decode(strings[i]);
+ list[i] = decodeInteger(strings[i]);
}
intent.putExtra(key, list);
}
@@ -8612,7 +8629,7 @@
String[] strings = value.split(",");
ArrayList<Integer> list = new ArrayList<>(strings.length);
for (int i = 0; i < strings.length; i++) {
- list.add(Integer.decode(strings[i]));
+ list.add(decodeInteger(strings[i]));
}
intent.putExtra(key, list);
}
@@ -8747,7 +8764,7 @@
arg = false;
} else {
try {
- arg = Integer.decode(value) != 0;
+ arg = decodeInteger(value) != 0;
} catch (NumberFormatException ex) {
throw new IllegalArgumentException("Invalid boolean value: " + value);
}
@@ -8777,7 +8794,7 @@
break;
case "-f":
String str = cmd.getNextArgRequired();
- intent.setFlags(Integer.decode(str).intValue());
+ intent.setFlags(decodeInteger(str).intValue());
break;
case "--grant-read-uri-permission":
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
diff --git a/core/java/android/hardware/OverlayProperties.java b/core/java/android/hardware/OverlayProperties.java
index 88089ee..4a4d451 100644
--- a/core/java/android/hardware/OverlayProperties.java
+++ b/core/java/android/hardware/OverlayProperties.java
@@ -70,19 +70,6 @@
}
/**
- * @return True if the device can support fp16, false otherwise.
- * TODO: Move this to isCombinationSupported once the flag flips
- * @hide
- */
- public boolean isFp16SupportedForHdr() {
- if (mNativeObject == 0) {
- return false;
- }
- return nIsCombinationSupported(
- mNativeObject, DataSpace.DATASPACE_SCRGB, HardwareBuffer.RGBA_FP16);
- }
-
- /**
* Indicates that hardware composition of a buffer encoded with the provided {@link DataSpace}
* and {@link HardwareBuffer.Format} is supported on the device.
*
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 6b2814e..58aafbc 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -778,6 +778,16 @@
*/
float[] getAutoBrightnessLuxLevels(int mode);
+ /**
+ * @return The current brightness setting
+ */
+ float getBrightness();
+
+ /**
+ * @return The brightness value that is used when the device is in doze
+ */
+ float getDozeBrightness();
+
/** Returns whether displayoffload supports the given display state. */
static boolean isSupportedOffloadState(int displayState) {
return Display.isSuspendedState(displayState);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 81e321d..b0f69f5 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -83,7 +83,8 @@
/**
* A class that coordinates access to the fingerprint hardware.
- * @deprecated See {@link BiometricPrompt} which shows a system-provided dialog upon starting
+ *
+ * @removed See {@link BiometricPrompt} which shows a system-provided dialog upon starting
* authentication. In a world where devices may have different types of biometric authentication,
* it's much more realistic to have a system-provided authentication dialog since the method may
* vary by vendor/device.
@@ -94,7 +95,6 @@
@RequiresFeature(PackageManager.FEATURE_FINGERPRINT)
public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {
private static final String TAG = "FingerprintManager";
- private static final boolean DEBUG = true;
private static final int MSG_ENROLL_RESULT = 100;
private static final int MSG_ACQUIRED = 101;
private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
@@ -196,6 +196,7 @@
/**
* Retrieves a test session for FingerprintManager.
+ *
* @hide
*/
@TestApi
@@ -254,9 +255,10 @@
}
/**
- * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
+ * A wrapper class for the crypto objects supported by FingerprintManager. Currently, the
* framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
- * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.CryptoObject}
+ *
+ * @removed See {@link android.hardware.biometrics.BiometricPrompt.CryptoObject}
*/
@Deprecated
public static final class CryptoObject extends android.hardware.biometrics.CryptoObject {
@@ -330,7 +332,8 @@
/**
* Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
* CancellationSignal, int, AuthenticationCallback, Handler)}.
- * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationResult}
+ *
+ * @removed See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationResult}
*/
@Deprecated
public static class AuthenticationResult {
@@ -392,7 +395,8 @@
* FingerprintManager#authenticate(CryptoObject, CancellationSignal,
* int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
* fingerprint events.
- * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationCallback}
+ *
+ * @removed See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationCallback}
*/
@Deprecated
public static abstract class AuthenticationCallback
@@ -455,6 +459,7 @@
/**
* Callback structure provided for {@link #detectFingerprint(CancellationSignal,
* FingerprintDetectionCallback, int, Surface)}.
+ *
* @hide
*/
public interface FingerprintDetectionCallback {
@@ -608,7 +613,8 @@
* by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
* facility</a>.
* @throws IllegalStateException if the crypto primitive is not initialized.
- * @deprecated See {@link BiometricPrompt#authenticate(CancellationSignal, Executor,
+ *
+ * @removed See {@link BiometricPrompt#authenticate(CancellationSignal, Executor,
* BiometricPrompt.AuthenticationCallback)} and {@link BiometricPrompt#authenticate(
* BiometricPrompt.CryptoObject, CancellationSignal, Executor,
* BiometricPrompt.AuthenticationCallback)}
@@ -623,6 +629,7 @@
/**
* Per-user version of authenticate.
* @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
+ *
* @hide
*/
@Deprecated
@@ -635,6 +642,7 @@
/**
* Per-user and per-sensor version of authenticate.
* @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
+ *
* @hide
*/
@Deprecated
@@ -651,6 +659,7 @@
/**
* Version of authenticate with additional options.
+ *
* @hide
*/
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
@@ -698,6 +707,7 @@
/**
* Uses the fingerprint hardware to detect for the presence of a finger, without giving details
* about accept/reject/lockout.
+ *
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
@@ -740,6 +750,7 @@
* @param callback an object to receive enrollment events
* @param shouldLogMetrics a flag that indicates if enrollment failure/success metrics
* should be logged.
+ *
* @hide
*/
@RequiresPermission(MANAGE_FINGERPRINT)
@@ -810,6 +821,7 @@
/**
* Same as {@link #generateChallenge(int, GenerateChallengeCallback)}, but assumes the first
* enumerated sensor.
+ *
* @hide
*/
@RequiresPermission(MANAGE_FINGERPRINT)
@@ -824,6 +836,7 @@
/**
* Revokes the specified challenge.
+ *
* @hide
*/
@RequiresPermission(MANAGE_FINGERPRINT)
@@ -849,6 +862,7 @@
* @param sensorId Sensor ID that this operation takes effect for
* @param userId User ID that this operation takes effect for.
* @param hardwareAuthToken An opaque token returned by password confirmation.
+ *
* @hide
*/
@RequiresPermission(RESET_FINGERPRINT_LOCKOUT)
@@ -886,6 +900,7 @@
/**
* Removes all fingerprint templates for the given user.
+ *
* @hide
*/
@RequiresPermission(MANAGE_FINGERPRINT)
@@ -1005,6 +1020,7 @@
/**
* Forwards BiometricStateListener to FingerprintService
* @param listener new BiometricStateListener being added
+ *
* @hide
*/
public void registerBiometricStateListener(@NonNull BiometricStateListener listener) {
@@ -1156,7 +1172,8 @@
}
/**
- * This is triggered by SideFpsEventHandler
+ * This is triggered by SideFpsEventHandler.
+ *
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
@@ -1169,7 +1186,8 @@
* Determine if there is at least one fingerprint enrolled.
*
* @return true if at least one fingerprint is enrolled, false otherwise
- * @deprecated See {@link BiometricPrompt} and
+ *
+ * @removed See {@link BiometricPrompt} and
* {@link FingerprintManager#FINGERPRINT_ERROR_NO_FINGERPRINTS}
*/
@Deprecated
@@ -1203,7 +1221,8 @@
* Determine if fingerprint hardware is present and functional.
*
* @return true if hardware is present and functional, false otherwise.
- * @deprecated See {@link BiometricPrompt} and
+ *
+ * @removed See {@link BiometricPrompt} and
* {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE}
*/
@Deprecated
@@ -1229,6 +1248,7 @@
/**
* Get statically configured sensor properties.
+ *
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
@@ -1247,6 +1267,7 @@
/**
* Returns whether the device has a power button fingerprint sensor.
* @return boolean indicating whether power button is fingerprint sensor
+ *
* @hide
*/
public boolean isPowerbuttonFps() {
diff --git a/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
index 2a11835..9e487e1 100644
--- a/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
+++ b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
@@ -25,5 +25,5 @@
name: "enable_usb_data_signal_staking"
namespace: "preload_safety"
description: "Enables signal API with staking"
- bug: "296119135"
+ bug: "287498482"
}
\ No newline at end of file
diff --git a/core/java/android/service/voice/HotwordDetectedResult.java b/core/java/android/service/voice/HotwordDetectedResult.java
index 6140812..df4a2bb 100644
--- a/core/java/android/service/voice/HotwordDetectedResult.java
+++ b/core/java/android/service/voice/HotwordDetectedResult.java
@@ -662,6 +662,8 @@
/**
* Id of the current speaker
+ *
+ * <p>Only values between 0 and {@link #getMaxSpeakerId} (inclusive) are accepted.
*/
@DataClass.Generated.Member
@FlaggedApi(Flags.FLAG_ALLOW_SPEAKER_ID_EGRESS)
@@ -982,6 +984,8 @@
/**
* Id of the current speaker
+ *
+ * <p>Only values between 0 and {@link #getMaxSpeakerId} (inclusive) are accepted.
*/
@DataClass.Generated.Member
@FlaggedApi(Flags.FLAG_ALLOW_SPEAKER_ID_EGRESS)
@@ -1228,7 +1232,7 @@
}
@DataClass.Generated(
- time = 1704944087827L,
+ time = 1709773165191L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
inputSignatures = "public static final int CONFIDENCE_LEVEL_NONE\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\npublic static final int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final int HOTWORD_OFFSET_UNSET\npublic static final int AUDIO_CHANNEL_UNSET\npublic static final int BACKGROUND_AUDIO_POWER_UNSET\nprivate static final int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE\nprivate static final java.lang.String EXTRA_PROXIMITY\npublic static final int PROXIMITY_UNKNOWN\npublic static final int PROXIMITY_NEAR\npublic static final int PROXIMITY_FAR\nprivate final int mSpeakerId\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate int mHotwordOffsetMillis\nprivate int mHotwordDurationMillis\nprivate int mAudioChannel\nprivate boolean mHotwordDetectionPersonalized\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final int mHotwordPhraseId\nprivate final @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> mAudioStreams\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int sMaxBundleSize\nprivate final int mBackgroundAudioPower\nprivate static int defaultSpeakerId()\npublic static @android.annotation.FlaggedApi int getMaxSpeakerId()\nprivate static int defaultConfidenceLevel()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static int defaultHotwordPhraseId()\npublic static int getMaxHotwordPhraseId()\nprivate static java.util.List<android.service.voice.HotwordAudioStream> defaultAudioStreams()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\nprivate static int defaultBackgroundAudioPower()\npublic static int getMaxBackgroundAudioPower()\npublic static int getParcelableSize(android.os.Parcelable)\npublic static int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static int bitCount(long)\nprivate void onConstructed()\npublic @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams()\npublic void setProximity(double)\npublic @android.service.voice.HotwordDetectedResult.ProximityValue int getProximity()\nprivate @android.service.voice.HotwordDetectedResult.ProximityValue int convertToProximityLevel(double)\npublic android.service.voice.HotwordDetectedResult.Builder buildUpon()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []")
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b91a878..4d4cb6c 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -194,13 +194,6 @@
public static final String SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION =
"settings_remote_device_credential_validation";
- /**
- * Flag to enable/disable to start treating any calls to "suspend" an app as "quarantine".
- * @hide
- */
- public static final String SETTINGS_TREAT_PAUSE_AS_QUARANTINE =
- "settings_treat_pause_as_quarantine";
-
private static final Map<String, String> DEFAULT_FLAGS;
static {
@@ -246,7 +239,6 @@
DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS, "false");
// TODO: b/298454866 Replace with Trunk Stable Feature Flag
DEFAULT_FLAGS.put(SETTINGS_REMOTEAUTH_ENROLLMENT_SETTINGS, "false");
- DEFAULT_FLAGS.put(SETTINGS_TREAT_PAUSE_AS_QUARANTINE, "false");
}
private static final Set<String> PERSISTENT_FLAGS;
@@ -264,7 +256,6 @@
PERSISTENT_FLAGS.add(SETTINGS_ENABLE_SPA);
PERSISTENT_FLAGS.add(SETTINGS_ENABLE_SPA_PHASE2);
PERSISTENT_FLAGS.add(SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM);
- PERSISTENT_FLAGS.add(SETTINGS_TREAT_PAUSE_AS_QUARANTINE);
}
/**
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 6cc4b20..1920fa3 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1876,11 +1876,15 @@
@Override
public @Appearance int getSystemBarsAppearance() {
+ @Appearance int appearance = mHost.getSystemBarsAppearance();
+
+ // We only return the requested appearance, not the implied one.
+ appearance &= ~APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS;
if (!mHost.isSystemBarsAppearanceControlled()) {
- // We only return the requested appearance, not the implied one.
- return 0;
+ appearance &= ~COMPATIBLE_APPEARANCE_FLAGS;
}
- return mHost.getSystemBarsAppearance();
+
+ return appearance;
}
@Override
diff --git a/core/java/android/view/InsetsFlags.java b/core/java/android/view/InsetsFlags.java
index 3355252..ca8a7a8 100644
--- a/core/java/android/view/InsetsFlags.java
+++ b/core/java/android/view/InsetsFlags.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.WindowInsetsController.APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -64,7 +65,11 @@
@ViewDebug.FlagToString(
mask = APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS,
equals = APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS,
- name = "SEMI_TRANSPARENT_NAVIGATION_BARS")
+ name = "SEMI_TRANSPARENT_NAVIGATION_BARS"),
+ @ViewDebug.FlagToString(
+ mask = APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS,
+ equals = APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS,
+ name = "FORCE_LIGHT_NAVIGATION_BARS")
})
public @Appearance int appearance;
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 124aece..c66abe8 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -889,11 +889,11 @@
* @hide
*/
@Override
- protected int calculateFrameRateCategory(float sizePercentage) {
+ protected int calculateFrameRateCategory(int width, int height) {
if (mMinusTwoFrameIntervalMillis > 15 && mMinusOneFrameIntervalMillis > 15) {
return FRAME_RATE_CATEGORY_NORMAL;
}
- return super.calculateFrameRateCategory(sizePercentage);
+ return super.calculateFrameRateCategory(width, height);
}
@UnsupportedAppUsage
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a6f380d..f0bde97 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2371,6 +2371,39 @@
*/
protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ /**
+ * This indicates that the frame rate category was chosen because it was a small area update.
+ * @hide
+ */
+ public static final int FRAME_RATE_CATEGORY_REASON_SMALL = 0x0100_0000;
+
+ /**
+ * This indicates that the frame rate category was chosen because it was an intermittent update.
+ * @hide
+ */
+ public static final int FRAME_RATE_CATEGORY_REASON_INTERMITTENT = 0x0200_0000;
+
+ /**
+ * This indicates that the frame rate category was chosen because it was a large View.
+ * @hide
+ */
+ public static final int FRAME_RATE_CATEGORY_REASON_LARGE = 0x03000000;
+
+ /**
+ * This indicates that the frame rate category was chosen because it was requested.
+ * @hide
+ */
+ public static final int FRAME_RATE_CATEGORY_REASON_REQUESTED = 0x0400_0000;
+
+ /**
+ * This indicates that the frame rate category was chosen because an invalid frame rate was
+ * requested.
+ * @hide
+ */
+ public static final int FRAME_RATE_CATEGORY_REASON_INVALID = 0x0500_0000;
+
+ private static final int FRAME_RATE_CATEGORY_REASON_MASK = 0xFFFF_0000;
+
private static boolean sToolkitSetFrameRateReadOnlyFlagValue;
private static boolean sToolkitMetricsForFrameRateDecisionFlagValue;
// Used to set frame rate compatibility.
@@ -5637,10 +5670,17 @@
private ViewTranslationResponse mViewTranslationResponse;
/**
- * A threshold value to determine the frame rate category of the View based on the size.
+ * Threshold size for something to be considered a small area update (in DP).
+ * This is the dimension for both width and height.
*/
- private static final float FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD = 0.07f;
+ private static final float FRAME_RATE_SMALL_SIZE_THRESHOLD = 40f;
+ /**
+ * Threshold size for something to be considered a small area update (in DP) if
+ * it is narrow. This is for either width OR height. For example, a narrow progress
+ * bar could be considered a small area.
+ */
+ private static final float FRAME_RATE_NARROW_THRESHOLD = 10f;
private static final long INFREQUENT_UPDATE_INTERVAL_MILLIS = 100;
private static final int INFREQUENT_UPDATE_COUNTS = 2;
@@ -33655,18 +33695,28 @@
*
* @hide
*/
- protected int calculateFrameRateCategory(float sizePercentage) {
+ protected int calculateFrameRateCategory(int width, int height) {
if (mMinusTwoFrameIntervalMillis + mMinusOneFrameIntervalMillis
< INFREQUENT_UPDATE_INTERVAL_MILLIS) {
- if (sizePercentage <= FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD) {
- return FRAME_RATE_CATEGORY_NORMAL;
+ DisplayMetrics displayMetrics = mResources.getDisplayMetrics();
+ float density = displayMetrics.density;
+ if (density == 0f) {
+ density = 1f;
+ }
+ float widthDp = width / density;
+ float heightDp = height / density;
+ if (widthDp <= FRAME_RATE_NARROW_THRESHOLD
+ || heightDp <= FRAME_RATE_NARROW_THRESHOLD
+ || (widthDp <= FRAME_RATE_SMALL_SIZE_THRESHOLD
+ && heightDp <= FRAME_RATE_SMALL_SIZE_THRESHOLD)) {
+ return FRAME_RATE_CATEGORY_NORMAL | FRAME_RATE_CATEGORY_REASON_SMALL;
} else {
- return FRAME_RATE_CATEGORY_HIGH;
+ return FRAME_RATE_CATEGORY_HIGH | FRAME_RATE_CATEGORY_REASON_LARGE;
}
}
if (mInfrequentUpdateCount == INFREQUENT_UPDATE_COUNTS) {
- return FRAME_RATE_CATEGORY_NORMAL;
+ return FRAME_RATE_CATEGORY_NORMAL | FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
}
return mLastFrameRateCategory;
}
@@ -33674,12 +33724,9 @@
private void votePreferredFrameRate() {
// use toolkitSetFrameRate flag to gate the change
ViewRootImpl viewRootImpl = getViewRootImpl();
- float sizePercentage = getSizePercentage();
- int frameRateCateogry = calculateFrameRateCategory(sizePercentage);
- if (viewRootImpl != null && sizePercentage > 0) {
- if (sToolkitMetricsForFrameRateDecisionFlagValue) {
- viewRootImpl.recordViewPercentage(sizePercentage);
- }
+ int width = mRight - mLeft;
+ int height = mBottom - mTop;
+ if (viewRootImpl != null && (width != 0 && height != 0)) {
if (viewVelocityApi()) {
float velocity = mFrameContentVelocity;
if (velocity < 0f) {
@@ -33691,25 +33738,40 @@
return;
}
}
- if (!Float.isNaN(mPreferredFrameRate)) {
- if (mPreferredFrameRate < 0) {
- if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE) {
- frameRateCateogry = FRAME_RATE_CATEGORY_NO_PREFERENCE;
- } else if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_LOW) {
- frameRateCateogry = FRAME_RATE_CATEGORY_LOW;
- } else if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_NORMAL) {
- frameRateCateogry = FRAME_RATE_CATEGORY_NORMAL;
- } else if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_HIGH) {
- frameRateCateogry = FRAME_RATE_CATEGORY_HIGH;
- }
+ int frameRateCategory;
+ if (Float.isNaN(mPreferredFrameRate)) {
+ frameRateCategory = calculateFrameRateCategory(width, height);
+ } else if (mPreferredFrameRate < 0) {
+ if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE) {
+ frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
+ | FRAME_RATE_CATEGORY_REASON_REQUESTED;
+ } else if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_LOW) {
+ frameRateCategory = FRAME_RATE_CATEGORY_LOW
+ | FRAME_RATE_CATEGORY_REASON_REQUESTED;
+ } else if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_NORMAL) {
+ frameRateCategory = FRAME_RATE_CATEGORY_NORMAL
+ | FRAME_RATE_CATEGORY_REASON_REQUESTED;
+ } else if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_HIGH) {
+ frameRateCategory = FRAME_RATE_CATEGORY_HIGH
+ | FRAME_RATE_CATEGORY_REASON_REQUESTED;
} else {
- viewRootImpl.votePreferredFrameRate(mPreferredFrameRate,
- mFrameRateCompatibility);
- return;
+ // invalid frame rate, default to HIGH
+ frameRateCategory = FRAME_RATE_CATEGORY_HIGH
+ | FRAME_RATE_CATEGORY_REASON_INVALID;
}
+ } else {
+ viewRootImpl.votePreferredFrameRate(mPreferredFrameRate,
+ mFrameRateCompatibility);
+ return;
}
- viewRootImpl.votePreferredFrameRateCategory(frameRateCateogry);
- mLastFrameRateCategory = frameRateCateogry;
+
+ int category = frameRateCategory & ~FRAME_RATE_CATEGORY_REASON_MASK;
+ if (sToolkitMetricsForFrameRateDecisionFlagValue) {
+ int reason = frameRateCategory & FRAME_RATE_CATEGORY_REASON_MASK;
+ viewRootImpl.recordCategory(category, reason, this);
+ }
+ viewRootImpl.votePreferredFrameRateCategory(category);
+ mLastFrameRateCategory = frameRateCategory;
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 42f6405..6f178bb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -32,6 +32,11 @@
import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
+import static android.view.View.FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
+import static android.view.View.FRAME_RATE_CATEGORY_REASON_INVALID;
+import static android.view.View.FRAME_RATE_CATEGORY_REASON_LARGE;
+import static android.view.View.FRAME_RATE_CATEGORY_REASON_REQUESTED;
+import static android.view.View.FRAME_RATE_CATEGORY_REASON_SMALL;
import static android.view.View.PFLAG_DRAW_ANIMATION;
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
@@ -59,6 +64,7 @@
import static android.view.ViewRootImplProto.WINDOW_ATTRIBUTES;
import static android.view.ViewRootImplProto.WIN_FRAME;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
+import static android.view.WindowInsetsController.COMPATIBLE_APPEARANCE_FLAGS;
import static android.view.flags.Flags.sensitiveContentAppProtection;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
@@ -841,8 +847,9 @@
private boolean mInsetsAnimationRunning;
private long mPreviousFrameDrawnTime = -1;
- // The largest view size percentage to the display size. Used on trace to collect metric.
- private float mLargestChildPercentage = 0.0f;
+ // The reason the category was changed.
+ private int mFrameRateCategoryChangeReason = 0;
+ private String mFrameRateCategoryView;
/**
* The resolved pointer icon type requested by this window.
@@ -2861,7 +2868,7 @@
final int adjust = inOutParams.softInputMode & SOFT_INPUT_MASK_ADJUST;
if ((inOutParams.privateFlags & PRIVATE_FLAG_APPEARANCE_CONTROLLED) == 0) {
- inOutParams.insetsFlags.appearance = 0;
+ inOutParams.insetsFlags.appearance &= ~COMPATIBLE_APPEARANCE_FLAGS;
if ((sysUiVis & SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
inOutParams.insetsFlags.appearance |= APPEARANCE_LOW_PROFILE_BARS;
}
@@ -4847,10 +4854,6 @@
long fps = NANOS_PER_SEC / timeDiff;
Trace.setCounter(mFpsTraceName, fps);
mPreviousFrameDrawnTime = expectedDrawnTime;
-
- long percentage = (long) (mLargestChildPercentage * 100);
- Trace.setCounter(mLargestViewTraceName, percentage);
- mLargestChildPercentage = 0.0f;
}
private void reportDrawFinished(@Nullable Transaction t, int seqId) {
@@ -12360,16 +12363,29 @@
// For now, FRAME_RATE_CATEGORY_HIGH_HINT is used for boosting with user interaction.
// FRAME_RATE_CATEGORY_HIGH is for boosting without user interaction
// (e.g., Window Initialization).
- if (mIsFrameRateBoosting || mInsetsAnimationRunning) {
+ if (mIsFrameRateBoosting || mInsetsAnimationRunning
+ || (mFrameRateCompatibility == FRAME_RATE_COMPATIBILITY_GTE
+ && mPreferredFrameRate > 0)) {
frameRateCategory = FRAME_RATE_CATEGORY_HIGH;
}
try {
if (mLastPreferredFrameRateCategory != frameRateCategory) {
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ String reason = "none";
+ switch (mFrameRateCategoryChangeReason) {
+ case FRAME_RATE_CATEGORY_REASON_INTERMITTENT -> reason = "intermittent";
+ case FRAME_RATE_CATEGORY_REASON_SMALL -> reason = "small";
+ case FRAME_RATE_CATEGORY_REASON_LARGE -> reason = "large";
+ case FRAME_RATE_CATEGORY_REASON_REQUESTED -> reason = "requested";
+ case FRAME_RATE_CATEGORY_REASON_INVALID -> reason = "invalid frame rate";
+ }
+ String sourceView = mFrameRateCategoryView == null ? "No View Given"
+ : mFrameRateCategoryView;
Trace.traceBegin(
Trace.TRACE_TAG_VIEW, "ViewRootImpl#setFrameRateCategory "
- + frameRateCategory);
+ + frameRateCategory + ", reason " + reason + ", "
+ + sourceView);
}
mFrameRateTransaction.setFrameRateCategory(mSurfaceControl,
frameRateCategory, false).applyAsyncUnsafe();
@@ -12383,7 +12399,8 @@
}
private void setPreferredFrameRate(float preferredFrameRate) {
- if (!shouldSetFrameRate()) {
+ if (!shouldSetFrameRate() || (mFrameRateCompatibility == FRAME_RATE_COMPATIBILITY_GTE
+ && preferredFrameRate > 0)) {
return;
}
@@ -12543,6 +12560,14 @@
}
/**
+ * Get the value of mLastPreferredFrameRate
+ */
+ @VisibleForTesting
+ public float getLastPreferredFrameRate() {
+ return mLastPreferredFrameRate;
+ }
+
+ /**
* Returns whether touch boost is currently enabled.
*/
@VisibleForTesting
@@ -12592,10 +12617,12 @@
mWindowlessBackKeyCallback = callback;
}
- void recordViewPercentage(float percentage) {
+ void recordCategory(int category, int reason, View view) {
if (!Trace.isEnabled()) return;
- // Record the largest view of percentage to the display size.
- mLargestChildPercentage = Math.max(percentage, mLargestChildPercentage);
+ if (category > mPreferredFrameRateCategory) {
+ mFrameRateCategoryChangeReason = reason;
+ mFrameRateCategoryView = view.getClass().getSimpleName();
+ }
}
/**
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index f2a3b4c..4214141 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -17,6 +17,7 @@
package android.view;
import static android.view.InsetsController.DEBUG;
+import static android.view.WindowInsetsController.COMPATIBLE_APPEARANCE_FLAGS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
@@ -173,7 +174,9 @@
@Override
public void setSystemBarsAppearance(int appearance, int mask) {
- mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_APPEARANCE_CONTROLLED;
+ if ((mask & COMPATIBLE_APPEARANCE_FLAGS) != 0) {
+ mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_APPEARANCE_CONTROLLED;
+ }
final InsetsFlags insetsFlags = mViewRoot.mWindowAttributes.insetsFlags;
final int newAppearance = (insetsFlags.appearance & ~mask) | (appearance & mask);
if (insetsFlags.appearance != newAppearance) {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 6b427fc..51229a7 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -666,7 +666,7 @@
* Update the status bar appearance.
*/
- void updateStatusBarAppearance(int appearance);
+ void updateSystemBarsAppearance(int appearance);
/**
* Update the navigation bar color to a forced one.
@@ -1038,6 +1038,11 @@
}
/** @hide */
+ public final void setSystemBarAppearance(@WindowInsetsController.Appearance int appearance) {
+ mSystemBarAppearance = appearance;
+ }
+
+ /** @hide */
@WindowInsetsController.Appearance
public final int getSystemBarAppearance() {
return mSystemBarAppearance;
@@ -1046,12 +1051,12 @@
/** @hide */
public final void dispatchOnSystemBarAppearanceChanged(
@WindowInsetsController.Appearance int appearance) {
- mSystemBarAppearance = appearance;
+ setSystemBarAppearance(appearance);
if (mDecorCallback != null) {
mDecorCallback.onSystemBarAppearanceChanged(appearance);
}
if (mWindowControllerCallback != null) {
- mWindowControllerCallback.updateStatusBarAppearance(appearance);
+ mWindowControllerCallback.updateSystemBarsAppearance(appearance);
}
}
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index b7542dc..7601ffa 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -94,15 +94,36 @@
int APPEARANCE_LIGHT_CAPTION_BARS = 1 << 8;
/**
+ * Same as {@link #APPEARANCE_LIGHT_NAVIGATION_BARS} but set by the system. The system will
+ * respect {@link #APPEARANCE_LIGHT_NAVIGATION_BARS} when this is cleared.
+ * @hide
+ */
+ int APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS = 1 << 9;
+
+ /**
+ * Appearance flags that can be implied from system UI flags.
+ * @hide
+ */
+ int COMPATIBLE_APPEARANCE_FLAGS = APPEARANCE_LOW_PROFILE_BARS
+ | APPEARANCE_LIGHT_STATUS_BARS
+ | APPEARANCE_LIGHT_NAVIGATION_BARS;
+
+ /**
* Determines the appearance of system bars.
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, value = {APPEARANCE_OPAQUE_STATUS_BARS, APPEARANCE_OPAQUE_NAVIGATION_BARS,
- APPEARANCE_LOW_PROFILE_BARS, APPEARANCE_LIGHT_STATUS_BARS,
- APPEARANCE_LIGHT_NAVIGATION_BARS, APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS,
+ @IntDef(flag = true, value = {
+ APPEARANCE_OPAQUE_STATUS_BARS,
+ APPEARANCE_OPAQUE_NAVIGATION_BARS,
+ APPEARANCE_LOW_PROFILE_BARS,
+ APPEARANCE_LIGHT_STATUS_BARS,
+ APPEARANCE_LIGHT_NAVIGATION_BARS,
+ APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS,
APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS,
- APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND, APPEARANCE_LIGHT_CAPTION_BARS})
+ APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND,
+ APPEARANCE_LIGHT_CAPTION_BARS,
+ APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS})
@interface Appearance {
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index cf6b9e5..3ee8307 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1480,20 +1480,29 @@
if (infos.size() == 0) {
throw new IllegalArgumentException("No VirtualViewInfo found");
}
+ boolean isCredmanRequested = false;
if (shouldSuppressDialogsForCredman(view)
&& mIsFillAndSaveDialogDisabledForCredentialManager) {
- if (sDebug) {
- Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:"
- + view.getAutofillId().toString());
- }
mScreenHasCredmanField = true;
- return;
+ if (isCredmanRequested(view)) {
+ if (sDebug) {
+ Log.d(TAG, "Prefetching fill response for credMan: "
+ + view.getAutofillId().toString());
+ }
+ isCredmanRequested = true;
+ } else {
+ if (sDebug) {
+ Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:"
+ + view.getAutofillId().toString());
+ }
+ return;
+ }
}
for (int i = 0; i < infos.size(); i++) {
final VirtualViewFillInfo info = infos.valueAt(i);
final int virtualId = infos.keyAt(i);
notifyViewReadyInner(getAutofillId(view, virtualId),
- (info == null) ? null : info.getAutofillHints());
+ (info == null) ? null : info.getAutofillHints(), isCredmanRequested);
}
}
@@ -1505,19 +1514,29 @@
* @hide
*/
public void notifyViewEnteredForFillDialog(View v) {
+ boolean isCredmanRequested = false;
if (shouldSuppressDialogsForCredman(v)
&& mIsFillAndSaveDialogDisabledForCredentialManager) {
- if (sDebug) {
- Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:"
- + v.getAutofillId());
- }
mScreenHasCredmanField = true;
- return;
+ if (isCredmanRequested(v)) {
+ if (sDebug) {
+ Log.d(TAG, "Prefetching fill response for credMan: "
+ + v.getAutofillId().toString());
+ }
+ isCredmanRequested = true;
+ } else {
+ if (sDebug) {
+ Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:"
+ + v.getAutofillId().toString());
+ }
+ return;
+ }
}
- notifyViewReadyInner(v.getAutofillId(), v.getAutofillHints());
+ notifyViewReadyInner(v.getAutofillId(), v.getAutofillHints(), isCredmanRequested);
}
- private void notifyViewReadyInner(AutofillId id, @Nullable String[] autofillHints) {
+ private void notifyViewReadyInner(AutofillId id, @Nullable String[] autofillHints,
+ boolean isCredmanRequested) {
if (sDebug) {
Log.d(TAG, "notifyViewReadyInner:" + id);
}
@@ -1592,6 +1611,12 @@
}
int flags = FLAG_SUPPORTS_FILL_DIALOG;
flags |= FLAG_VIEW_NOT_FOCUSED;
+ if (isCredmanRequested) {
+ if (sDebug) {
+ Log.d(TAG, "Pre fill request is triggered for credMan");
+ }
+ flags |= FLAG_VIEW_REQUESTS_CREDMAN_SERVICE;
+ }
synchronized (mLock) {
// To match the id of the IME served view, used AutofillId.NO_AUTOFILL_ID on prefill
// request, because IME will reset the id of IME served view to 0 when activity
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index c76c7a4..e5658e6 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -36,6 +36,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
@@ -424,9 +425,12 @@
layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
| FLAG_NOT_FOCUSABLE
| FLAG_NOT_TOUCHABLE;
- // Setting as trusted overlay to let touches pass through. This is safe because this
- // window is controlled by the system.
- layoutParams.privateFlags = (windowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS)
+ layoutParams.privateFlags =
+ (windowPrivateFlags
+ & (PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS
+ | PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED))
+ // Setting as trusted overlay to let touches pass through. This is safe because this
+ // window is controlled by the system.
| PRIVATE_FLAG_TRUSTED_OVERLAY;
layoutParams.token = token;
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
@@ -475,14 +479,16 @@
mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS,
semiTransparent, taskDescription.getStatusBarColor(), appearance,
APPEARANCE_LIGHT_STATUS_BARS,
- taskDescription.getEnsureStatusBarContrastWhenTransparent());
+ taskDescription.getEnsureStatusBarContrastWhenTransparent(),
+ false /* movesBarColorToScrim */);
mNavigationBarColor = DecorView.calculateBarColor(windowFlags,
FLAG_TRANSLUCENT_NAVIGATION, semiTransparent,
taskDescription.getNavigationBarColor(), appearance,
APPEARANCE_LIGHT_NAVIGATION_BARS,
taskDescription.getEnsureNavigationBarContrastWhenTransparent()
&& context.getResources().getBoolean(
- R.bool.config_navBarNeedsScrim));
+ R.bool.config_navBarNeedsScrim),
+ (windowPrivateFlags & PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED) != 0);
mStatusBarPaint.setColor(mStatusBarColor);
mNavigationBarPaint.setColor(mNavigationBarColor);
mRequestedVisibleTypes = requestedVisibleTypes;
diff --git a/core/java/com/android/internal/inputmethod/EditableInputConnection.java b/core/java/com/android/internal/inputmethod/EditableInputConnection.java
index 3020d77..0e4f04f 100644
--- a/core/java/com/android/internal/inputmethod/EditableInputConnection.java
+++ b/core/java/com/android/internal/inputmethod/EditableInputConnection.java
@@ -17,8 +17,6 @@
package com.android.internal.inputmethod;
import static android.view.inputmethod.InputConnectionProto.CURSOR_CAPS_MODE;
-import static android.view.inputmethod.InputConnectionProto.EDITABLE_TEXT;
-import static android.view.inputmethod.InputConnectionProto.SELECTED_TEXT;
import static android.view.inputmethod.InputConnectionProto.SELECTED_TEXT_END;
import static android.view.inputmethod.InputConnectionProto.SELECTED_TEXT_START;
@@ -335,16 +333,6 @@
@Override
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
- CharSequence editableText = mTextView.getText();
- CharSequence selectedText = getSelectedText(0 /* flags */);
- if (InputConnectionProtoDumper.DUMP_TEXT) {
- if (editableText != null) {
- proto.write(EDITABLE_TEXT, editableText.toString());
- }
- if (selectedText != null) {
- proto.write(SELECTED_TEXT, selectedText.toString());
- }
- }
final Editable content = getEditable();
if (content != null) {
int start = Selection.getSelectionStart(content);
diff --git a/core/java/com/android/internal/inputmethod/InputConnectionProtoDumper.java b/core/java/com/android/internal/inputmethod/InputConnectionProtoDumper.java
index 7172d0a..31cf758 100644
--- a/core/java/com/android/internal/inputmethod/InputConnectionProtoDumper.java
+++ b/core/java/com/android/internal/inputmethod/InputConnectionProtoDumper.java
@@ -44,7 +44,6 @@
*/
public final class InputConnectionProtoDumper {
static final String TAG = "InputConnectionProtoDumper";
- public static final boolean DUMP_TEXT = false;
private InputConnectionProtoDumper() {}
@@ -67,11 +66,6 @@
final long token = proto.start(GET_TEXT_AFTER_CURSOR);
proto.write(GetTextAfterCursor.LENGTH, length);
proto.write(GetTextAfterCursor.FLAGS, flags);
- if (result == null) {
- proto.write(GetTextAfterCursor.RESULT, "null result");
- } else if (DUMP_TEXT) {
- proto.write(GetTextAfterCursor.RESULT, result.toString());
- }
proto.end(token);
return proto.getBytes();
}
@@ -95,11 +89,6 @@
final long token = proto.start(GET_TEXT_BEFORE_CURSOR);
proto.write(GetTextBeforeCursor.LENGTH, length);
proto.write(GetTextBeforeCursor.FLAGS, flags);
- if (result == null) {
- proto.write(GetTextBeforeCursor.RESULT, "null result");
- } else if (DUMP_TEXT) {
- proto.write(GetTextBeforeCursor.RESULT, result.toString());
- }
proto.end(token);
return proto.getBytes();
}
@@ -122,11 +111,6 @@
ProtoOutputStream proto = new ProtoOutputStream();
final long token = proto.start(GET_SELECTED_TEXT);
proto.write(GetSelectedText.FLAGS, flags);
- if (result == null) {
- proto.write(GetSelectedText.RESULT, "null result");
- } else if (DUMP_TEXT) {
- proto.write(GetSelectedText.RESULT, result.toString());
- }
proto.end(token);
return proto.getBytes();
}
@@ -155,13 +139,8 @@
proto.write(GetSurroundingText.BEFORE_LENGTH, beforeLength);
proto.write(GetSurroundingText.AFTER_LENGTH, afterLength);
proto.write(GetSurroundingText.FLAGS, flags);
- if (result == null) {
+ if (result != null) {
final long token_result = proto.start(GetSurroundingText.RESULT);
- proto.write(GetSurroundingText.SurroundingText.TEXT, "null result");
- proto.end(token_result);
- } else if (DUMP_TEXT) {
- final long token_result = proto.start(GetSurroundingText.RESULT);
- proto.write(GetSurroundingText.SurroundingText.TEXT, result.getText().toString());
proto.write(GetSurroundingText.SurroundingText.SELECTION_START,
result.getSelectionStart());
proto.write(GetSurroundingText.SurroundingText.SELECTION_END,
@@ -188,9 +167,7 @@
ProtoOutputStream proto = new ProtoOutputStream();
final long token = proto.start(GET_CURSOR_CAPS_MODE);
proto.write(GetCursorCapsMode.REQ_MODES, reqModes);
- if (DUMP_TEXT) {
- proto.write(GetCursorCapsMode.RESULT, result);
- }
+ proto.write(GetCursorCapsMode.RESULT, result);
proto.end(token);
return proto.getBytes();
}
@@ -223,11 +200,6 @@
proto.write(GetExtractedText.ExtractedTextRequest.HINT_MAX_CHARS, request.hintMaxChars);
proto.end(token_request);
proto.write(GetExtractedText.FLAGS, flags);
- if (result == null) {
- proto.write(GetExtractedText.RESULT, "null result");
- } else if (DUMP_TEXT) {
- proto.write(GetExtractedText.RESULT, result.text.toString());
- }
proto.end(token);
return proto.getBytes();
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 8566263..0f1f7e9 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -29,6 +29,7 @@
import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
import static android.view.Window.DECOR_CAPTION_SHADE_DARK;
import static android.view.Window.DECOR_CAPTION_SHADE_LIGHT;
+import static android.view.WindowInsetsController.APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
@@ -136,6 +137,8 @@
private static final int SCRIM_LIGHT = 0xe6ffffff; // 90% white
+ private static final int SCRIM_ALPHA = 0xcc0000; // 80% alpha
+
public static final ColorViewAttributes STATUS_BAR_COLOR_VIEW_ATTRIBUTES =
new ColorViewAttributes(FLAG_TRANSLUCENT_STATUS,
Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
@@ -989,6 +992,16 @@
if (mOriginalBackgroundDrawable != drawable) {
mOriginalBackgroundDrawable = drawable;
updateBackgroundDrawable();
+ if (mWindow.mEdgeToEdgeEnforced && !mWindow.mNavigationBarColorSpecified
+ && drawable instanceof ColorDrawable) {
+ final int color = ((ColorDrawable) drawable).getColor();
+ final boolean lightBar = Color.valueOf(color).luminance() > 0.5f;
+ getWindowInsetsController().setSystemBarsAppearance(
+ lightBar ? APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS : 0,
+ APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS);
+ mWindow.mNavigationBarColor = color;
+ updateColorViews(null /* insets */, false /* animate */);
+ }
if (drawable != null) {
mResizingBackgroundDrawable = enforceNonTranslucentBackground(drawable,
mWindow.isTranslucent() || mWindow.isShowingWallpaper());
@@ -1407,7 +1420,8 @@
mSemiTransparentBarColor, mWindow.mStatusBarColor,
appearance, APPEARANCE_LIGHT_STATUS_BARS,
mWindow.mEnsureStatusBarContrastWhenTransparent
- && (mLastSuppressScrimTypes & WindowInsets.Type.statusBars()) == 0);
+ && (mLastSuppressScrimTypes & WindowInsets.Type.statusBars()) == 0,
+ false /* movesBarColorToScrim */);
}
private int calculateNavigationBarColor(@Appearance int appearance) {
@@ -1415,22 +1429,29 @@
mSemiTransparentBarColor, mWindow.mNavigationBarColor,
appearance, APPEARANCE_LIGHT_NAVIGATION_BARS,
mWindow.mEnsureNavigationBarContrastWhenTransparent
- && (mLastSuppressScrimTypes & WindowInsets.Type.navigationBars()) == 0);
+ && (mLastSuppressScrimTypes & WindowInsets.Type.navigationBars()) == 0,
+ mWindow.mEdgeToEdgeEnforced);
}
public static int calculateBarColor(int flags, int translucentFlag, int semiTransparentBarColor,
int barColor, @Appearance int appearance, @Appearance int lightAppearanceFlag,
- boolean scrimTransparent) {
+ boolean ensuresContrast, boolean movesBarColorToScrim) {
if ((flags & translucentFlag) != 0) {
return semiTransparentBarColor;
} else if ((flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
return Color.BLACK;
- } else if (scrimTransparent && Color.alpha(barColor) == 0) {
- boolean light = (appearance & lightAppearanceFlag) != 0;
- return light ? SCRIM_LIGHT : semiTransparentBarColor;
- } else {
- return barColor;
+ } else if (ensuresContrast) {
+ final int alpha = Color.alpha(barColor);
+ if (alpha == 0) {
+ boolean light = (appearance & lightAppearanceFlag) != 0;
+ return light ? SCRIM_LIGHT : semiTransparentBarColor;
+ } else if (movesBarColorToScrim) {
+ return (barColor & 0xffffff) | SCRIM_ALPHA;
+ }
+ } else if (movesBarColorToScrim) {
+ return Color.TRANSPARENT;
}
+ return barColor;
}
private int getCurrentColor(ColorViewState state) {
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 0dd01e4..9868ceb 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -21,6 +21,7 @@
import static android.view.View.SYSTEM_UI_LAYOUT_FLAGS;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowInsetsController.APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
@@ -298,6 +299,7 @@
int mStatusBarColor = Color.TRANSPARENT;
int mNavigationBarColor = Color.TRANSPARENT;
int mNavigationBarDividerColor = Color.TRANSPARENT;
+ boolean mNavigationBarColorSpecified = false;
private boolean mForcedStatusBarColor = false;
private boolean mForcedNavigationBarColor = false;
@@ -370,7 +372,7 @@
boolean mDecorFitsSystemWindows = true;
- private boolean mEdgeToEdgeEnforced;
+ boolean mEdgeToEdgeEnforced;
private final ProxyOnBackInvokedDispatcher mProxyOnBackInvokedDispatcher;
@@ -406,6 +408,7 @@
mElevation = preservedWindow.getElevation();
mLoadElevation = false;
mForceDecorInstall = true;
+ setSystemBarAppearance(preservedWindow.getSystemBarAppearance());
// If we're preserving window, carry over the app token from the preserved
// window, as we'll be skipping the addView in handleResumeActivity(), and
// the token will not be updated as for a new window.
@@ -2577,21 +2580,27 @@
if (!mForcedStatusBarColor && !mEdgeToEdgeEnforced) {
mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, Color.BLACK);
}
- if (!mForcedNavigationBarColor && !mEdgeToEdgeEnforced) {
+ if (!mForcedNavigationBarColor) {
final int navBarCompatibleColor = context.getColor(R.color.navigation_bar_compatible);
final int navBarDefaultColor = context.getColor(R.color.navigation_bar_default);
final int navBarColor = a.getColor(R.styleable.Window_navigationBarColor,
navBarDefaultColor);
+ final boolean navigationBarColorSpecified = navBarColor != navBarDefaultColor;
mNavigationBarColor =
- navBarColor == navBarDefaultColor
+ !navigationBarColorSpecified
+ && !mEdgeToEdgeEnforced
&& !context.getResources().getBoolean(
R.bool.config_navBarDefaultTransparent)
? navBarCompatibleColor
: navBarColor;
- mNavigationBarDividerColor = a.getColor(R.styleable.Window_navigationBarDividerColor,
- Color.TRANSPARENT);
+ mNavigationBarColorSpecified |= navigationBarColorSpecified;
+
+ if (!mEdgeToEdgeEnforced) {
+ mNavigationBarDividerColor = a.getColor(
+ R.styleable.Window_navigationBarDividerColor, Color.TRANSPARENT);
+ }
}
if (!targetPreQ) {
mEnsureStatusBarContrastWhenTransparent = a.getBoolean(
@@ -3941,17 +3950,20 @@
@Override
public void setNavigationBarColor(int color) {
- if (mEdgeToEdgeEnforced) {
- return;
- }
if (mNavigationBarColor == color && mForcedNavigationBarColor) {
return;
}
mNavigationBarColor = color;
mForcedNavigationBarColor = true;
+ mNavigationBarColorSpecified = true;
if (mDecor != null) {
+ mDecor.getWindowInsetsController().setSystemBarsAppearance(
+ 0, APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS);
mDecor.updateColorViews(null, false /* animate */);
}
+ if (mEdgeToEdgeEnforced) {
+ return;
+ }
final WindowControllerCallback callback = getWindowControllerCallback();
if (callback != null) {
getWindowControllerCallback().updateNavigationBarColor(color);
diff --git a/core/jni/android_text_Hyphenator.cpp b/core/jni/android_text_Hyphenator.cpp
index b6bf617..7c976b7 100644
--- a/core/jni/android_text_Hyphenator.cpp
+++ b/core/jni/android_text_Hyphenator.cpp
@@ -36,41 +36,43 @@
return SYSTEM_HYPHENATOR_PREFIX + lowerLocale + SYSTEM_HYPHENATOR_SUFFIX;
}
-static const uint8_t* mmapPatternFile(const std::string& locale) {
+static std::pair<const uint8_t*, uint32_t> mmapPatternFile(const std::string& locale) {
const std::string hyFilePath = buildFileName(locale);
const int fd = open(hyFilePath.c_str(), O_RDONLY | O_CLOEXEC);
if (fd == -1) {
- return nullptr; // Open failed.
+ return std::make_pair(nullptr, 0); // Open failed.
}
struct stat st = {};
if (fstat(fd, &st) == -1) { // Unlikely to happen.
close(fd);
- return nullptr;
+ return std::make_pair(nullptr, 0);
}
void* ptr = mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, fd, 0 /* offset */);
close(fd);
if (ptr == MAP_FAILED) {
- return nullptr;
+ return std::make_pair(nullptr, 0);
}
- return reinterpret_cast<const uint8_t*>(ptr);
+ return std::make_pair(reinterpret_cast<const uint8_t*>(ptr), st.st_size);
}
static void addHyphenatorWithoutPatternFile(const std::string& locale, int minPrefix,
int minSuffix) {
- minikin::addHyphenator(locale, minikin::Hyphenator::loadBinary(
- nullptr, minPrefix, minSuffix, locale));
+ minikin::addHyphenator(locale,
+ minikin::Hyphenator::loadBinary(nullptr, 0, minPrefix, minSuffix,
+ locale));
}
static void addHyphenator(const std::string& locale, int minPrefix, int minSuffix) {
- const uint8_t* ptr = mmapPatternFile(locale);
+ auto [ptr, size] = mmapPatternFile(locale);
if (ptr == nullptr) {
ALOGE("Unable to find pattern file or unable to map it for %s", locale.c_str());
return;
}
- minikin::addHyphenator(locale, minikin::Hyphenator::loadBinary(
- ptr, minPrefix, minSuffix, locale));
+ minikin::addHyphenator(locale,
+ minikin::Hyphenator::loadBinary(ptr, size, minPrefix, minSuffix,
+ locale));
}
static void addHyphenatorAlias(const std::string& from, const std::string& to) {
diff --git a/core/jni/android_tracing_PerfettoDataSource.cpp b/core/jni/android_tracing_PerfettoDataSource.cpp
index 16c3ca9..1eff5ce 100644
--- a/core/jni/android_tracing_PerfettoDataSource.cpp
+++ b/core/jni/android_tracing_PerfettoDataSource.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "Perfetto"
+#define LOG_TAG "NativeJavaPerfettoDs"
#include "android_tracing_PerfettoDataSource.h"
@@ -166,16 +166,25 @@
void PerfettoDataSource::trace(JNIEnv* env, jobject traceFunction) {
PERFETTO_DS_TRACE(dataSource, ctx) {
+ ALOG(LOG_DEBUG, LOG_TAG, "\tin native trace callback function %p", this);
TlsState* tls_state =
reinterpret_cast<TlsState*>(PerfettoDsGetCustomTls(&dataSource, &ctx));
IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(
PerfettoDsGetIncrementalState(&dataSource, &ctx));
+ ALOG(LOG_DEBUG, LOG_TAG, "\t tls_state = %p", tls_state);
+ ALOG(LOG_DEBUG, LOG_TAG, "\t incr_state = %p", incr_state);
+
+ ALOG(LOG_DEBUG, LOG_TAG, "\t tls_state->jobj = %p", tls_state->jobj);
+ ALOG(LOG_DEBUG, LOG_TAG, "\t incr_state->jobj = %p", incr_state->jobj);
+
ScopedLocalRef<jobject> jCtx(env,
env->NewObject(gTracingContextClassInfo.clazz,
gTracingContextClassInfo.init, &ctx,
tls_state->jobj, incr_state->jobj));
+ ALOG(LOG_DEBUG, LOG_TAG, "\t jCtx = %p", jCtx.get());
+
jclass objclass = env->GetObjectClass(traceFunction);
jmethodID method =
env->GetMethodID(objclass, "trace", "(Landroid/tracing/perfetto/TracingContext;)V");
@@ -209,7 +218,9 @@
jlong nativeCreate(JNIEnv* env, jclass clazz, jobject javaDataSource, jstring name) {
const char* nativeString = env->GetStringUTFChars(name, 0);
+ ALOG(LOG_DEBUG, LOG_TAG, "nativeCreate(%p, %s)", javaDataSource, nativeString);
PerfettoDataSource* dataSource = new PerfettoDataSource(env, javaDataSource, nativeString);
+ ALOG(LOG_DEBUG, LOG_TAG, "\tdatasource* = %p", dataSource);
env->ReleaseStringUTFChars(name, nativeString);
dataSource->incStrong((void*)nativeCreate);
@@ -218,33 +229,39 @@
}
void nativeDestroy(void* ptr) {
+ ALOG(LOG_DEBUG, LOG_TAG, "nativeCreate(%p)", ptr);
PerfettoDataSource* dataSource = reinterpret_cast<PerfettoDataSource*>(ptr);
dataSource->decStrong((void*)nativeCreate);
}
static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
+ ALOG(LOG_DEBUG, LOG_TAG, "nativeGetFinalizer()");
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&nativeDestroy));
}
void nativeTrace(JNIEnv* env, jclass clazz, jlong dataSourcePtr, jobject traceFunctionInterface) {
+ ALOG(LOG_DEBUG, LOG_TAG, "nativeTrace(%p)", (void*)dataSourcePtr);
sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
datasource->trace(env, traceFunctionInterface);
}
void nativeFlush(JNIEnv* env, jclass clazz, jobject jCtx, jlong ctxPtr) {
+ ALOG(LOG_DEBUG, LOG_TAG, "nativeFlush(%p, %p)", jCtx, (void*)ctxPtr);
auto* ctx = reinterpret_cast<struct PerfettoDsTracerIterator*>(ctxPtr);
traceAllPendingPackets(env, jCtx, ctx);
PerfettoDsTracerFlush(ctx, nullptr, nullptr);
}
void nativeFlushAll(JNIEnv* env, jclass clazz, jlong ptr) {
+ ALOG(LOG_DEBUG, LOG_TAG, "nativeFlushAll(%p)", (void*)ptr);
sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(ptr);
datasource->flushAll();
}
void nativeRegisterDataSource(JNIEnv* env, jclass clazz, jlong datasource_ptr,
int buffer_exhausted_policy) {
+ ALOG(LOG_DEBUG, LOG_TAG, "nativeRegisterDataSource(%p)", (void*)datasource_ptr);
sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(datasource_ptr);
struct PerfettoDsParams params = PerfettoDsParamsDefault();
@@ -267,6 +284,9 @@
auto* datasource_instance =
new PerfettoDataSourceInstance(env, java_data_source_instance.get(), inst_id);
+ ALOG(LOG_DEBUG, LOG_TAG, "on_setup_cb ds=%p, ds_instance=%p", datasource,
+ datasource_instance);
+
return static_cast<void*>(datasource_instance);
};
@@ -280,6 +300,8 @@
auto* tls_state = new TlsState(java_tls_state);
+ ALOG(LOG_DEBUG, LOG_TAG, "on_create_tls_cb ds=%p, tsl_state=%p", datasource, tls_state);
+
return static_cast<void*>(tls_state);
};
@@ -287,6 +309,9 @@
JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
TlsState* tls_state = reinterpret_cast<TlsState*>(ptr);
+
+ ALOG(LOG_DEBUG, LOG_TAG, "on_delete_tls_cb %p", tls_state);
+
env->DeleteGlobalRef(tls_state->jobj);
delete tls_state;
};
@@ -299,6 +324,9 @@
jobject java_incr_state = datasource->createIncrementalStateGlobalRef(env, inst_id);
auto* incr_state = new IncrementalState(java_incr_state);
+
+ ALOG(LOG_DEBUG, LOG_TAG, "on_create_incr_cb ds=%p, incr_state=%p", datasource, incr_state);
+
return static_cast<void*>(incr_state);
};
@@ -306,6 +334,9 @@
JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
IncrementalState* incr_state = reinterpret_cast<IncrementalState*>(ptr);
+
+ ALOG(LOG_DEBUG, LOG_TAG, "on_delete_incr_cb incr_state=%p", incr_state);
+
env->DeleteGlobalRef(incr_state->jobj);
delete incr_state;
};
@@ -315,6 +346,9 @@
JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
+
+ ALOG(LOG_DEBUG, LOG_TAG, "on_start_cb ds_instance=%p", datasource_instance);
+
datasource_instance->onStart(env);
};
@@ -323,6 +357,9 @@
JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
+
+ ALOG(LOG_DEBUG, LOG_TAG, "on_flush_cb ds_instance=%p", datasource_instance);
+
datasource_instance->onFlush(env);
};
@@ -331,12 +368,18 @@
JNIEnv* env = GetOrAttachJNIEnvironment(gVm, JNI_VERSION_1_6);
auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
+
+ ALOG(LOG_DEBUG, LOG_TAG, "on_stop_cb ds_instance=%p", datasource_instance);
+
datasource_instance->onStop(env);
};
params.on_destroy_cb = [](struct PerfettoDsImpl* ds_impl, void* user_arg,
void* inst_ctx) -> void {
auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(inst_ctx);
+
+ ALOG(LOG_DEBUG, LOG_TAG, "on_destroy_cb ds_instance=%p", datasource_instance);
+
delete datasource_instance;
};
@@ -345,20 +388,28 @@
jobject nativeGetPerfettoInstanceLocked(JNIEnv* env, jclass clazz, jlong dataSourcePtr,
PerfettoDsInstanceIndex instance_idx) {
+ ALOG(LOG_DEBUG, LOG_TAG, "nativeGetPerfettoInstanceLocked ds=%p, idx=%d", (void*)dataSourcePtr,
+ instance_idx);
sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
auto* datasource_instance = static_cast<PerfettoDataSourceInstance*>(
PerfettoDsImplGetInstanceLocked(datasource->dataSource.impl, instance_idx));
if (datasource_instance == nullptr) {
// datasource instance doesn't exist
+ ALOG(LOG_WARN, LOG_TAG,
+ "DS instance invalid!! nativeGetPerfettoInstanceLocked returning NULL");
return nullptr;
}
+ ALOG(LOG_DEBUG, LOG_TAG, "\tnativeGetPerfettoInstanceLocked got lock ds=%p, idx=%d",
+ (void*)dataSourcePtr, instance_idx);
return datasource_instance->GetJavaDataSourceInstance();
}
void nativeReleasePerfettoInstanceLocked(JNIEnv* env, jclass clazz, jlong dataSourcePtr,
PerfettoDsInstanceIndex instance_idx) {
+ ALOG(LOG_DEBUG, LOG_TAG, "nativeReleasePerfettoInstanceLocked got lock ds=%p, idx=%d",
+ (void*)dataSourcePtr, instance_idx);
sp<PerfettoDataSource> datasource = reinterpret_cast<PerfettoDataSource*>(dataSourcePtr);
PerfettoDsImplReleaseInstanceLocked(datasource->dataSource.impl, instance_idx);
}
diff --git a/core/jni/android_tracing_PerfettoDataSource.h b/core/jni/android_tracing_PerfettoDataSource.h
index 61a7654..906d9f5 100644
--- a/core/jni/android_tracing_PerfettoDataSource.h
+++ b/core/jni/android_tracing_PerfettoDataSource.h
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#define LOG_TAG "Perfetto"
-
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
#include <nativehelper/JNIHelp.h>
diff --git a/core/jni/android_tracing_PerfettoDataSourceInstance.h b/core/jni/android_tracing_PerfettoDataSourceInstance.h
index ebb5259..be71cbb 100644
--- a/core/jni/android_tracing_PerfettoDataSourceInstance.h
+++ b/core/jni/android_tracing_PerfettoDataSourceInstance.h
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#define LOG_TAG "Perfetto"
-
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
#include <nativehelper/JNIHelp.h>
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 75cfba0..d31baf3 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -144,6 +144,7 @@
}
repeated BroadcastSummary historical_broadcasts_summary = 6;
repeated BroadcastRecordProto pending_broadcasts = 7;
+ repeated BroadcastRecordProto frozen_broadcasts = 8;
}
message MemInfoDumpProto {
diff --git a/core/proto/android/view/inputmethod/inputconnection.proto b/core/proto/android/view/inputmethod/inputconnection.proto
index d1f257f..ff6871d 100644
--- a/core/proto/android/view/inputmethod/inputconnection.proto
+++ b/core/proto/android/view/inputmethod/inputconnection.proto
@@ -16,8 +16,6 @@
syntax = "proto2";
-import "frameworks/base/core/proto/android/privacy.proto";
-
package android.view.inputmethod;
option java_multiple_files = true;
@@ -26,8 +24,8 @@
* Represents a {@link android.view.inputmethod.InputConnection} object.
*/
message InputConnectionProto {
- optional string editable_text = 1 [(.android.privacy).dest = DEST_LOCAL];
- optional string selected_text = 2 [(.android.privacy).dest = DEST_LOCAL];
+ reserved 1; // string editable_text
+ reserved 2; // string selected_text
optional int32 selected_text_start = 3;
optional int32 selected_text_end = 4;
optional int32 cursor_caps_mode = 5;
@@ -50,18 +48,18 @@
message GetTextBeforeCursor {
optional int32 length = 1;
optional int32 flags = 2;
- optional string result = 3 [(.android.privacy).dest = DEST_LOCAL];
+ reserved 3; // string result
}
message GetTextAfterCursor {
optional int32 length = 1;
optional int32 flags = 2;
- optional string result = 3 [(.android.privacy).dest = DEST_LOCAL];
+ reserved 3; // string result = 3
}
message GetSelectedText {
optional int32 flags = 1;
- optional string result = 2 [(.android.privacy).dest = DEST_LOCAL];
+ reserved 2; // string result = 2
}
message GetSurroundingText {
@@ -71,7 +69,7 @@
optional SurroundingText result = 4;
message SurroundingText {
- optional string text = 1 [(.android.privacy).dest = DEST_LOCAL];
+ reserved 1; // string text = 1
optional int32 selection_start = 2;
optional int32 selection_end = 3;
optional int32 offset = 4;
@@ -86,7 +84,7 @@
message GetExtractedText {
optional ExtractedTextRequest request = 1;
optional int32 flags = 2;
- optional string result = 3 [(.android.privacy).dest = DEST_LOCAL];
+ reserved 3; // string result = 3
message ExtractedTextRequest {
optional int32 token = 1;
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index eafaf32..983775e 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -186,8 +186,8 @@
<string name="contentServiceSyncNotificationTitle" msgid="5766411446676388623">"Αδυναμία συγχρονισμού"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"Επιχειρήθηκε η διαγραφή πάρα πολλών <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="5557552311566179924">"Ο αποθηκευτικός χώρος του tablet είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
- <string name="low_memory" product="watch" msgid="3479447988234030194">"Ο αποθηκευτικός χώρος παρακολούθησης είναι πλήρης! Διαγράψτε μερικά αρχεία για να απελευθερώσετε χώρο."</string>
- <string name="low_memory" product="tv" msgid="6663680413790323318">"Ο αποθηκευτικός χώρος της συσκευής Android TV είναι πλήρης. Διαγράψτε μερικά αρχεία για να απελευθερώσετε χώρο."</string>
+ <string name="low_memory" product="watch" msgid="3479447988234030194">"Ο αποθηκευτικός χώρος παρακολούθησης είναι πλήρης! Διαγράψτε μερικά αρχεία για να αποδεσμεύσετε χώρο."</string>
+ <string name="low_memory" product="tv" msgid="6663680413790323318">"Ο αποθηκευτικός χώρος της συσκευής Android TV είναι πλήρης. Διαγράψτε μερικά αρχεία για να αποδεσμεύσετε χώρο."</string>
<string name="low_memory" product="default" msgid="2539532364144025569">"Ο αποθηκευτικός χώρος του τηλεφώνου είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
<string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Η αρχή έκδοσης πιστοποιητικών εγκαταστάθηκε}other{Οι αρχές έκδοσης πιστοποιητικών εγκαταστάθηκαν}}"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Από ένα άγνωστο τρίτο μέρος"</string>
diff --git a/core/res/res/values-fr-feminine/strings.xml b/core/res/res/values-fr-feminine/strings.xml
new file mode 100644
index 0000000..2ad85d1
--- /dev/null
+++ b/core/res/res/values-fr-feminine/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonnée"</string>
+</resources>
diff --git a/core/res/res/values-fr-masculine/strings.xml b/core/res/res/values-fr-masculine/strings.xml
new file mode 100644
index 0000000..744ef2b
--- /dev/null
+++ b/core/res/res/values-fr-masculine/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné"</string>
+</resources>
diff --git a/core/res/res/values-fr-neuter/strings.xml b/core/res/res/values-fr-neuter/strings.xml
new file mode 100644
index 0000000..b4f4cc7
--- /dev/null
+++ b/core/res/res/values-fr-neuter/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné·e"</string>
+</resources>
diff --git a/core/res/res/values-mcc334-mnc020-fr-feminine/strings.xml b/core/res/res/values-mcc334-mnc020-fr-feminine/strings.xml
new file mode 100644
index 0000000..ba278df
--- /dev/null
+++ b/core/res/res/values-mcc334-mnc020-fr-feminine/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2020, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Vous n\'êtes pas autorisée à avoir plusieurs connexions PDN pour un APN donné -55-"</string>
+</resources>
diff --git a/core/res/res/values-mcc334-mnc020-fr-masculine/strings.xml b/core/res/res/values-mcc334-mnc020-fr-masculine/strings.xml
new file mode 100644
index 0000000..8227cd6
--- /dev/null
+++ b/core/res/res/values-mcc334-mnc020-fr-masculine/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2020, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Vous n\'êtes pas autorisé à avoir plusieurs connexions PDN pour un APN donné -55-"</string>
+</resources>
diff --git a/core/res/res/values-mcc334-mnc020-fr-neuter/strings.xml b/core/res/res/values-mcc334-mnc020-fr-neuter/strings.xml
new file mode 100644
index 0000000..110d962
--- /dev/null
+++ b/core/res/res/values-mcc334-mnc020-fr-neuter/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2020, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Vous n\'êtes pas autorisé·e à avoir plusieurs connexions PDN pour un APN donné -55-"</string>
+</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 2648a38..a23bcfa 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -706,8 +706,8 @@
<string name="face_acquired_too_far" msgid="2922278214231064859">"ഫോൺ അടുത്തേക്ക് നീക്കുക"</string>
<string name="face_acquired_too_high" msgid="8278815780046368576">"ഫോൺ മുകളിലേക്ക് ഉയർത്തുക"</string>
<string name="face_acquired_too_low" msgid="4075391872960840081">"ഫോൺ കൂടുതൽ താഴേക്ക് നീക്കുക"</string>
- <string name="face_acquired_too_right" msgid="6245286514593540859">"ഫോൺ നിങ്ങളുടെ ഇടതുവശത്തേക്ക് നീക്കുക"</string>
- <string name="face_acquired_too_left" msgid="9201762240918405486">"ഫോൺ നിങ്ങളുടെ വലതുവശത്തേക്ക് നീക്കുക"</string>
+ <string name="face_acquired_too_right" msgid="6245286514593540859">"ഫോൺ ഇടതുവശത്തേക്ക് നീക്കുക"</string>
+ <string name="face_acquired_too_left" msgid="9201762240918405486">"ഫോൺ വലതുവശത്തേക്ക് നീക്കുക"</string>
<string name="face_acquired_poor_gaze" msgid="4427153558773628020">"നിങ്ങളുടെ ഉപകരണത്തിന് നേരെ കൂടുതൽ നന്നായി നോക്കുക."</string>
<string name="face_acquired_not_detected" msgid="1057966913397548150">"മുഖം കാണുന്നില്ല. ഫോൺ കണ്ണിന് നേരെ പിടിക്കുക."</string>
<string name="face_acquired_too_much_motion" msgid="8199691445085189528">"വളരെയധികം ചലനം. ഫോൺ അനക്കാതെ നേരെ പിടിക്കുക."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index f26eb78..00d368d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -2122,11 +2122,11 @@
<string name="notification_appops_camera_active" msgid="8177643089272352083">"Câmara"</string>
<string name="notification_appops_microphone_active" msgid="581333393214739332">"Microfone"</string>
<string name="notification_appops_overlay_active" msgid="5571732753262836481">"sobrepõe-se a outras aplicações no ecrã"</string>
- <string name="notification_feedback_indicator" msgid="663476517711323016">"Fornecer feedback"</string>
- <string name="notification_feedback_indicator_alerted" msgid="6552871804121942099">"Esta notificação foi promovida para Predefinida. Toque para fornecer feedback."</string>
- <string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Esta notificação foi despromovida para Silenciosa. Toque para fornecer feedback."</string>
- <string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Esta notificação passou para uma classificação superior. Toque para fornecer feedback."</string>
- <string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Esta notificação passou para uma classificação inferior. Toque para fornecer feedback."</string>
+ <string name="notification_feedback_indicator" msgid="663476517711323016">"Dar feedback"</string>
+ <string name="notification_feedback_indicator_alerted" msgid="6552871804121942099">"Esta notificação foi promovida para Predefinida. Toque para dar feedback."</string>
+ <string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"Esta notificação foi despromovida para Silenciosa. Toque para dar feedback."</string>
+ <string name="notification_feedback_indicator_promoted" msgid="9030204303764698640">"Esta notificação passou para uma classificação superior. Toque para dar feedback."</string>
+ <string name="notification_feedback_indicator_demoted" msgid="8880309924296450875">"Esta notificação passou para uma classificação inferior. Toque para dar feedback."</string>
<string name="nas_upgrade_notification_title" msgid="8436359459300146555">"Notificações melhoradas"</string>
<string name="nas_upgrade_notification_content" msgid="5157550369837103337">"As ações e as respostas sugeridas são agora fornecidas por notificações melhoradas. As notificações adaptáveis do Android já não são suportadas."</string>
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 3c7619c..3a7de66 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -492,8 +492,8 @@
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"允許應用程式存取額外位置資訊提供者指令。這項設定可能會造成應用程式干擾 GPS 或其他位置資訊來源的運作。"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"僅可在前景中取得精確位置"</string>
<string name="permdesc_accessFineLocation" msgid="6732174080240016335">"只有在你使用時,這個應用程式才能透過定位服務取得你的精確位置。你必須在裝置上開啟定位服務,這個應用程式才能取得位置資訊。這麼做可能會增加電池用量。"</string>
- <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"僅可在前景中取得概略位置"</string>
- <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"只有在你使用時,這個應用程式才能透過定位服務取得你的概略位置。你必須在裝置上開啟定位服務,這個應用程式才能取得位置資訊。"</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"僅可在前景中取得大概位置"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"只有在你使用時,這個應用程式才能透過定位服務取得你的大概位置。你必須在裝置上開啟定位服務,這個應用程式才能取得位置資訊。"</string>
<string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"在背景存取位置資訊"</string>
<string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"這個應用程式隨時都能取得位置資訊 (包括未使用應用程式時)。"</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"變更音訊設定"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9d902c9..a0cb705 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1608,7 +1608,10 @@
<fraction name="config_autoBrightnessAdjustmentMaxGamma">300%</fraction>
<!-- If we allow automatic adjustment of screen brightness while dozing, how many times we want
- to reduce it to preserve the battery. Value of 100% means no scaling. -->
+ to reduce it to preserve the battery. Value of 100% means no scaling. Not used if there is
+ a designated auto-brightness doze mapping defined in Display Device Config.
+ Also used to scale the brightness for the doze mode when auto-brightness is disabled if
+ there is an offload session present. -->
<fraction name="config_screenAutoBrightnessDozeScaleFactor">100%</fraction>
<!-- When the screen is turned on, the previous estimate of the ambient light level at the time
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 6e56fe2..7c9f2ef 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -339,4 +339,17 @@
<integer name="config_metrics_pull_cooldown_millis">82800000</integer>
<java-symbol type="integer" name="config_metrics_pull_cooldown_millis" />
+ <!-- The network capabilities that would be forced marked as cellular transport regardless it's
+ on cellular or satellite-->
+ <string-array name="config_force_cellular_transport_capabilities">
+ <!-- Added the following three capabilities for now. For the long term solution, the client
+ requests satellite network should really include TRANSPORT_SATELLITE in the network
+ request. With the following workaround, the clients can continue request network with
+ the following capabilities with TRANSPORT_CELLULAR. The network with one of the
+ following capabilities would also be marked as cellular. -->
+ <item>ims</item>
+ <item>eims</item>
+ <item>xcap</item>
+ </string-array>
+ <java-symbol type="array" name="config_force_cellular_transport_capabilities" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 238772f..c7e08e2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5452,7 +5452,7 @@
<string name="set_up_screen_lock_title">Set a screen lock</string>
<!-- Action label for the dialog prompting the user to set up a screen lock [CHAR LIMIT=30] -->
<string name="set_up_screen_lock_action_label">Set screen lock</string>
- <!-- Message shown in the dialog prompting the user to set up a screen lock to access private space [CHAR LIMIT=30] -->
+ <!-- Message shown in the dialog prompting the user to set up a screen lock to access private space [CHAR LIMIT=120] -->
<string name="private_space_set_up_screen_lock_message">To use your private space, set a screen lock on this device</string>
<!-- Title of the dialog that is shown when the user tries to launch a blocked application [CHAR LIMIT=50] -->
diff --git a/core/tests/companiontests/src/android/companion/SystemDataTransportTest.java b/core/tests/companiontests/src/android/companion/SystemDataTransportTest.java
index 73d7fe9..544ca56 100644
--- a/core/tests/companiontests/src/android/companion/SystemDataTransportTest.java
+++ b/core/tests/companiontests/src/android/companion/SystemDataTransportTest.java
@@ -220,6 +220,36 @@
assertEquals(0, out.toByteArray().length);
}
+ public void testDisassociationCleanup() throws InterruptedException {
+ // Create a new association
+ final int associationId = createAssociation();
+
+ // Subscribe to transport updates for new association
+ final CountDownLatch attached = new CountDownLatch(1);
+ final CountDownLatch detached = new CountDownLatch(1);
+ mCdm.addOnTransportsChangedListener(Runnable::run, associations -> {
+ if (associations.stream()
+ .anyMatch(association -> associationId == association.getId())) {
+ attached.countDown();
+ } else if (attached.getCount() == 0) {
+ detached.countDown();
+ }
+ });
+
+ final ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]);
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ mCdm.attachSystemDataTransport(associationId, in, out);
+
+ // Assert that the transport is attached
+ assertTrue(attached.await(1, TimeUnit.SECONDS));
+
+ // When CDM disassociates, any transport attached to that associated device should detach
+ mCdm.disassociate(associationId);
+
+ // Assert that the transport is detached
+ assertTrue(detached.await(1, TimeUnit.SECONDS));
+ }
+
public static byte[] concat(byte[]... blobs) {
int length = 0;
for (byte[] blob : blobs) {
@@ -250,12 +280,14 @@
}
private int createAssociation() {
+ List<AssociationInfo> before = mCdm.getMyAssociations();
getInstrumentation().getUiAutomation().executeShellCommand("cmd companiondevice associate "
+ mContext.getUserId() + " " + mContext.getPackageName() + " AA:BB:CC:DD:EE:FF");
List<AssociationInfo> infos;
for (int i = 0; i < 100; i++) {
infos = mCdm.getMyAssociations();
- if (!infos.isEmpty()) {
+ if (infos.size() != before.size()) {
+ infos.removeAll(before);
return infos.get(0).getId();
} else {
SystemClock.sleep(100);
diff --git a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
index 5ac99db..89c2b3c 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
@@ -255,7 +255,7 @@
assertEquals(td1.getBackgroundColor(), td2.getBackgroundColor());
assertEquals(td1.getStatusBarColor(), td2.getStatusBarColor());
assertEquals(td1.getNavigationBarColor(), td2.getNavigationBarColor());
- assertEquals(td1.getStatusBarAppearance(), td2.getStatusBarAppearance());
+ assertEquals(td1.getSystemBarsAppearance(), td2.getSystemBarsAppearance());
assertEquals(td1.getResizeMode(), td2.getResizeMode());
assertEquals(td1.getMinWidth(), td2.getMinWidth());
assertEquals(td1.getMinHeight(), td2.getMinHeight());
diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
new file mode 100644
index 0000000..90a8c5c
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2024 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.view;
+
+import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.os.SystemClock;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ViewFrameRateTest {
+
+ @Rule
+ public ActivityTestRule<ViewCaptureTestActivity> mActivityRule = new ActivityTestRule<>(
+ ViewCaptureTestActivity.class);
+
+ private Activity mActivity;
+ private View mMovingView;
+ private ViewRootImpl mViewRoot;
+
+ @Before
+ public void setUp() throws Throwable {
+ mActivity = mActivityRule.getActivity();
+ mActivityRule.runOnUiThread(() -> {
+ mActivity.setContentView(R.layout.view_velocity_test);
+ mMovingView = mActivity.findViewById(R.id.moving_view);
+ });
+ ViewParent parent = mActivity.getWindow().getDecorView().getParent();
+ while (parent instanceof View) {
+ parent = parent.getParent();
+ }
+ mViewRoot = (ViewRootImpl) parent;
+ }
+
+ @UiThreadTest
+ @Test
+ @RequiresFlagsEnabled(FLAG_VIEW_VELOCITY_API)
+ public void frameRateChangesWhenContentMoves() {
+ mMovingView.offsetLeftAndRight(100);
+ float frameRate = mViewRoot.getPreferredFrameRate();
+ assertTrue(frameRate > 0);
+ }
+
+ @UiThreadTest
+ @Test
+ @RequiresFlagsEnabled(FLAG_VIEW_VELOCITY_API)
+ public void firstFrameNoMovement() {
+ assertEquals(0f, mViewRoot.getPreferredFrameRate(), 0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_VIEW_VELOCITY_API)
+ public void touchBoostDisable() throws Throwable {
+ mActivityRule.runOnUiThread(() -> {
+ long now = SystemClock.uptimeMillis();
+ MotionEvent down = MotionEvent.obtain(
+ /* downTime */ now,
+ /* eventTime */ now,
+ /* action */ MotionEvent.ACTION_DOWN,
+ /* x */ 0f,
+ /* y */ 0f,
+ /* metaState */ 0
+ );
+ mActivity.dispatchTouchEvent(down);
+ mMovingView.offsetLeftAndRight(10);
+ });
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ });
+
+ mActivityRule.runOnUiThread(() -> {
+ assertFalse(mViewRoot.getIsTouchBoosting());
+ });
+ }
+
+ private void waitForFrameRateCategoryToSettle() throws Throwable {
+ for (int i = 0; i < 5; i++) {
+ final CountDownLatch drawLatch = new CountDownLatch(1);
+
+ // Now that it is small, any invalidation should have a normal category
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch::countDown);
+ });
+
+ assertTrue(drawLatch.await(1, TimeUnit.SECONDS));
+ }
+ }
+
+ @Test
+ public void noVelocityUsesCategorySmall() throws Throwable {
+ final CountDownLatch drawLatch1 = new CountDownLatch(1);
+ mActivityRule.runOnUiThread(() -> {
+ float density = mActivity.getResources().getDisplayMetrics().density;
+ ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
+ layoutParams.height = (int) (40 * density);
+ layoutParams.width = (int) (40 * density);
+ mMovingView.setLayoutParams(layoutParams);
+ mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
+ });
+
+ assertTrue(drawLatch1.await(1, TimeUnit.SECONDS));
+ waitForFrameRateCategoryToSettle();
+
+ // Now that it is small, any invalidation should have a normal category
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ assertEquals(Surface.FRAME_RATE_CATEGORY_NORMAL,
+ mViewRoot.getPreferredFrameRateCategory());
+ });
+ }
+
+ @Test
+ public void noVelocityUsesCategoryNarrowWidth() throws Throwable {
+ final CountDownLatch drawLatch1 = new CountDownLatch(1);
+ mActivityRule.runOnUiThread(() -> {
+ float density = mActivity.getResources().getDisplayMetrics().density;
+ ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
+ layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ layoutParams.width = (int) (10 * density);
+ mMovingView.setLayoutParams(layoutParams);
+ mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
+ });
+
+ assertTrue(drawLatch1.await(1, TimeUnit.SECONDS));
+ waitForFrameRateCategoryToSettle();
+
+ // Now that it is small, any invalidation should have a normal category
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ assertEquals(Surface.FRAME_RATE_CATEGORY_NORMAL,
+ mViewRoot.getPreferredFrameRateCategory());
+ });
+ }
+
+ @Test
+ public void noVelocityUsesCategoryNarrowHeight() throws Throwable {
+ final CountDownLatch drawLatch1 = new CountDownLatch(1);
+ mActivityRule.runOnUiThread(() -> {
+ float density = mActivity.getResources().getDisplayMetrics().density;
+ ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
+ layoutParams.height = (int) (10 * density);
+ layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ mMovingView.setLayoutParams(layoutParams);
+ mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
+ });
+
+ assertTrue(drawLatch1.await(1, TimeUnit.SECONDS));
+ waitForFrameRateCategoryToSettle();
+
+ // Now that it is small, any invalidation should have a normal category
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ assertEquals(Surface.FRAME_RATE_CATEGORY_NORMAL,
+ mViewRoot.getPreferredFrameRateCategory());
+ });
+ }
+
+ @Test
+ public void noVelocityUsesCategoryLargeWidth() throws Throwable {
+ final CountDownLatch drawLatch1 = new CountDownLatch(1);
+ mActivityRule.runOnUiThread(() -> {
+ float density = mActivity.getResources().getDisplayMetrics().density;
+ ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
+ layoutParams.height = (int) (40 * density);
+ layoutParams.width = (int) Math.ceil(41 * density);
+ mMovingView.setLayoutParams(layoutParams);
+ mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
+ });
+
+ assertTrue(drawLatch1.await(1, TimeUnit.SECONDS));
+ waitForFrameRateCategoryToSettle();
+
+ // Now that it is small, any invalidation should have a high category
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ assertEquals(Surface.FRAME_RATE_CATEGORY_HIGH,
+ mViewRoot.getPreferredFrameRateCategory());
+ });
+ }
+
+ @Test
+ public void noVelocityUsesCategoryLargeHeight() throws Throwable {
+ final CountDownLatch drawLatch1 = new CountDownLatch(1);
+ mActivityRule.runOnUiThread(() -> {
+ float density = mActivity.getResources().getDisplayMetrics().density;
+ ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
+ layoutParams.height = (int) Math.ceil(41 * density);
+ layoutParams.width = (int) (40 * density);
+ mMovingView.setLayoutParams(layoutParams);
+ mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
+ });
+
+ assertTrue(drawLatch1.await(1, TimeUnit.SECONDS));
+ waitForFrameRateCategoryToSettle();
+
+ // Now that it is small, any invalidation should have a high category
+ mActivityRule.runOnUiThread(() -> {
+ mMovingView.invalidate();
+ assertEquals(Surface.FRAME_RATE_CATEGORY_HIGH,
+ mViewRoot.getPreferredFrameRateCategory());
+ });
+ }
+}
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 1a242ef..2544fcb 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -19,6 +19,7 @@
import static android.view.accessibility.Flags.FLAG_FORCE_INVERT_COLOR;
import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_BY_SIZE_READ_ONLY;
+import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT;
import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
@@ -796,6 +797,38 @@
}
/**
+ * When velocity of a View is not equal to 0, we call setFrameRateCategory with HIGH.
+ * Also, we shouldn't call setFrameRate.
+ */
+ @Test
+ @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY, FLAG_VIEW_VELOCITY_API})
+ public void votePreferredFrameRate_voteFrameRateCategory_velocityToHigh() {
+ View view = new View(sContext);
+ WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
+ wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check
+ wmlp.width = 1;
+ wmlp.height = 1;
+
+ sInstrumentation.runOnMainSync(() -> {
+ WindowManager wm = sContext.getSystemService(WindowManager.class);
+ wm.addView(view, wmlp);
+ });
+ sInstrumentation.waitForIdleSync();
+
+ ViewRootImpl viewRootImpl = view.getViewRootImpl();
+
+ sInstrumentation.runOnMainSync(() -> {
+ assertEquals(viewRootImpl.getPreferredFrameRate(), 0, 0.1);
+ view.setFrameContentVelocity(100);
+ view.invalidate();
+ assertTrue(viewRootImpl.getPreferredFrameRate() > 0);
+ });
+ sInstrumentation.waitForIdleSync();
+ assertEquals(viewRootImpl.getLastPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH);
+ assertEquals(viewRootImpl.getLastPreferredFrameRate(), 0 , 0.1);
+ }
+
+ /**
* We should boost the frame rate if the value of mInsetsAnimationRunning is true.
*/
@Test
diff --git a/core/tests/coretests/src/android/view/ViewVelocityTest.java b/core/tests/coretests/src/android/view/ViewVelocityTest.java
deleted file mode 100644
index d437f7b..0000000
--- a/core/tests/coretests/src/android/view/ViewVelocityTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2024 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.view;
-
-import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.app.Activity;
-import android.os.SystemClock;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.filters.SmallTest;
-import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.frameworks.coretests.R;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class ViewVelocityTest {
-
- @Rule
- public ActivityTestRule<ViewCaptureTestActivity> mActivityRule = new ActivityTestRule<>(
- ViewCaptureTestActivity.class);
-
- private Activity mActivity;
- private View mMovingView;
- private ViewRootImpl mViewRoot;
-
- @Before
- public void setUp() throws Throwable {
- mActivity = mActivityRule.getActivity();
- mActivityRule.runOnUiThread(() -> {
- mActivity.setContentView(R.layout.view_velocity_test);
- mMovingView = mActivity.findViewById(R.id.moving_view);
- });
- ViewParent parent = mActivity.getWindow().getDecorView().getParent();
- while (parent instanceof View) {
- parent = parent.getParent();
- }
- mViewRoot = (ViewRootImpl) parent;
- }
-
- @UiThreadTest
- @Test
- @RequiresFlagsEnabled(FLAG_VIEW_VELOCITY_API)
- public void frameRateChangesWhenContentMoves() {
- mMovingView.offsetLeftAndRight(100);
- float frameRate = mViewRoot.getPreferredFrameRate();
- assertTrue(frameRate > 0);
- }
-
- @UiThreadTest
- @Test
- @RequiresFlagsEnabled(FLAG_VIEW_VELOCITY_API)
- public void firstFrameNoMovement() {
- assertEquals(0f, mViewRoot.getPreferredFrameRate(), 0f);
- }
-
- @Test
- @RequiresFlagsEnabled(FLAG_VIEW_VELOCITY_API)
- public void touchBoostDisable() throws Throwable {
- mActivityRule.runOnUiThread(() -> {
- long now = SystemClock.uptimeMillis();
- MotionEvent down = MotionEvent.obtain(
- /* downTime */ now,
- /* eventTime */ now,
- /* action */ MotionEvent.ACTION_DOWN,
- /* x */ 0f,
- /* y */ 0f,
- /* metaState */ 0
- );
- mActivity.dispatchTouchEvent(down);
- mMovingView.offsetLeftAndRight(10);
- });
- mActivityRule.runOnUiThread(() -> {
- mMovingView.invalidate();
- });
-
- mActivityRule.runOnUiThread(() -> {
- assertFalse(mViewRoot.getIsTouchBoosting());
- });
- }
-}
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index ce2543a..bca741f 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -88,5 +88,8 @@
<permission name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS" />
<permission name="android.permission.READ_SEARCH_INDEXABLES" />
<permission name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT"/>
+ <permission name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS" />
+ <permission name="android.permission.CONTROL_UI_TRACING" />
+ <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND" />
</privapp-permissions>
</permissions>
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 20e393e..940cd93 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -25,6 +25,8 @@
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
+import android.hardware.DataSpace;
+import android.hardware.HardwareBuffer;
import android.hardware.OverlayProperties;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
@@ -1417,7 +1419,14 @@
nInitDisplayInfo(largestWidth, largestHeight, defaultDisplay.getRefreshRate(),
wideColorDataspace, defaultDisplay.getAppVsyncOffsetNanos(),
defaultDisplay.getPresentationDeadlineNanos(),
- overlayProperties.isFp16SupportedForHdr(),
+ overlayProperties.isCombinationSupported(
+ DataSpace.DATASPACE_SCRGB, HardwareBuffer.RGBA_FP16),
+ overlayProperties.isCombinationSupported(
+ DataSpace.pack(
+ DataSpace.STANDARD_DCI_P3,
+ DataSpace.TRANSFER_SRGB,
+ DataSpace.RANGE_EXTENDED),
+ HardwareBuffer.RGBA_10101010),
overlayProperties.isMixedColorSpacesSupported());
mDisplayInitialized = true;
@@ -1603,7 +1612,8 @@
private static native void nInitDisplayInfo(int width, int height, float refreshRate,
int wideColorDataspace, long appVsyncOffsetNanos, long presentationDeadlineNanos,
- boolean supportsFp16ForHdr, boolean nInitDisplayInfo);
+ boolean supportsFp16ForHdr, boolean isRgba10101010SupportedForHdr,
+ boolean nSupportMixedColorSpaces);
private static native void nSetDrawingEnabled(boolean drawingEnabled);
diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java
index 3cd709e..69e1982 100644
--- a/graphics/java/android/graphics/pdf/PdfEditor.java
+++ b/graphics/java/android/graphics/pdf/PdfEditor.java
@@ -25,7 +25,9 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+
import dalvik.system.CloseGuard;
+
import libcore.io.IoUtils;
import java.io.IOException;
@@ -37,6 +39,12 @@
*/
public final class PdfEditor {
+ /**
+ * Any call the native pdfium code has to be single threaded as the library does not support
+ * parallel use.
+ */
+ private static final Object sPdfiumLock = new Object();
+
private final CloseGuard mCloseGuard = CloseGuard.get();
private long mNativeDocument;
@@ -79,7 +87,7 @@
}
mInput = input;
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
mNativeDocument = nativeOpen(mInput.getFd(), size);
try {
mPageCount = nativeGetPageCount(mNativeDocument);
@@ -112,7 +120,7 @@
throwIfClosed();
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
mPageCount = nativeRemovePage(mNativeDocument, pageIndex);
}
}
@@ -138,12 +146,12 @@
Point size = new Point();
getPageSize(pageIndex, size);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(),
0, 0, size.x, size.y);
}
} else {
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(),
clip.left, clip.top, clip.right, clip.bottom);
}
@@ -161,7 +169,7 @@
throwIfOutSizeNull(outSize);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeGetPageSize(mNativeDocument, pageIndex, outSize);
}
}
@@ -177,7 +185,7 @@
throwIfOutMediaBoxNull(outMediaBox);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox);
}
}
@@ -193,7 +201,7 @@
throwIfMediaBoxNull(mediaBox);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox);
}
}
@@ -209,7 +217,7 @@
throwIfOutCropBoxNull(outCropBox);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox);
}
}
@@ -225,7 +233,7 @@
throwIfCropBoxNull(cropBox);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox);
}
}
@@ -238,7 +246,7 @@
public boolean shouldScaleForPrinting() {
throwIfClosed();
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
return nativeScaleForPrinting(mNativeDocument);
}
}
@@ -255,7 +263,7 @@
try {
throwIfClosed();
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeWrite(mNativeDocument, output.getFd());
}
} finally {
@@ -287,7 +295,7 @@
private void doClose() {
if (mNativeDocument != 0) {
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeClose(mNativeDocument);
}
mNativeDocument = 0;
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
deleted file mode 100644
index 4666963..0000000
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * 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.
- */
-
-package android.graphics.pdf;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Matrix;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-
-import com.android.internal.util.Preconditions;
-
-import dalvik.system.CloseGuard;
-
-import libcore.io.IoUtils;
-
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * <p>
- * This class enables rendering a PDF document. This class is not thread safe.
- * </p>
- * <p>
- * If you want to render a PDF, you create a renderer and for every page you want
- * to render, you open the page, render it, and close the page. After you are done
- * with rendering, you close the renderer. After the renderer is closed it should not
- * be used anymore. Note that the pages are rendered one by one, i.e. you can have
- * only a single page opened at any given time.
- * </p>
- * <p>
- * A typical use of the APIs to render a PDF looks like this:
- * </p>
- * <pre>
- * // create a new renderer
- * PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor());
- *
- * // let us just render all pages
- * final int pageCount = renderer.getPageCount();
- * for (int i = 0; i < pageCount; i++) {
- * Page page = renderer.openPage(i);
- *
- * // say we render for showing on the screen
- * page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY);
- *
- * // do stuff with the bitmap
- *
- * // close the page
- * page.close();
- * }
- *
- * // close the renderer
- * renderer.close();
- * </pre>
- *
- * <h3>Print preview and print output</h3>
- * <p>
- * If you are using this class to rasterize a PDF for printing or show a print
- * preview, it is recommended that you respect the following contract in order
- * to provide a consistent user experience when seeing a preview and printing,
- * i.e. the user sees a preview that is the same as the printout.
- * </p>
- * <ul>
- * <li>
- * Respect the property whether the document would like to be scaled for printing
- * as per {@link #shouldScaleForPrinting()}.
- * </li>
- * <li>
- * When scaling a document for printing the aspect ratio should be preserved.
- * </li>
- * <li>
- * Do not inset the content with any margins from the {@link android.print.PrintAttributes}
- * as the application is responsible to render it such that the margins are respected.
- * </li>
- * <li>
- * If document page size is greater than the printed media size the content should
- * be anchored to the upper left corner of the page for left-to-right locales and
- * top right corner for right-to-left locales.
- * </li>
- * </ul>
- *
- * @see #close()
- */
-public final class PdfRenderer implements AutoCloseable {
- /**
- * Any call the native pdfium code has to be single threaded as the library does not support
- * parallel use.
- */
- final static Object sPdfiumLock = new Object();
-
- private final CloseGuard mCloseGuard = CloseGuard.get();
-
- private final Point mTempPoint = new Point();
-
- private long mNativeDocument;
-
- private final int mPageCount;
-
- private ParcelFileDescriptor mInput;
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private Page mCurrentPage;
-
- /** @hide */
- @IntDef({
- Page.RENDER_MODE_FOR_DISPLAY,
- Page.RENDER_MODE_FOR_PRINT
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface RenderMode {}
-
- /**
- * Creates a new instance.
- * <p>
- * <strong>Note:</strong> The provided file descriptor must be <strong>seekable</strong>,
- * i.e. its data being randomly accessed, e.g. pointing to a file.
- * </p>
- * <p>
- * <strong>Note:</strong> This class takes ownership of the passed in file descriptor
- * and is responsible for closing it when the renderer is closed.
- * </p>
- * <p>
- * If the file is from an untrusted source it is recommended to run the renderer in a separate,
- * isolated process with minimal permissions to limit the impact of security exploits.
- * </p>
- *
- * @param input Seekable file descriptor to read from.
- *
- * @throws java.io.IOException If an error occurs while reading the file.
- * @throws java.lang.SecurityException If the file requires a password or
- * the security scheme is not supported.
- */
- public PdfRenderer(@NonNull ParcelFileDescriptor input) throws IOException {
- if (input == null) {
- throw new NullPointerException("input cannot be null");
- }
-
- final long size;
- try {
- Os.lseek(input.getFileDescriptor(), 0, OsConstants.SEEK_SET);
- size = Os.fstat(input.getFileDescriptor()).st_size;
- } catch (ErrnoException ee) {
- throw new IllegalArgumentException("file descriptor not seekable");
- }
- mInput = input;
-
- synchronized (sPdfiumLock) {
- mNativeDocument = nativeCreate(mInput.getFd(), size);
- try {
- mPageCount = nativeGetPageCount(mNativeDocument);
- } catch (Throwable t) {
- nativeClose(mNativeDocument);
- mNativeDocument = 0;
- throw t;
- }
- }
-
- mCloseGuard.open("close");
- }
-
- /**
- * Closes this renderer. You should not use this instance
- * after this method is called.
- */
- public void close() {
- throwIfClosed();
- throwIfPageOpened();
- doClose();
- }
-
- /**
- * Gets the number of pages in the document.
- *
- * @return The page count.
- */
- public int getPageCount() {
- throwIfClosed();
- return mPageCount;
- }
-
- /**
- * Gets whether the document prefers to be scaled for printing.
- * You should take this info account if the document is rendered
- * for printing and the target media size differs from the page
- * size.
- *
- * @return If to scale the document.
- */
- public boolean shouldScaleForPrinting() {
- throwIfClosed();
-
- synchronized (sPdfiumLock) {
- return nativeScaleForPrinting(mNativeDocument);
- }
- }
-
- /**
- * Opens a page for rendering.
- *
- * @param index The page index.
- * @return A page that can be rendered.
- *
- * @see android.graphics.pdf.PdfRenderer.Page#close() PdfRenderer.Page.close()
- */
- public Page openPage(int index) {
- throwIfClosed();
- throwIfPageOpened();
- throwIfPageNotInDocument(index);
- mCurrentPage = new Page(index);
- return mCurrentPage;
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
-
- doClose();
- } finally {
- super.finalize();
- }
- }
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private void doClose() {
- if (mCurrentPage != null) {
- mCurrentPage.close();
- mCurrentPage = null;
- }
-
- if (mNativeDocument != 0) {
- synchronized (sPdfiumLock) {
- nativeClose(mNativeDocument);
- }
- mNativeDocument = 0;
- }
-
- if (mInput != null) {
- IoUtils.closeQuietly(mInput);
- mInput = null;
- }
- mCloseGuard.close();
- }
-
- private void throwIfClosed() {
- if (mInput == null) {
- throw new IllegalStateException("Already closed");
- }
- }
-
- private void throwIfPageOpened() {
- if (mCurrentPage != null) {
- throw new IllegalStateException("Current page not closed");
- }
- }
-
- private void throwIfPageNotInDocument(int pageIndex) {
- if (pageIndex < 0 || pageIndex >= mPageCount) {
- throw new IllegalArgumentException("Invalid page index");
- }
- }
-
- /**
- * This class represents a PDF document page for rendering.
- */
- public final class Page implements AutoCloseable {
-
- private final CloseGuard mCloseGuard = CloseGuard.get();
-
- /**
- * Mode to render the content for display on a screen.
- */
- public static final int RENDER_MODE_FOR_DISPLAY = 1;
-
- /**
- * Mode to render the content for printing.
- */
- public static final int RENDER_MODE_FOR_PRINT = 2;
-
- private final int mIndex;
- private final int mWidth;
- private final int mHeight;
-
- private long mNativePage;
-
- private Page(int index) {
- Point size = mTempPoint;
- synchronized (sPdfiumLock) {
- mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size);
- }
- mIndex = index;
- mWidth = size.x;
- mHeight = size.y;
- mCloseGuard.open("close");
- }
-
- /**
- * Gets the page index.
- *
- * @return The index.
- */
- public int getIndex() {
- return mIndex;
- }
-
- /**
- * Gets the page width in points (1/72").
- *
- * @return The width in points.
- */
- public int getWidth() {
- return mWidth;
- }
-
- /**
- * Gets the page height in points (1/72").
- *
- * @return The height in points.
- */
- public int getHeight() {
- return mHeight;
- }
-
- /**
- * Renders a page to a bitmap.
- * <p>
- * You may optionally specify a rectangular clip in the bitmap bounds. No rendering
- * outside the clip will be performed, hence it is your responsibility to initialize
- * the bitmap outside the clip.
- * </p>
- * <p>
- * You may optionally specify a matrix to transform the content from page coordinates
- * which are in points (1/72") to bitmap coordinates which are in pixels. If this
- * matrix is not provided this method will apply a transformation that will fit the
- * whole page to the destination clip if provided or the destination bitmap if no
- * clip is provided.
- * </p>
- * <p>
- * The clip and transformation are useful for implementing tile rendering where the
- * destination bitmap contains a portion of the image, for example when zooming.
- * Another useful application is for printing where the size of the bitmap holding
- * the page is too large and a client can render the page in stripes.
- * </p>
- * <p>
- * <strong>Note: </strong> The destination bitmap format must be
- * {@link Config#ARGB_8888 ARGB}.
- * </p>
- * <p>
- * <strong>Note: </strong> The optional transformation matrix must be affine as per
- * {@link android.graphics.Matrix#isAffine() Matrix.isAffine()}. Hence, you can specify
- * rotation, scaling, translation but not a perspective transformation.
- * </p>
- *
- * @param destination Destination bitmap to which to render.
- * @param destClip Optional clip in the bitmap bounds.
- * @param transform Optional transformation to apply when rendering.
- * @param renderMode The render mode.
- *
- * @see #RENDER_MODE_FOR_DISPLAY
- * @see #RENDER_MODE_FOR_PRINT
- */
- public void render(@NonNull Bitmap destination, @Nullable Rect destClip,
- @Nullable Matrix transform, @RenderMode int renderMode) {
- if (mNativePage == 0) {
- throw new NullPointerException();
- }
-
- destination = Preconditions.checkNotNull(destination, "bitmap null");
-
- if (destination.getConfig() != Config.ARGB_8888) {
- throw new IllegalArgumentException("Unsupported pixel format");
- }
-
- if (destClip != null) {
- if (destClip.left < 0 || destClip.top < 0
- || destClip.right > destination.getWidth()
- || destClip.bottom > destination.getHeight()) {
- throw new IllegalArgumentException("destBounds not in destination");
- }
- }
-
- if (transform != null && !transform.isAffine()) {
- throw new IllegalArgumentException("transform not affine");
- }
-
- if (renderMode != RENDER_MODE_FOR_PRINT && renderMode != RENDER_MODE_FOR_DISPLAY) {
- throw new IllegalArgumentException("Unsupported render mode");
- }
-
- if (renderMode == RENDER_MODE_FOR_PRINT && renderMode == RENDER_MODE_FOR_DISPLAY) {
- throw new IllegalArgumentException("Only single render mode supported");
- }
-
- final int contentLeft = (destClip != null) ? destClip.left : 0;
- final int contentTop = (destClip != null) ? destClip.top : 0;
- final int contentRight = (destClip != null) ? destClip.right
- : destination.getWidth();
- final int contentBottom = (destClip != null) ? destClip.bottom
- : destination.getHeight();
-
- // If transform is not set, stretch page to whole clipped area
- if (transform == null) {
- int clipWidth = contentRight - contentLeft;
- int clipHeight = contentBottom - contentTop;
-
- transform = new Matrix();
- transform.postScale((float)clipWidth / getWidth(),
- (float)clipHeight / getHeight());
- transform.postTranslate(contentLeft, contentTop);
- }
-
- // FIXME: This code is planned to be outside the UI rendering module, so it should not
- // be able to access native instances from Bitmap, Matrix, etc.
- final long transformPtr = transform.ni();
-
- synchronized (sPdfiumLock) {
- nativeRenderPage(mNativeDocument, mNativePage, destination.getNativeInstance(),
- contentLeft, contentTop, contentRight, contentBottom, transformPtr,
- renderMode);
- }
- }
-
- /**
- * Closes this page.
- *
- * @see android.graphics.pdf.PdfRenderer#openPage(int)
- */
- @Override
- public void close() {
- throwIfClosed();
- doClose();
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
-
- doClose();
- } finally {
- super.finalize();
- }
- }
-
- private void doClose() {
- if (mNativePage != 0) {
- synchronized (sPdfiumLock) {
- nativeClosePage(mNativePage);
- }
- mNativePage = 0;
- }
-
- mCloseGuard.close();
- mCurrentPage = null;
- }
-
- private void throwIfClosed() {
- if (mNativePage == 0) {
- throw new IllegalStateException("Already closed");
- }
- }
- }
-
- private static native long nativeCreate(int fd, long size);
- private static native void nativeClose(long documentPtr);
- private static native int nativeGetPageCount(long documentPtr);
- private static native boolean nativeScaleForPrinting(long documentPtr);
- private static native void nativeRenderPage(long documentPtr, long pagePtr, long bitmapHandle,
- int clipLeft, int clipTop, int clipRight, int clipBottom, long transformPtr,
- int renderMode);
- private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex,
- Point outSize);
- private static native void nativeClosePage(long pagePtr);
-}
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt
index 9cd14fca..e422198 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt
@@ -28,6 +28,7 @@
import androidx.test.filters.SmallTest
import com.android.wm.shell.R
import com.android.wm.shell.bubbles.BubblePositioner.MAX_HEIGHT
+import com.android.wm.shell.common.bubbles.BubbleBarLocation
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
import org.junit.Before
@@ -486,6 +487,32 @@
positioner.screenRect.width() - paddings[0] - paddings[2])
}
+ @Test
+ fun testIsBubbleBarOnLeft_defaultsToRight() {
+ positioner.bubbleBarLocation = BubbleBarLocation.DEFAULT
+ assertThat(positioner.isBubbleBarOnLeft).isFalse()
+
+ // Check that left and right return expected position
+ positioner.bubbleBarLocation = BubbleBarLocation.LEFT
+ assertThat(positioner.isBubbleBarOnLeft).isTrue()
+ positioner.bubbleBarLocation = BubbleBarLocation.RIGHT
+ assertThat(positioner.isBubbleBarOnLeft).isFalse()
+ }
+
+ @Test
+ fun testIsBubbleBarOnLeft_rtlEnabled_defaultsToLeft() {
+ positioner.update(defaultDeviceConfig.copy(isRtl = true))
+
+ positioner.bubbleBarLocation = BubbleBarLocation.DEFAULT
+ assertThat(positioner.isBubbleBarOnLeft).isTrue()
+
+ // Check that left and right return expected position
+ positioner.bubbleBarLocation = BubbleBarLocation.LEFT
+ assertThat(positioner.isBubbleBarOnLeft).isTrue()
+ positioner.bubbleBarLocation = BubbleBarLocation.RIGHT
+ assertThat(positioner.isBubbleBarOnLeft).isFalse()
+ }
+
private val defaultYPosition: Float
/**
* Calculates the Y position bubbles should be placed based on the config. Based on the
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 96aaf02..9585842 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -103,6 +103,7 @@
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.annotations.ShellBackgroundThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
@@ -708,6 +709,30 @@
return mBubbleProperties.isBubbleBarEnabled() && mBubblePositioner.isLargeScreen();
}
+ /**
+ * Returns current {@link BubbleBarLocation} if bubble bar is being used.
+ * Otherwise returns <code>null</code>
+ */
+ @Nullable
+ public BubbleBarLocation getBubbleBarLocation() {
+ if (canShowAsBubbleBar()) {
+ return mBubblePositioner.getBubbleBarLocation();
+ }
+ return null;
+ }
+
+ /**
+ * Update bubble bar location and trigger and update to listeners
+ */
+ public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+ if (canShowAsBubbleBar()) {
+ mBubblePositioner.setBubbleBarLocation(bubbleBarLocation);
+ BubbleBarUpdate bubbleBarUpdate = new BubbleBarUpdate();
+ bubbleBarUpdate.bubbleBarLocation = bubbleBarLocation;
+ mBubbleStateListener.onBubbleStateChange(bubbleBarUpdate);
+ }
+ }
+
/** Whether this userId belongs to the current user. */
private boolean isCurrentProfile(int userId) {
return userId == UserHandle.USER_ALL
@@ -1179,7 +1204,7 @@
*/
@VisibleForTesting
public void expandStackAndSelectBubbleFromLauncher(String key, Rect bubbleBarBounds) {
- mBubblePositioner.setBubbleBarPosition(bubbleBarBounds);
+ mBubblePositioner.setBubbleBarBounds(bubbleBarBounds);
if (BubbleOverflow.KEY.equals(key)) {
mBubbleData.setSelectedBubbleFromLauncher(mBubbleData.getOverflow());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index 6c2f925..61f0ed2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -165,7 +165,7 @@
* used when {@link BubbleController#isShowingAsBubbleBar()} is true.
*/
BubbleBarUpdate getInitialState() {
- BubbleBarUpdate bubbleBarUpdate = new BubbleBarUpdate();
+ BubbleBarUpdate bubbleBarUpdate = BubbleBarUpdate.createInitialState();
bubbleBarUpdate.shouldShowEducation = shouldShowEducation;
for (int i = 0; i < bubbles.size(); i++) {
bubbleBarUpdate.currentBubbleList.add(bubbles.get(i).asBubbleBarBubble());
@@ -255,7 +255,9 @@
* Returns a bubble bar update populated with the current list of active bubbles.
*/
public BubbleBarUpdate getInitialStateForBubbleBar() {
- return mStateChange.getInitialState();
+ BubbleBarUpdate initialState = mStateChange.getInitialState();
+ initialState.bubbleBarLocation = mPositioner.getBubbleBarLocation();
+ return initialState;
}
public void setSuppressionChangedListener(Bubbles.BubbleMetadataFlagListener listener) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index a5853d6..b215b61 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -32,6 +32,7 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.launcher3.icons.IconNormalizer;
import com.android.wm.shell.R;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
/**
* Keeps track of display size, configuration, and specific bubble sizes. One place for all
@@ -95,6 +96,7 @@
private PointF mRestingStackPosition;
private boolean mShowingInBubbleBar;
+ private BubbleBarLocation mBubbleBarLocation = BubbleBarLocation.DEFAULT;
private final Rect mBubbleBarBounds = new Rect();
public BubblePositioner(Context context, WindowManager windowManager) {
@@ -797,14 +799,36 @@
mShowingInBubbleBar = showingInBubbleBar;
}
+ public void setBubbleBarLocation(BubbleBarLocation location) {
+ mBubbleBarLocation = location;
+ }
+
+ public BubbleBarLocation getBubbleBarLocation() {
+ return mBubbleBarLocation;
+ }
+
+ /**
+ * @return <code>true</code> when bubble bar is on the left and <code>false</code> when on right
+ */
+ public boolean isBubbleBarOnLeft() {
+ return mBubbleBarLocation.isOnLeft(mDeviceConfig.isRtl());
+ }
+
/**
* Sets the position of the bubble bar in display coordinates.
*/
- public void setBubbleBarPosition(Rect bubbleBarBounds) {
+ public void setBubbleBarBounds(Rect bubbleBarBounds) {
mBubbleBarBounds.set(bubbleBarBounds);
}
/**
+ * Returns the display coordinates of the bubble bar.
+ */
+ public Rect getBubbleBarBounds() {
+ return mBubbleBarBounds;
+ }
+
+ /**
* How wide the expanded view should be when showing from the bubble bar.
*/
public int getExpandedViewWidthForBubbleBar(boolean isOverflow) {
@@ -831,11 +855,4 @@
public int getBubbleBarExpandedViewPadding() {
return mExpandedViewPadding;
}
-
- /**
- * Returns the display coordinates of the bubble bar.
- */
- public Rect getBubbleBarBounds() {
- return mBubbleBarBounds;
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
index 8946f41..9eb9632 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
@@ -477,7 +477,7 @@
private Point getExpandedViewRestPosition(Size size) {
final int padding = mPositioner.getBubbleBarExpandedViewPadding();
Point point = new Point();
- if (mLayerView.isOnLeft()) {
+ if (mPositioner.isBubbleBarOnLeft()) {
point.x = mPositioner.getInsets().left + padding;
} else {
point.x = mPositioner.getAvailableRect().width() - size.getWidth() - padding;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt
index 7d37d60..056598b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewDragController.kt
@@ -19,6 +19,8 @@
import android.annotation.SuppressLint
import android.view.MotionEvent
import android.view.View
+import com.android.wm.shell.bubbles.BubblePositioner
+import com.android.wm.shell.common.bubbles.BubbleBarLocation
import com.android.wm.shell.common.bubbles.DismissView
import com.android.wm.shell.common.bubbles.RelativeTouchListener
import com.android.wm.shell.common.magnetictarget.MagnetizedObject
@@ -29,7 +31,8 @@
private val expandedView: BubbleBarExpandedView,
private val dismissView: DismissView,
private val animationHelper: BubbleBarAnimationHelper,
- private val onDismissed: () -> Unit
+ private val bubblePositioner: BubblePositioner,
+ private val dragListener: DragListener
) {
var isStuckToDismiss: Boolean = false
@@ -45,11 +48,11 @@
magnetizedExpandedView.magnetListener = MagnetListener()
magnetizedExpandedView.animateStuckToTarget =
{
- target: MagnetizedObject.MagneticTarget,
- _: Float,
- _: Float,
- _: Boolean,
- after: (() -> Unit)? ->
+ target: MagnetizedObject.MagneticTarget,
+ _: Float,
+ _: Float,
+ _: Boolean,
+ after: (() -> Unit)? ->
animationHelper.animateIntoTarget(target, after)
}
@@ -73,13 +76,34 @@
}
}
+ /** Listener to receive callback about dragging events */
+ interface DragListener {
+ /**
+ * Bubble bar [BubbleBarLocation] has changed as a result of dragging the expanded view.
+ *
+ * Triggered when drag gesture passes the middle of the screen and before touch up.
+ * Can be triggered multiple times per gesture.
+ *
+ * @param location new location of the bubble bar as a result of the ongoing drag operation
+ */
+ fun onLocationChanged(location: BubbleBarLocation)
+
+ /** Expanded view has been released in the dismiss target */
+ fun onReleasedInDismiss()
+ }
+
private inner class HandleDragListener : RelativeTouchListener() {
private var isMoving = false
+ private var screenCenterX: Int = -1
+ private var isOnLeft = false
override fun onDown(v: View, ev: MotionEvent): Boolean {
// While animating, don't allow new touch events
- return !expandedView.isAnimating
+ if (expandedView.isAnimating) return false
+ screenCenterX = bubblePositioner.screenRect.centerX()
+ isOnLeft = bubblePositioner.isBubbleBarOnLeft
+ return true
}
override fun onMove(
@@ -97,6 +121,14 @@
expandedView.translationX = expandedViewInitialTranslationX + dx
expandedView.translationY = expandedViewInitialTranslationY + dy
dismissView.show()
+
+ if (isOnLeft && ev.rawX > screenCenterX) {
+ isOnLeft = false
+ dragListener.onLocationChanged(BubbleBarLocation.RIGHT)
+ } else if (!isOnLeft && ev.rawX < screenCenterX) {
+ isOnLeft = true
+ dragListener.onLocationChanged(BubbleBarLocation.LEFT)
+ }
}
override fun onUp(
@@ -113,6 +145,7 @@
}
override fun onCancel(v: View, ev: MotionEvent, viewInitialX: Float, viewInitialY: Float) {
+ isStuckToDismiss = false
finishDrag()
}
@@ -127,30 +160,29 @@
private inner class MagnetListener : MagnetizedObject.MagnetListener {
override fun onStuckToTarget(
- target: MagnetizedObject.MagneticTarget,
- draggedObject: MagnetizedObject<*>
+ target: MagnetizedObject.MagneticTarget,
+ draggedObject: MagnetizedObject<*>
) {
isStuckToDismiss = true
}
override fun onUnstuckFromTarget(
- target: MagnetizedObject.MagneticTarget,
- draggedObject: MagnetizedObject<*>,
- velX: Float,
- velY: Float,
- wasFlungOut: Boolean
+ target: MagnetizedObject.MagneticTarget,
+ draggedObject: MagnetizedObject<*>,
+ velX: Float,
+ velY: Float,
+ wasFlungOut: Boolean
) {
isStuckToDismiss = false
animationHelper.animateUnstuckFromDismissView(target)
}
override fun onReleasedInTarget(
- target: MagnetizedObject.MagneticTarget,
- draggedObject: MagnetizedObject<*>
+ target: MagnetizedObject.MagneticTarget,
+ draggedObject: MagnetizedObject<*>
) {
- onDismissed()
+ dragListener.onReleasedInDismiss()
dismissView.hide()
}
}
}
-
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
index 42799d9..3fb9f63 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
@@ -33,6 +33,8 @@
import android.view.WindowManager;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+
import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.Bubble;
import com.android.wm.shell.bubbles.BubbleController;
@@ -42,6 +44,8 @@
import com.android.wm.shell.bubbles.BubbleViewProvider;
import com.android.wm.shell.bubbles.DeviceConfig;
import com.android.wm.shell.bubbles.DismissViewUtils;
+import com.android.wm.shell.bubbles.bar.BubbleBarExpandedViewDragController.DragListener;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
import com.android.wm.shell.common.bubbles.DismissView;
import kotlin.Unit;
@@ -155,12 +159,6 @@
return mIsExpanded;
}
- // TODO(b/313661121) - when dragging is implemented, check user setting first
- /** Whether the expanded view is positioned on the left or right side of the screen. */
- public boolean isOnLeft() {
- return getLayoutDirection() == LAYOUT_DIRECTION_RTL;
- }
-
/** Shows the expanded view of the provided bubble. */
public void showExpandedView(BubbleViewProvider b) {
BubbleBarExpandedView expandedView = b.getBubbleBarExpandedView();
@@ -207,15 +205,23 @@
}
});
+ DragListener dragListener = new DragListener() {
+ @Override
+ public void onLocationChanged(@NonNull BubbleBarLocation location) {
+ mBubbleController.setBubbleBarLocation(location);
+ }
+
+ @Override
+ public void onReleasedInDismiss() {
+ mBubbleController.dismissBubble(mExpandedBubble.getKey(), DISMISS_USER_GESTURE);
+ }
+ };
mDragController = new BubbleBarExpandedViewDragController(
mExpandedView,
mDismissView,
mAnimationHelper,
- () -> {
- mBubbleController.dismissBubble(mExpandedBubble.getKey(),
- DISMISS_USER_GESTURE);
- return Unit.INSTANCE;
- });
+ mPositioner,
+ dragListener);
addView(mExpandedView, new LayoutParams(width, height, Gravity.LEFT));
}
@@ -352,7 +358,7 @@
lp.width = width;
lp.height = height;
mExpandedView.setLayoutParams(lp);
- if (isOnLeft()) {
+ if (mPositioner.isBubbleBarOnLeft()) {
mExpandedView.setX(mPositioner.getInsets().left + padding);
} else {
mExpandedView.setX(mPositioner.getAvailableRect().width() - width - padding);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleBarLocation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleBarLocation.kt
new file mode 100644
index 0000000..f0bdfde
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleBarLocation.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 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.bubbles
+
+import android.os.Parcel
+import android.os.Parcelable
+
+/**
+ * The location of the bubble bar.
+ */
+enum class BubbleBarLocation : Parcelable {
+ /**
+ * Place bubble bar at the default location for the chosen system language.
+ * If an RTL language is used, it is on the left. Otherwise on the right.
+ */
+ DEFAULT,
+ /** Default bubble bar location is overridden. Place bubble bar on the left. */
+ LEFT,
+ /** Default bubble bar location is overridden. Place bubble bar on the right. */
+ RIGHT;
+
+ /**
+ * Returns whether bubble bar is pinned to the left edge or right edge.
+ */
+ fun isOnLeft(isRtl: Boolean): Boolean {
+ if (this == DEFAULT) {
+ return isRtl
+ }
+ return this == LEFT
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ override fun writeToParcel(dest: Parcel, flags: Int) {
+ dest.writeString(name)
+ }
+
+ companion object {
+ @JvmField
+ val CREATOR = object : Parcelable.Creator<BubbleBarLocation> {
+ override fun createFromParcel(parcel: Parcel): BubbleBarLocation {
+ return parcel.readString()?.let { valueOf(it) } ?: DEFAULT
+ }
+
+ override fun newArray(size: Int) = arrayOfNulls<BubbleBarLocation>(size)
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleBarUpdate.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleBarUpdate.java
index fc627a8..e5f6c37 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleBarUpdate.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleBarUpdate.java
@@ -33,6 +33,7 @@
public static final String BUNDLE_KEY = "update";
+ public final boolean initialState;
public boolean expandedChanged;
public boolean expanded;
public boolean shouldShowEducation;
@@ -46,6 +47,8 @@
public String suppressedBubbleKey;
@Nullable
public String unsupressedBubbleKey;
+ @Nullable
+ public BubbleBarLocation bubbleBarLocation;
// This is only populated if bubbles have been removed.
public List<RemovedBubble> removedBubbles = new ArrayList<>();
@@ -56,10 +59,17 @@
// This is only populated the first time a listener is connected so it gets the current state.
public List<BubbleInfo> currentBubbleList = new ArrayList<>();
+
public BubbleBarUpdate() {
+ this(false);
+ }
+
+ private BubbleBarUpdate(boolean initialState) {
+ this.initialState = initialState;
}
public BubbleBarUpdate(Parcel parcel) {
+ initialState = parcel.readBoolean();
expandedChanged = parcel.readBoolean();
expanded = parcel.readBoolean();
shouldShowEducation = parcel.readBoolean();
@@ -75,6 +85,8 @@
parcel.readStringList(bubbleKeysInOrder);
currentBubbleList = parcel.readParcelableList(new ArrayList<>(),
BubbleInfo.class.getClassLoader());
+ bubbleBarLocation = parcel.readParcelable(BubbleBarLocation.class.getClassLoader(),
+ BubbleBarLocation.class);
}
/**
@@ -89,12 +101,15 @@
|| !bubbleKeysInOrder.isEmpty()
|| suppressedBubbleKey != null
|| unsupressedBubbleKey != null
- || !currentBubbleList.isEmpty();
+ || !currentBubbleList.isEmpty()
+ || bubbleBarLocation != null;
}
@Override
public String toString() {
- return "BubbleBarUpdate{ expandedChanged=" + expandedChanged
+ return "BubbleBarUpdate{"
+ + " initialState=" + initialState
+ + " expandedChanged=" + expandedChanged
+ " expanded=" + expanded
+ " selectedBubbleKey=" + selectedBubbleKey
+ " shouldShowEducation=" + shouldShowEducation
@@ -105,6 +120,7 @@
+ " removedBubbles=" + removedBubbles
+ " bubbles=" + bubbleKeysInOrder
+ " currentBubbleList=" + currentBubbleList
+ + " bubbleBarLocation=" + bubbleBarLocation
+ " }";
}
@@ -115,6 +131,7 @@
@Override
public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeBoolean(initialState);
parcel.writeBoolean(expandedChanged);
parcel.writeBoolean(expanded);
parcel.writeBoolean(shouldShowEducation);
@@ -126,6 +143,16 @@
parcel.writeParcelableList(removedBubbles, flags);
parcel.writeStringList(bubbleKeysInOrder);
parcel.writeParcelableList(currentBubbleList, flags);
+ parcel.writeParcelable(bubbleBarLocation, flags);
+ }
+
+ /**
+ * Create update for initial set of values.
+ * <p>
+ * Used when bubble bar is newly created.
+ */
+ public static BubbleBarUpdate createInitialState() {
+ return new BubbleBarUpdate(true);
}
@NonNull
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 7650444..9dd4c19 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -820,14 +820,15 @@
void startIntents(PendingIntent pendingIntent1, Intent fillInIntent1,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
- PendingIntent pendingIntent2, Intent fillInIntent2,
+ @Nullable PendingIntent pendingIntent2, Intent fillInIntent2,
@Nullable ShortcutInfo shortcutInfo2, @Nullable Bundle options2,
@SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN,
"startIntents: intent1=%s intent2=%s position=%d snapPosition=%d",
- pendingIntent1.getIntent(), pendingIntent2.getIntent(), splitPosition,
- snapPosition);
+ pendingIntent1.getIntent(),
+ (pendingIntent2 != null ? pendingIntent2.getIntent() : "null"),
+ splitPosition, snapPosition);
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (pendingIntent2 == null) {
options1 = options1 != null ? options1 : new Bundle();
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 da2965c..2b12a22 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
@@ -251,9 +251,14 @@
final ActivityInfo activityInfo = windowInfo.targetActivityInfo != null
? windowInfo.targetActivityInfo
: taskInfo.topActivityInfo;
+ final boolean isEdgeToEdgeEnforced = PhoneWindow.isEdgeToEdgeEnforced(
+ activityInfo.applicationInfo, false /* local */, a);
+ if (isEdgeToEdgeEnforced) {
+ params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED;
+ }
params.layoutInDisplayCutoutMode = a.getInt(
R.styleable.Window_windowLayoutInDisplayCutoutMode,
- PhoneWindow.isEdgeToEdgeEnforced(activityInfo.applicationInfo, false /* local */, a)
+ isEdgeToEdgeEnforced
? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
: params.layoutInDisplayCutoutMode);
params.windowAnimations = a.getResourceId(R.styleable.Window_windowAnimationStyle, 0);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
index 31fc98b..da3aa4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
@@ -461,25 +461,6 @@
a.recycle();
}
- // Reset the system bar color which set by splash screen, make it align to the app.
- void clearSystemBarColor() {
- if (mRootView == null || !mRootView.isAttachedToWindow()) {
- return;
- }
- if (mRootView.getLayoutParams() instanceof WindowManager.LayoutParams) {
- final WindowManager.LayoutParams lp =
- (WindowManager.LayoutParams) mRootView.getLayoutParams();
- if (mDrawsSystemBarBackgrounds) {
- lp.flags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
- } else {
- lp.flags &= ~WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
- }
- mRootView.setLayoutParams(lp);
- }
- mRootView.getWindowInsetsController().setSystemBarsAppearance(
- mSystemBarAppearance, LIGHT_BARS_MASK);
- }
-
@Override
public boolean removeIfPossible(StartingWindowRemovalInfo info, boolean immediately) {
if (mRootView == null) {
@@ -491,7 +472,6 @@
removeWindowInner(mRootView, false);
return true;
}
- clearSystemBarColor();
if (immediately
|| mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
removeWindowInner(mRootView, false);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/extension/TaskInfo.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/extension/TaskInfo.kt
index 5dd96ac..7a64a47 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/extension/TaskInfo.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/extension/TaskInfo.kt
@@ -22,12 +22,12 @@
val TaskInfo.isTransparentCaptionBarAppearance: Boolean
get() {
- val appearance = taskDescription?.statusBarAppearance ?: 0
+ val appearance = taskDescription?.systemBarsAppearance ?: 0
return (appearance and APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND) != 0
}
val TaskInfo.isLightCaptionBarAppearance: Boolean
get() {
- val appearance = taskDescription?.statusBarAppearance ?: 0
+ val appearance = taskDescription?.systemBarsAppearance ?: 0
return (appearance and APPEARANCE_LIGHT_CAPTION_BARS) != 0
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
index 6dcae27..96bc4a1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
@@ -65,7 +65,7 @@
taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
Color.valueOf(taskDescription.statusBarColor).luminance() < 0.5
} else {
- taskDescription.statusBarAppearance and APPEARANCE_LIGHT_STATUS_BARS == 0
+ taskDescription.systemBarsAppearance and APPEARANCE_LIGHT_STATUS_BARS == 0
}
} ?: false
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
index fa0aba5..48e396a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
@@ -49,6 +49,8 @@
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.bubbles.BubbleData.TimeSource;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
+import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
import com.google.common.collect.ImmutableList;
@@ -1207,6 +1209,19 @@
assertOverflowChangedTo(ImmutableList.of());
}
+ @Test
+ public void test_getInitialStateForBubbleBar_includesInitialBubblesAndPosition() {
+ sendUpdatedEntryAtTime(mEntryA1, 1000);
+ sendUpdatedEntryAtTime(mEntryA2, 2000);
+ mPositioner.setBubbleBarLocation(BubbleBarLocation.LEFT);
+
+ BubbleBarUpdate update = mBubbleData.getInitialStateForBubbleBar();
+ assertThat(update.currentBubbleList).hasSize(2);
+ assertThat(update.currentBubbleList.get(0).getKey()).isEqualTo(mEntryA2.getKey());
+ assertThat(update.currentBubbleList.get(1).getKey()).isEqualTo(mEntryA1.getKey());
+ assertThat(update.bubbleBarLocation).isEqualTo(BubbleBarLocation.LEFT);
+ }
+
private void verifyUpdateReceived() {
verify(mListener).applyUpdate(mUpdateCaptor.capture());
reset(mListener);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/bubbles/BubbleBarLocationTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/bubbles/BubbleBarLocationTest.kt
new file mode 100644
index 0000000..27e0b19
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/bubbles/BubbleBarLocationTest.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 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.bubbles
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.common.bubbles.BubbleBarLocation.DEFAULT
+import com.android.wm.shell.common.bubbles.BubbleBarLocation.LEFT
+import com.android.wm.shell.common.bubbles.BubbleBarLocation.RIGHT
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class BubbleBarLocationTest : ShellTestCase() {
+
+ @Test
+ fun isOnLeft_rtlEnabled_defaultsToLeft() {
+ assertThat(DEFAULT.isOnLeft(isRtl = true)).isTrue()
+ }
+
+ @Test
+ fun isOnLeft_rtlDisabled_defaultsToRight() {
+ assertThat(DEFAULT.isOnLeft(isRtl = false)).isFalse()
+ }
+
+ @Test
+ fun isOnLeft_left_trueForAllLanguageDirections() {
+ assertThat(LEFT.isOnLeft(isRtl = false)).isTrue()
+ assertThat(LEFT.isOnLeft(isRtl = true)).isTrue()
+ }
+
+ @Test
+ fun isOnLeft_right_falseForAllLanguageDirections() {
+ assertThat(RIGHT.isOnLeft(isRtl = false)).isFalse()
+ assertThat(RIGHT.isOnLeft(isRtl = true)).isFalse()
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 9e62bd2..ba3f6dd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -176,7 +176,7 @@
public void updateRelayoutParams_freeformAndTransparent_allowsInputFallthrough() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
- taskInfo.taskDescription.setStatusBarAppearance(
+ taskInfo.taskDescription.setSystemBarsAppearance(
APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND);
final RelayoutParams relayoutParams = new RelayoutParams();
@@ -194,7 +194,7 @@
public void updateRelayoutParams_freeformButOpaque_disallowsInputFallthrough() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
- taskInfo.taskDescription.setStatusBarAppearance(0);
+ taskInfo.taskDescription.setSystemBarsAppearance(0);
final RelayoutParams relayoutParams = new RelayoutParams();
DesktopModeWindowDecoration.updateRelayoutParams(
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 54f94f5..4486f55 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -428,7 +428,6 @@
"jni/MovieImpl.cpp",
"jni/pdf/PdfDocument.cpp",
"jni/pdf/PdfEditor.cpp",
- "jni/pdf/PdfRenderer.cpp",
"jni/pdf/PdfUtils.cpp",
],
shared_libs: [
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 32bc122..af7a496 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -108,6 +108,10 @@
get()->mSupportFp16ForHdr = supportFp16ForHdr;
}
+void DeviceInfo::setSupportRgba10101010ForHdr(bool supportRgba10101010ForHdr) {
+ get()->mSupportRgba10101010ForHdr = supportRgba10101010ForHdr;
+}
+
void DeviceInfo::setSupportMixedColorSpaces(bool supportMixedColorSpaces) {
get()->mSupportMixedColorSpaces = supportMixedColorSpaces;
}
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index a5a841e..fb58a69 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -69,6 +69,15 @@
return get()->mSupportFp16ForHdr;
};
+ static void setSupportRgba10101010ForHdr(bool supportRgba10101010ForHdr);
+ static bool isSupportRgba10101010ForHdr() {
+ if (!Properties::hdr10bitPlus) {
+ return false;
+ }
+
+ return get()->mSupportRgba10101010ForHdr;
+ };
+
static void setSupportMixedColorSpaces(bool supportMixedColorSpaces);
static bool isSupportMixedColorSpaces() { return get()->mSupportMixedColorSpaces; };
@@ -102,6 +111,7 @@
int mMaxTextureSize;
sk_sp<SkColorSpace> mWideColorSpace = SkColorSpace::MakeSRGB();
bool mSupportFp16ForHdr = false;
+ bool mSupportRgba10101010ForHdr = false;
bool mSupportMixedColorSpaces = false;
SkColorType mWideColorType = SkColorType::kN32_SkColorType;
int mDisplaysSize = 0;
diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp
index 883f273..fb0cdb0 100644
--- a/libs/hwui/apex/jni_runtime.cpp
+++ b/libs/hwui/apex/jni_runtime.cpp
@@ -70,7 +70,6 @@
extern int register_android_graphics_fonts_FontFamily(JNIEnv* env);
extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
-extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
extern int register_android_graphics_text_MeasuredText(JNIEnv* env);
extern int register_android_graphics_text_LineBreaker(JNIEnv *env);
extern int register_android_graphics_text_TextShaper(JNIEnv *env);
@@ -142,7 +141,6 @@
REG_JNI(register_android_graphics_fonts_FontFamily),
REG_JNI(register_android_graphics_pdf_PdfDocument),
REG_JNI(register_android_graphics_pdf_PdfEditor),
- REG_JNI(register_android_graphics_pdf_PdfRenderer),
REG_JNI(register_android_graphics_text_MeasuredText),
REG_JNI(register_android_graphics_text_LineBreaker),
REG_JNI(register_android_graphics_text_TextShaper),
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index d15b1680..d9e2c8c 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -860,7 +860,8 @@
static void android_view_ThreadedRenderer_initDisplayInfo(
JNIEnv* env, jclass, jint physicalWidth, jint physicalHeight, jfloat refreshRate,
jint wideColorDataspace, jlong appVsyncOffsetNanos, jlong presentationDeadlineNanos,
- jboolean supportFp16ForHdr, jboolean supportMixedColorSpaces) {
+ jboolean supportFp16ForHdr, jboolean supportRgba10101010ForHdr,
+ jboolean supportMixedColorSpaces) {
DeviceInfo::setWidth(physicalWidth);
DeviceInfo::setHeight(physicalHeight);
DeviceInfo::setRefreshRate(refreshRate);
@@ -868,6 +869,7 @@
DeviceInfo::setAppVsyncOffsetNanos(appVsyncOffsetNanos);
DeviceInfo::setPresentationDeadlineNanos(presentationDeadlineNanos);
DeviceInfo::setSupportFp16ForHdr(supportFp16ForHdr);
+ DeviceInfo::setSupportRgba10101010ForHdr(supportRgba10101010ForHdr);
DeviceInfo::setSupportMixedColorSpaces(supportMixedColorSpaces);
}
@@ -1020,7 +1022,7 @@
{"nSetForceDark", "(JI)V", (void*)android_view_ThreadedRenderer_setForceDark},
{"nSetDisplayDensityDpi", "(I)V",
(void*)android_view_ThreadedRenderer_setDisplayDensityDpi},
- {"nInitDisplayInfo", "(IIFIJJZZ)V", (void*)android_view_ThreadedRenderer_initDisplayInfo},
+ {"nInitDisplayInfo", "(IIFIJJZZZ)V", (void*)android_view_ThreadedRenderer_initDisplayInfo},
{"preload", "()V", (void*)android_view_ThreadedRenderer_preload},
{"isWebViewOverlaysEnabled", "()Z",
(void*)android_view_ThreadedRenderer_isWebViewOverlaysEnabled},
diff --git a/libs/hwui/jni/pdf/PdfRenderer.cpp b/libs/hwui/jni/pdf/PdfRenderer.cpp
deleted file mode 100644
index cc1f961..0000000
--- a/libs/hwui/jni/pdf/PdfRenderer.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.
- */
-
-#include "PdfUtils.h"
-
-#include "GraphicsJNI.h"
-#include "SkBitmap.h"
-#include "SkMatrix.h"
-#include "fpdfview.h"
-
-#include <vector>
-#include <utils/Log.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-namespace android {
-
-static const int RENDER_MODE_FOR_DISPLAY = 1;
-static const int RENDER_MODE_FOR_PRINT = 2;
-
-static struct {
- jfieldID x;
- jfieldID y;
-} gPointClassInfo;
-
-static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPtr,
- jint pageIndex, jobject outSize) {
- FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
-
- FPDF_PAGE page = FPDF_LoadPage(document, pageIndex);
- if (!page) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "cannot load page");
- return -1;
- }
-
- double width = 0;
- double height = 0;
-
- int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height);
- if (!result) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "cannot get page size");
- return -1;
- }
-
- env->SetIntField(outSize, gPointClassInfo.x, width);
- env->SetIntField(outSize, gPointClassInfo.y, height);
-
- return reinterpret_cast<jlong>(page);
-}
-
-static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) {
- FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr);
- FPDF_ClosePage(page);
-}
-
-static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr,
- jlong bitmapPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom,
- jlong transformPtr, jint renderMode) {
- FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr);
-
- SkBitmap skBitmap;
- bitmap::toBitmap(bitmapPtr).getSkBitmap(&skBitmap);
-
- const int stride = skBitmap.width() * 4;
-
- FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(),
- FPDFBitmap_BGRA, skBitmap.getPixels(), stride);
-
- int renderFlags = FPDF_REVERSE_BYTE_ORDER;
- if (renderMode == RENDER_MODE_FOR_DISPLAY) {
- renderFlags |= FPDF_LCD_TEXT;
- } else if (renderMode == RENDER_MODE_FOR_PRINT) {
- renderFlags |= FPDF_PRINTING;
- }
-
- SkMatrix matrix = *reinterpret_cast<SkMatrix*>(transformPtr);
- SkScalar transformValues[6];
- if (!matrix.asAffine(transformValues)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "transform matrix has perspective. Only affine matrices are allowed.");
- return;
- }
-
- FS_MATRIX transform = {transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY],
- transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY],
- transformValues[SkMatrix::kATransX],
- transformValues[SkMatrix::kATransY]};
-
- FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom};
-
- FPDF_RenderPageBitmapWithMatrix(bitmap, page, &transform, &clip, renderFlags);
-
- skBitmap.notifyPixelsChanged();
-}
-
-static const JNINativeMethod gPdfRenderer_Methods[] = {
- {"nativeCreate", "(IJ)J", (void*) nativeOpen},
- {"nativeClose", "(J)V", (void*) nativeClose},
- {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
- {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting},
- {"nativeRenderPage", "(JJJIIIIJI)V", (void*) nativeRenderPage},
- {"nativeOpenPageAndGetSize", "(JILandroid/graphics/Point;)J", (void*) nativeOpenPageAndGetSize},
- {"nativeClosePage", "(J)V", (void*) nativeClosePage}
-};
-
-int register_android_graphics_pdf_PdfRenderer(JNIEnv* env) {
- int result = RegisterMethodsOrDie(
- env, "android/graphics/pdf/PdfRenderer", gPdfRenderer_Methods,
- NELEM(gPdfRenderer_Methods));
-
- jclass clazz = FindClassOrDie(env, "android/graphics/Point");
- gPointClassInfo.x = GetFieldIDOrDie(env, clazz, "x", "I");
- gPointClassInfo.y = GetFieldIDOrDie(env, clazz, "y", "I");
-
- return result;
-};
-
-};
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 326b6ed..99469d1 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -650,7 +650,11 @@
mSurfaceColorSpace = DeviceInfo::get()->getWideColorSpace();
break;
case ColorMode::Hdr:
- if (DeviceInfo::get()->isSupportFp16ForHdr()) {
+ if (DeviceInfo::get()->isSupportRgba10101010ForHdr()) {
+ mSurfaceColorType = SkColorType::kRGBA_10x6_SkColorType;
+ mSurfaceColorSpace = SkColorSpace::MakeRGB(
+ GetExtendedTransferFunction(mTargetSdrHdrRatio), SkNamedGamut::kDisplayP3);
+ } else if (DeviceInfo::get()->isSupportFp16ForHdr()) {
mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType;
mSurfaceColorSpace = SkColorSpace::MakeSRGB();
} else {
@@ -675,7 +679,8 @@
if (mColorMode == ColorMode::Hdr || mColorMode == ColorMode::Hdr10) {
mTargetSdrHdrRatio = ratio;
- if (mColorMode == ColorMode::Hdr && DeviceInfo::get()->isSupportFp16ForHdr()) {
+ if (mColorMode == ColorMode::Hdr && DeviceInfo::get()->isSupportFp16ForHdr() &&
+ !DeviceInfo::get()->isSupportRgba10101010ForHdr()) {
mSurfaceColorSpace = SkColorSpace::MakeSRGB();
} else {
mSurfaceColorSpace = SkColorSpace::MakeRGB(
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index b5f7caa..0d0af11 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -25,6 +25,7 @@
#include <android/sync.h>
#include <gui/TraceUtils.h>
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
+#include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
#include <include/gpu/ganesh/vk/GrVkBackendSurface.h>
#include <include/gpu/ganesh/vk/GrVkDirectContext.h>
#include <ui/FatVector.h>
@@ -597,15 +598,14 @@
close(fence_clone);
sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
} else {
- GrBackendSemaphore backendSemaphore;
- backendSemaphore.initVulkan(semaphore);
+ GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(semaphore);
// Skia will take ownership of the VkSemaphore and delete it once the wait
// has finished. The VkSemaphore also owns the imported fd, so it will
// close the fd when it is deleted.
- bufferInfo->skSurface->wait(1, &backendSemaphore);
+ bufferInfo->skSurface->wait(1, &beSemaphore);
// The following flush blocks the GPU immediately instead of waiting for
// other drawing ops. It seems dequeue_fence is not respected otherwise.
- // TODO: remove the flush after finding why backendSemaphore is not working.
+ // TODO: remove the flush after finding why beSemaphore is not working.
skgpu::ganesh::FlushAndSubmit(bufferInfo->skSurface.get());
}
}
@@ -626,7 +626,7 @@
SharedSemaphoreInfo(PFN_vkDestroySemaphore destroyFunction, VkDevice device,
VkSemaphore semaphore)
: mDestroyFunction(destroyFunction), mDevice(device), mSemaphore(semaphore) {
- mGrBackendSemaphore.initVulkan(semaphore);
+ mGrBackendSemaphore = GrBackendSemaphores::MakeVk(mSemaphore);
}
~SharedSemaphoreInfo() { mDestroyFunction(mDevice, mSemaphore, nullptr); }
@@ -798,8 +798,7 @@
return UNKNOWN_ERROR;
}
- GrBackendSemaphore beSemaphore;
- beSemaphore.initVulkan(semaphore);
+ GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(semaphore);
// Skia will take ownership of the VkSemaphore and delete it once the wait has finished. The
// VkSemaphore also owns the imported fd, so it will close the fd when it is deleted.
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 6dc45a6..6a32c5a 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -202,11 +202,13 @@
&& update.state.surfaceDrawn;
bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible;
bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible;
- if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
- || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
- | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
- | DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID
- | DIRTY_ICON_STYLE))))) {
+ if (update.state.surfaceControl != NULL &&
+ (becomingVisible || becomingHidden ||
+ (wantSurfaceVisibleAndDrawn &&
+ (update.state.dirty &
+ (DIRTY_ALPHA | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER |
+ DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID | DIRTY_ICON_STYLE |
+ DIRTY_DRAW_DROP_SHADOW))))) {
needApplyTransaction = true;
if (wantSurfaceVisibleAndDrawn
@@ -235,13 +237,15 @@
update.state.transformationMatrix.dtdy);
}
- if (wantSurfaceVisibleAndDrawn
- && (becomingVisible
- || (update.state.dirty & (DIRTY_HOTSPOT | DIRTY_ICON_STYLE)))) {
+ if (wantSurfaceVisibleAndDrawn &&
+ (becomingVisible ||
+ (update.state.dirty &
+ (DIRTY_HOTSPOT | DIRTY_ICON_STYLE | DIRTY_DRAW_DROP_SHADOW)))) {
Parcel p;
p.writeInt32(static_cast<int32_t>(update.state.icon.style));
p.writeFloat(update.state.icon.hotSpotX);
p.writeFloat(update.state.icon.hotSpotY);
+ p.writeBool(update.state.icon.drawNativeDropShadow);
// Pass cursor metadata in the sprite surface so that when Android is running as a
// client OS (e.g. ARC++) the host OS can get the requested cursor metadata and
@@ -388,12 +392,13 @@
uint32_t dirty;
if (icon.isValid()) {
mLocked.state.icon.bitmap = icon.bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888);
- if (!mLocked.state.icon.isValid()
- || mLocked.state.icon.hotSpotX != icon.hotSpotX
- || mLocked.state.icon.hotSpotY != icon.hotSpotY) {
+ if (!mLocked.state.icon.isValid() || mLocked.state.icon.hotSpotX != icon.hotSpotX ||
+ mLocked.state.icon.hotSpotY != icon.hotSpotY ||
+ mLocked.state.icon.drawNativeDropShadow != icon.drawNativeDropShadow) {
mLocked.state.icon.hotSpotX = icon.hotSpotX;
mLocked.state.icon.hotSpotY = icon.hotSpotY;
- dirty = DIRTY_BITMAP | DIRTY_HOTSPOT;
+ mLocked.state.icon.drawNativeDropShadow = icon.drawNativeDropShadow;
+ dirty = DIRTY_BITMAP | DIRTY_HOTSPOT | DIRTY_DRAW_DROP_SHADOW;
} else {
dirty = DIRTY_BITMAP;
}
@@ -404,7 +409,7 @@
}
} else if (mLocked.state.icon.isValid()) {
mLocked.state.icon.bitmap.reset();
- dirty = DIRTY_BITMAP | DIRTY_HOTSPOT | DIRTY_ICON_STYLE;
+ dirty = DIRTY_BITMAP | DIRTY_HOTSPOT | DIRTY_ICON_STYLE | DIRTY_DRAW_DROP_SHADOW;
} else {
return; // setting to invalid icon and already invalid so nothing to do
}
diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h
index 04ecb38..35776e9 100644
--- a/libs/input/SpriteController.h
+++ b/libs/input/SpriteController.h
@@ -151,6 +151,7 @@
DIRTY_HOTSPOT = 1 << 6,
DIRTY_DISPLAY_ID = 1 << 7,
DIRTY_ICON_STYLE = 1 << 8,
+ DIRTY_DRAW_DROP_SHADOW = 1 << 9,
};
/* Describes the state of a sprite.
diff --git a/libs/input/SpriteIcon.h b/libs/input/SpriteIcon.h
index 0939af4..7d45d02 100644
--- a/libs/input/SpriteIcon.h
+++ b/libs/input/SpriteIcon.h
@@ -40,7 +40,7 @@
PointerIconStyle style{PointerIconStyle::TYPE_NULL};
float hotSpotX{};
float hotSpotY{};
- bool drawNativeDropShadow{false};
+ bool drawNativeDropShadow{};
inline bool isValid() const { return bitmap.isValid() && !bitmap.isEmpty(); }
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 60ab1a4..a53a8ce 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -275,17 +275,23 @@
if (o == null || getClass() != o.getClass()) return false;
final AudioMix that = (AudioMix) o;
+ boolean tokenMatch = android.media.audiopolicy.Flags.audioMixOwnership()
+ ? Objects.equals(this.mToken, that.mToken)
+ : true;
return Objects.equals(this.mRouteFlags, that.mRouteFlags)
&& Objects.equals(this.mRule, that.mRule)
&& Objects.equals(this.mMixType, that.mMixType)
&& Objects.equals(this.mFormat, that.mFormat)
- && Objects.equals(this.mToken, that.mToken);
+ && tokenMatch;
}
/** @hide */
@Override
public int hashCode() {
- return Objects.hash(mRouteFlags, mRule, mMixType, mFormat, mToken);
+ if (android.media.audiopolicy.Flags.audioMixOwnership()) {
+ return Objects.hash(mRouteFlags, mRule, mMixType, mFormat, mToken);
+ }
+ return Objects.hash(mRouteFlags, mRule, mMixType, mFormat);
}
@Override
diff --git a/media/java/android/media/tv/ad/TvAdView.java b/media/java/android/media/tv/ad/TvAdView.java
index 2fac8ce..d204908 100644
--- a/media/java/android/media/tv/ad/TvAdView.java
+++ b/media/java/android/media/tv/ad/TvAdView.java
@@ -659,6 +659,11 @@
}
}
+ /** @hide */
+ public TvAdManager.Session getAdSession() {
+ return mSession;
+ }
+
private class MySessionCallback extends TvAdManager.SessionCallback {
final String mServiceId;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java
index 47caf0a..ac12884 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java
@@ -60,7 +60,7 @@
private static final int DEFAULT_SENSITIVITY = 100;
private static final long EXPOSURE_TIME_ERROR_MARGIN_NS = 100000L; // 100us, Approximation.
private static final float EXPOSURE_TIME_ERROR_MARGIN_RATE = 0.03f; // 3%, Approximation.
- private static final float SENSITIVITY_ERROR_MARGIN_RATE = 0.03f; // 3%, Approximation.
+ private static final float SENSITIVITY_ERROR_MARGIN_RATE = 0.06f; // 6%, Approximation.
private static final int DEFAULT_NUM_EXPOSURE_TIME_STEPS = 3;
private static final int DEFAULT_NUM_SENSITIVITY_STEPS = 16;
private static final int DEFAULT_SENSITIVITY_STEP_SIZE = 100;
diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types
index b795560..5cf807d 100644
--- a/mime/java-res/android.mime.types
+++ b/mime/java-res/android.mime.types
@@ -80,6 +80,7 @@
?audio/aac-adts aac
?audio/ac3 ac3 a52
?audio/amr amr
+?audio/x-gsm gsm
?audio/imelody imy
?audio/midi rtttl xmf
?audio/mobile-xmf mxmf
@@ -103,6 +104,7 @@
?image/x-adobe-dng dng
?image/x-fuji-raf raf
?image/x-icon ico
+?image/x-jg art
?image/x-nikon-nrw nrw
?image/x-panasonic-rw2 rw2
?image/x-pentax-pef pef
@@ -117,7 +119,7 @@
?text/x-vcard vcf
?video/3gpp2 3gpp2 3gp2 3g2
-?video/3gpp 3gpp
+?video/3gpp 3gpp 3gp
?video/avi avi
?video/m4v m4v
?video/mp4 m4v f4v mp4v mpeg4
@@ -153,6 +155,7 @@
audio/x-mpegurl m3u m3u8
image/jpeg jpg
image/x-ms-bmp bmp
+image/x-photoshop psd
text/plain txt
text/x-c++hdr hpp
text/x-c++src cpp
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index 54f1421..9e0bb86 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -265,10 +265,11 @@
}
@FlaggedApi("android.nfc.nfc_read_polling_loop") public final class PollingFrame implements android.os.Parcelable {
- ctor public PollingFrame(int, @Nullable byte[], int, int);
+ ctor public PollingFrame(int, @Nullable byte[], int, int, boolean);
method public int describeContents();
method @NonNull public byte[] getData();
method public int getTimestamp();
+ method public boolean getTriggeredAutoTransact();
method public int getType();
method public int getVendorSpecificGain();
method public void writeToParcel(@NonNull android.os.Parcel, int);
diff --git a/nfc/java/android/nfc/cardemulation/PollingFrame.java b/nfc/java/android/nfc/cardemulation/PollingFrame.java
index 29d7bdf..7028c8f 100644
--- a/nfc/java/android/nfc/cardemulation/PollingFrame.java
+++ b/nfc/java/android/nfc/cardemulation/PollingFrame.java
@@ -133,12 +133,23 @@
@FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
public static final String KEY_POLLING_LOOP_TIMESTAMP = "android.nfc.cardemulation.TIMESTAMP";
+ /**
+ * KEY_POLLING_LOOP_TIMESTAMP is the Bundle key for whether this polling frame triggered
+ * autoTransact in the Bundle included in MSG_POLLING_LOOP.
+ *
+ * @hide
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+ public static final String KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT =
+ "android.nfc.cardemulation.TRIGGERED_AUTOTRANSACT";
+
@PollingFrameType
private final int mType;
private final byte[] mData;
private final int mGain;
private final int mTimestamp;
+ private final boolean mTriggeredAutoTransact;
public static final @NonNull Parcelable.Creator<PollingFrame> CREATOR =
new Parcelable.Creator<>() {
@@ -159,14 +170,17 @@
mData = (data == null) ? new byte[0] : data;
mGain = frame.getInt(KEY_POLLING_LOOP_GAIN, -1);
mTimestamp = frame.getInt(KEY_POLLING_LOOP_TIMESTAMP);
+ mTriggeredAutoTransact = frame.containsKey(KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT)
+ && frame.getBoolean(KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT);
}
public PollingFrame(@PollingFrameType int type, @Nullable byte[] data,
- int gain, int timestamp) {
+ int gain, int timestamp, boolean triggeredAutoTransact) {
mType = type;
mData = data == null ? new byte[0] : data;
mGain = gain;
mTimestamp = timestamp;
+ mTriggeredAutoTransact = triggeredAutoTransact;
}
/**
@@ -210,6 +224,14 @@
return mTimestamp;
}
+ /**
+ * Returns whether this frame triggered the device to automatically disable observe mode and
+ * allow one transaction.
+ */
+ public boolean getTriggeredAutoTransact() {
+ return mTriggeredAutoTransact;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -233,6 +255,7 @@
}
frame.putByteArray(KEY_POLLING_LOOP_DATA, getData());
frame.putInt(KEY_POLLING_LOOP_TIMESTAMP, getTimestamp());
+ frame.putBoolean(KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT, getTriggeredAutoTransact());
return frame;
}
diff --git a/packages/CredentialManager/res/values-en-rCA/strings.xml b/packages/CredentialManager/res/values-en-rCA/strings.xml
index ff1de20..10d95993 100644
--- a/packages/CredentialManager/res/values-en-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-en-rCA/strings.xml
@@ -39,10 +39,8 @@
<string name="seamless_transition_detail" msgid="4475509237171739843">"As we move towards a passwordless future, passwords will still be available alongside passkeys."</string>
<string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
<string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
- <!-- no translation found for choose_create_option_passkey_title (7980430650778623135) -->
- <skip />
- <!-- no translation found for choose_create_option_password_title (6238446571944651980) -->
- <skip />
+ <string name="choose_create_option_passkey_title" msgid="7980430650778623135">"Create passkey to sign in to <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
+ <string name="choose_create_option_password_title" msgid="6238446571944651980">"Save password to sign in to <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Save sign-in info for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"password"</string>
diff --git a/packages/CredentialManager/res/values-en-rXC/strings.xml b/packages/CredentialManager/res/values-en-rXC/strings.xml
index 8ffe001..16c0d1d 100644
--- a/packages/CredentialManager/res/values-en-rXC/strings.xml
+++ b/packages/CredentialManager/res/values-en-rXC/strings.xml
@@ -39,10 +39,8 @@
<string name="seamless_transition_detail" msgid="4475509237171739843">"As we move towards a passwordless future, passwords will still be available alongside passkeys."</string>
<string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
<string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
- <!-- no translation found for choose_create_option_passkey_title (7980430650778623135) -->
- <skip />
- <!-- no translation found for choose_create_option_password_title (6238446571944651980) -->
- <skip />
+ <string name="choose_create_option_passkey_title" msgid="7980430650778623135">"Create passkey to sign in to <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
+ <string name="choose_create_option_password_title" msgid="6238446571944651980">"Save password to sign in to <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Save sign-in info for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"password"</string>
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
index d7a2e36..271cccb 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
@@ -572,6 +572,12 @@
sessionId: Int
) {
viewNode.autofillId?.let {
+ val domain = viewNode.webDomain
+ val request = viewNode.credentialManagerRequest
+ if (domain != null && request != null) {
+ responseClientState.putBoolean(
+ WEBVIEW_REQUESTED_CREDENTIAL_KEY, true)
+ }
cmRequests.addAll(getCredentialOptionsFromViewNode(viewNode, it, responseClientState,
traversedViewNodes, credentialOptionsFromHints, sessionId))
traversedViewNodes.add(it)
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
index 965ee86..99a9409 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -21,6 +21,7 @@
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@@ -94,7 +95,7 @@
label = {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(
+ modifier = Modifier.fillMaxWidth().heightIn(min = 56.dp).padding(
// Total end padding should be 16dp, but the suggestion chip itself
// has 8dp horizontal elements padding
horizontal = 8.dp, vertical = 16.dp,
@@ -258,10 +259,14 @@
onClick = onClick,
shape = Shapes.large,
label = {
- Column(modifier = Modifier.wrapContentSize()
- .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+ Column(
+ modifier = Modifier.heightIn(min = 56.dp).wrapContentSize().padding(
+ start = 16.dp, top = 16.dp, bottom = 16.dp
+ ),
+ verticalArrangement = Arrangement.Center,
+ ) {
SmallTitleText(entryHeadlineText)
- if (entrySecondLineText != null && entrySecondLineText.isNotEmpty()) {
+ if (!entrySecondLineText.isNullOrBlank()) {
BodySmallText(entrySecondLineText)
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index bc0ea02..b9c9d89 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -18,7 +18,6 @@
import android.credentials.flags.Flags.selectorUiImprovementsEnabled
import android.graphics.drawable.Drawable
-import android.text.TextUtils
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
import androidx.activity.result.IntentSenderRequest
@@ -431,6 +430,14 @@
val hasSingleEntry = primaryPageCredentialEntryList.size +
primaryPageLockedEntryList.size == 1
+ val areAllPasswordsOnPrimaryScreen = primaryPageLockedEntryList.isEmpty() &&
+ primaryPageCredentialEntryList.all {
+ it.sortedCredentialEntryList.first().credentialType == CredentialType.PASSWORD
+ }
+ val areAllPasskeysOnPrimaryScreen = primaryPageLockedEntryList.isEmpty() &&
+ primaryPageCredentialEntryList.all {
+ it.sortedCredentialEntryList.first().credentialType == CredentialType.PASSKEY
+ }
item {
if (requestDisplayInfo.preferIdentityDocUi) {
HeadlineText(
@@ -447,28 +454,30 @@
HeadlineText(
text = stringResource(
if (hasSingleEntry) {
- val singleEntryType = primaryPageCredentialEntryList.firstOrNull()
- ?.sortedCredentialEntryList?.firstOrNull()?.credentialType
- if (singleEntryType == CredentialType.PASSKEY)
+ if (areAllPasskeysOnPrimaryScreen)
R.string.get_dialog_title_use_passkey_for
- else if (singleEntryType == CredentialType.PASSWORD)
+ else if (areAllPasswordsOnPrimaryScreen)
R.string.get_dialog_title_use_password_for
else if (authenticationEntryList.isNotEmpty())
R.string.get_dialog_title_unlock_options_for
else R.string.get_dialog_title_use_sign_in_for
} else {
- if (authenticationEntryList.isNotEmpty() ||
- sortedUserNameToCredentialEntryList.any { perNameEntryList ->
- perNameEntryList.sortedCredentialEntryList.any { entry ->
- entry.credentialType != CredentialType.PASSWORD &&
- entry.credentialType != CredentialType.PASSKEY
- }
+ if (areAllPasswordsOnPrimaryScreen)
+ R.string.get_dialog_title_choose_password_for
+ else if (areAllPasskeysOnPrimaryScreen)
+ R.string.get_dialog_title_choose_passkey_for
+ else if (primaryPageLockedEntryList.isNotEmpty() ||
+ primaryPageCredentialEntryList.any {
+ it.sortedCredentialEntryList.first().credentialType !=
+ CredentialType.PASSWORD &&
+ it.sortedCredentialEntryList.first().credentialType !=
+ CredentialType.PASSKEY
}
- ) // For an unknown / locked entry, it's not true that it is
+ ) // An unknown typed / locked entry exists, and we can't say it is
// already saved, strictly speaking. Hence use a different title
- // without the mention of "saved"
+ // without the mention of "saved".
R.string.get_dialog_title_choose_sign_in_for
- else
+ else // All entries on the primary screen are passkeys or passwords
R.string.get_dialog_title_choose_saved_sign_in_for
},
requestDisplayInfo.appName
@@ -490,8 +499,11 @@
showMoreForTruncatedEntry.value = it.hasVisualOverflow
},
hasSingleEntry = hasSingleEntry,
+ hasSingleProvider = singleProviderId != null,
shouldOverrideIcon = entry.isDefaultIconPreferredAsSingleProvider &&
(singleProviderId != null),
+ shouldRemoveTypeDisplayName = areAllPasswordsOnPrimaryScreen ||
+ areAllPasskeysOnPrimaryScreen
)
}
primaryPageLockedEntryList.forEach {
@@ -754,11 +766,19 @@
enforceOneLine: Boolean = false,
onTextLayout: (TextLayoutResult) -> Unit = {},
// Make optional since the secondary page doesn't care about this value.
- hasSingleEntry: Boolean? = null,
+ hasSingleEntry: Boolean = false,
// For primary page only, if all display entries come from the same provider AND if that
// provider has opted in via isDefaultIconPreferredAsSingleProvider, then we override the
// display icon to the default icon for the given credential type.
shouldOverrideIcon: Boolean = false,
+ // For primary page only, if all entries come from the same provider, then remove that provider
+ // name from each entry, since that provider icon + name will be shown front and central at
+ // the top of the bottom sheet.
+ hasSingleProvider: Boolean = false,
+ // For primary page only, if all visible entrise are of the same type and that type is passkey
+ // or password, then set this bit to true to remove the type display name from each entry for
+ // simplification, since that info is mentioned in the title.
+ shouldRemoveTypeDisplayName: Boolean = false,
) {
val (username, displayName) = if (credentialEntryInfo.credentialType == CredentialType.PASSKEY)
userAndDisplayNameForPasskey(
@@ -788,17 +808,16 @@
entryHeadlineText = username,
entrySecondLineText = displayName,
entryThirdLineText =
- (if (hasSingleEntry != null && hasSingleEntry)
- if (credentialEntryInfo.credentialType == CredentialType.PASSKEY ||
- credentialEntryInfo.credentialType == CredentialType.PASSWORD)
- emptyList()
+ (if (hasSingleEntry)
+ if (shouldRemoveTypeDisplayName) emptyList()
// Still show the type display name for all non-password/passkey types since it won't be
// mentioned in the bottom sheet heading.
else listOf(credentialEntryInfo.credentialTypeDisplayName)
else listOf(
- credentialEntryInfo.credentialTypeDisplayName,
- credentialEntryInfo.providerDisplayName
- )).filterNot(TextUtils::isEmpty).let { itemsToDisplay ->
+ if (shouldRemoveTypeDisplayName) null
+ else credentialEntryInfo.credentialTypeDisplayName,
+ if (hasSingleProvider) null else credentialEntryInfo.providerDisplayName
+ )).filterNot{ it.isNullOrBlank() }.let { itemsToDisplay ->
if (itemsToDisplay.isEmpty()) null
else itemsToDisplay.joinToString(
separator = stringResource(R.string.get_dialog_sign_in_type_username_separator)
diff --git a/packages/PackageInstaller/res/values-el/strings.xml b/packages/PackageInstaller/res/values-el/strings.xml
index 3c37df6..6f7a433 100644
--- a/packages/PackageInstaller/res/values-el/strings.xml
+++ b/packages/PackageInstaller/res/values-el/strings.xml
@@ -48,7 +48,7 @@
<string name="update_anyway" msgid="8792432341346261969">"Να ενημερωθεί ούτως ή άλλως"</string>
<string name="manage_applications" msgid="5400164782453975580">"Διαχ. εφαρμογών"</string>
<string name="out_of_space_dlg_title" msgid="4156690013884649502">"Δεν υπάρχει χώρος"</string>
- <string name="out_of_space_dlg_text" msgid="8727714096031856231">"Δεν ήταν δυνατή η εγκατάσταση της εφαρμογής <xliff:g id="APP_NAME">%1$s</xliff:g>. Απελευθερώστε λίγο χώρο και προσπαθήστε ξανά."</string>
+ <string name="out_of_space_dlg_text" msgid="8727714096031856231">"Δεν ήταν δυνατή η εγκατάσταση της εφαρμογής <xliff:g id="APP_NAME">%1$s</xliff:g>. Αποδεσμεύστε λίγο χώρο και προσπαθήστε ξανά."</string>
<string name="app_not_found_dlg_title" msgid="5107924008597470285">"Η εφαρμογή δεν βρέθηκε"</string>
<string name="app_not_found_dlg_text" msgid="5219983779377811611">"Η εφαρμογή δεν βρέθηκε στη λίστα εγκατεστημένων εφαρμογών."</string>
<string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"Δεν επιτρέπεται"</string>
diff --git a/packages/PackageInstaller/res/values-fr-feminine/strings.xml b/packages/PackageInstaller/res/values-fr-feminine/strings.xml
new file mode 100644
index 0000000..c6b8de7
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fr-feminine/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 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:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Votre téléphone et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être la seule responsable de tout dommage causé à votre téléphone ou de toute perte de données pouvant découler de son utilisation."</string>
+ <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Votre tablette et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être la seule responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de son utilisation."</string>
+ <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Votre téléviseur et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être la seule responsable de tout dommage causé à votre téléviseur ou de toute perte de données pouvant découler de son utilisation."</string>
+ <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Vous n\'êtes pas connectée"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fr-masculine/strings.xml b/packages/PackageInstaller/res/values-fr-masculine/strings.xml
new file mode 100644
index 0000000..b4a40a0
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fr-masculine/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 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:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Votre téléphone et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre téléphone ou de toute perte de données pouvant découler de son utilisation."</string>
+ <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Votre tablette et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de son utilisation."</string>
+ <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Votre téléviseur et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre téléviseur ou de toute perte de données pouvant découler de son utilisation."</string>
+ <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Vous n\'êtes pas connecté"</string>
+</resources>
diff --git a/packages/PackageInstaller/res/values-fr-neuter/strings.xml b/packages/PackageInstaller/res/values-fr-neuter/strings.xml
new file mode 100644
index 0000000..9362b33
--- /dev/null
+++ b/packages/PackageInstaller/res/values-fr-neuter/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2007 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:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Votre téléphone et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être l\'unique responsable de tout dommage causé à votre téléphone ou de toute perte de données pouvant découler de son utilisation."</string>
+ <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Votre tablette et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être l\'unique responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de son utilisation."</string>
+ <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Votre téléviseur et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être l\'unique responsable de tout dommage causé à votre téléviseur ou de toute perte de données pouvant découler de son utilisation."</string>
+ <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Vous n\'êtes pas connecté·e"</string>
+</resources>
diff --git a/packages/SettingsLib/DataStore/Android.bp b/packages/SettingsLib/DataStore/Android.bp
index 868a4a5..9fafcab 100644
--- a/packages/SettingsLib/DataStore/Android.bp
+++ b/packages/SettingsLib/DataStore/Android.bp
@@ -11,6 +11,8 @@
static_libs: [
"androidx.annotation_annotation",
"androidx.collection_collection-ktx",
+ "androidx.core_core-ktx",
"guava",
],
+ kotlincflags: ["-Xjvm-default=all"],
}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupCodec.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupCodec.kt
new file mode 100644
index 0000000..550645f
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupCodec.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import androidx.annotation.IntDef
+import java.io.InputStream
+import java.io.OutputStream
+import java.util.zip.Deflater
+import java.util.zip.DeflaterOutputStream
+import java.util.zip.InflaterInputStream
+
+/** Unique id of the codec. */
+@Target(AnnotationTarget.TYPE)
+@IntDef(
+ BackupCodecId.NO_OP.toInt(),
+ BackupCodecId.ZIP.toInt(),
+)
+@Retention(AnnotationRetention.SOURCE)
+annotation class BackupCodecId {
+ companion object {
+ /** Unknown reason of the change. */
+ const val NO_OP: Byte = 0
+ /** Data is updated. */
+ const val ZIP: Byte = 1
+ }
+}
+
+/** How to encode/decode the backup data. */
+interface BackupCodec {
+ /** Unique id of the codec. */
+ val id: @BackupCodecId Byte
+
+ /** Name of the codec. */
+ val name: String
+
+ /** Encodes the backup data. */
+ fun encode(outputStream: OutputStream): OutputStream
+
+ /** Decodes the backup data. */
+ fun decode(inputStream: InputStream): InputStream
+
+ companion object {
+ @JvmStatic
+ fun fromId(id: @BackupCodecId Byte): BackupCodec =
+ when (id) {
+ BackupCodecId.NO_OP -> BackupNoOpCodec()
+ BackupCodecId.ZIP -> BackupZipCodec.BEST_COMPRESSION
+ else -> throw IllegalArgumentException("Unknown codec id $id")
+ }
+ }
+}
+
+/** Codec without any additional encoding/decoding. */
+class BackupNoOpCodec : BackupCodec {
+ override val id
+ get() = BackupCodecId.NO_OP
+
+ override val name
+ get() = "N/A"
+
+ override fun encode(outputStream: OutputStream) = outputStream
+
+ override fun decode(inputStream: InputStream) = inputStream
+}
+
+/** Codec with ZIP compression. */
+class BackupZipCodec(
+ private val compressionLevel: Int,
+ override val name: String,
+) : BackupCodec {
+ override val id
+ get() = BackupCodecId.ZIP
+
+ override fun encode(outputStream: OutputStream) =
+ DeflaterOutputStream(outputStream, Deflater(compressionLevel))
+
+ override fun decode(inputStream: InputStream) = InflaterInputStream(inputStream)
+
+ companion object {
+ val DEFAULT_COMPRESSION = BackupZipCodec(Deflater.DEFAULT_COMPRESSION, "ZipDefault")
+ val BEST_COMPRESSION = BackupZipCodec(Deflater.BEST_COMPRESSION, "ZipBestCompression")
+ val BEST_SPEED = BackupZipCodec(Deflater.BEST_SPEED, "ZipBestSpeed")
+ }
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreContext.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreContext.kt
index c6d6f77..8fe618d 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreContext.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreContext.kt
@@ -20,7 +20,6 @@
import android.app.backup.BackupDataOutput
import android.app.backup.BackupHelper
import android.os.Build
-import android.os.ParcelFileDescriptor
import androidx.annotation.RequiresApi
/**
@@ -31,23 +30,8 @@
*/
class BackupContext
internal constructor(
- /**
- * An open, read-only file descriptor pointing to the last backup state provided by the
- * application. May be null, in which case no prior state is being provided and the application
- * should perform a full backup.
- *
- * TODO: the state should support marshall/unmarshall for incremental back up.
- */
- val oldState: ParcelFileDescriptor?,
-
/** An open, read/write BackupDataOutput pointing to the backup data destination. */
private val data: BackupDataOutput,
-
- /**
- * An open, read/write file descriptor pointing to an empty file. The application should record
- * the final backup.
- */
- val newState: ParcelFileDescriptor,
) {
/**
* The quota in bytes for the application's current backup operation.
@@ -68,5 +52,9 @@
@RequiresApi(Build.VERSION_CODES.P) get() = data.transportFlags
}
-/** Context for restore. */
-class RestoreContext(val key: String)
+/**
+ * Context for restore.
+ *
+ * @param key Entity key
+ */
+class RestoreContext internal constructor(val key: String)
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreEntity.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreEntity.kt
index 6a7ef5a..817ee4c 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreEntity.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreEntity.kt
@@ -36,6 +36,13 @@
val key: String
/**
+ * Codec used to encode/decode the backup data.
+ *
+ * When it is null, the [BackupRestoreStorage.defaultCodec] will be used.
+ */
+ fun codec(): BackupCodec? = null
+
+ /**
* Backs up the entity.
*
* @param backupContext context for backup
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileArchiver.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileArchiver.kt
new file mode 100644
index 0000000..621a8d7
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileArchiver.kt
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.app.backup.BackupDataInputStream
+import android.content.Context
+import android.util.Log
+import java.io.File
+import java.io.InputStream
+import java.io.OutputStream
+import java.util.zip.CheckedInputStream
+
+/**
+ * File archiver to handle backup and restore for all the [BackupRestoreFileStorage] subclasses.
+ *
+ * Compared with [android.app.backup.FileBackupHelper], this class supports forward-compatibility
+ * like the [com.google.android.libraries.backup.PersistentBackupAgentHelper]: the app does not need
+ * to know the list of files in advance at restore time.
+ */
+internal class BackupRestoreFileArchiver(
+ private val context: Context,
+ private val fileStorages: List<BackupRestoreFileStorage>,
+) : BackupRestoreStorage() {
+ override val name: String
+ get() = "file_archiver"
+
+ override fun createBackupRestoreEntities(): List<BackupRestoreEntity> =
+ fileStorages.map { it.toBackupRestoreEntity() }
+
+ override fun wrapBackupOutputStream(codec: BackupCodec, outputStream: OutputStream) =
+ outputStream
+
+ override fun wrapRestoreInputStream(codec: BackupCodec, inputStream: InputStream) = inputStream
+
+ override fun restoreEntity(data: BackupDataInputStream) {
+ val key = data.key
+ val fileStorage = fileStorages.firstOrNull { it.storageFilePath == key }
+ val file =
+ if (fileStorage != null) {
+ if (!fileStorage.enableRestore()) {
+ Log.i(LOG_TAG, "[$name] $key restore disabled")
+ return
+ }
+ fileStorage.restoreFile
+ } else { // forward-compatibility
+ Log.i(LOG_TAG, "Restore unknown file $key")
+ File(context.dataDirCompat, key)
+ }
+ Log.i(LOG_TAG, "[$name] Restore ${data.size()} bytes for $key to $file")
+ val inputStream = LimitedNoCloseInputStream(data)
+ checksum.reset()
+ val checkedInputStream = CheckedInputStream(inputStream, checksum)
+ try {
+ val codec = BackupCodec.fromId(checkedInputStream.read().toByte())
+ if (fileStorage != null && fileStorage.defaultCodec().id != codec.id) {
+ Log.i(
+ LOG_TAG,
+ "[$name] $key different codec: ${codec.id}, ${fileStorage.defaultCodec().id}"
+ )
+ }
+ file.parentFile?.mkdirs() // ensure parent folders are created
+ val wrappedInputStream = codec.decode(checkedInputStream)
+ val bytesCopied = file.outputStream().use { wrappedInputStream.copyTo(it) }
+ Log.i(LOG_TAG, "[$name] $key restore $bytesCopied bytes with ${codec.name}")
+ fileStorage?.onRestoreFinished(file)
+ entityStates[key] = checksum.value
+ } catch (e: Exception) {
+ Log.e(LOG_TAG, "[$name] Fail to restore $key", e)
+ }
+ }
+
+ override fun onRestoreFinished() {
+ fileStorages.forEach { it.onRestoreFinished() }
+ }
+}
+
+private fun BackupRestoreFileStorage.toBackupRestoreEntity() =
+ object : BackupRestoreEntity {
+ override val key: String
+ get() = storageFilePath
+
+ override fun backup(
+ backupContext: BackupContext,
+ outputStream: OutputStream,
+ ): EntityBackupResult {
+ if (!enableBackup(backupContext)) {
+ Log.i(LOG_TAG, "[$name] $key backup disabled")
+ return EntityBackupResult.INTACT
+ }
+ val file = backupFile
+ prepareBackup(file)
+ if (!file.exists()) {
+ Log.i(LOG_TAG, "[$name] $key not exist")
+ return EntityBackupResult.DELETE
+ }
+ val codec = codec() ?: defaultCodec()
+ // MUST close to flush the data
+ wrapBackupOutputStream(codec, outputStream).use { stream ->
+ val bytesCopied = file.inputStream().use { it.copyTo(stream) }
+ Log.i(LOG_TAG, "[$name] $key backup $bytesCopied bytes with ${codec.name}")
+ }
+ onBackupFinished(file)
+ return EntityBackupResult.UPDATE
+ }
+
+ override fun restore(restoreContext: RestoreContext, inputStream: InputStream) {
+ // no-op, BackupRestoreFileArchiver#restoreEntity will restore files
+ }
+ }
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileStorage.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileStorage.kt
new file mode 100644
index 0000000..b531bd1
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreFileStorage.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.content.Context
+import androidx.core.content.ContextCompat
+import java.io.File
+
+/**
+ * A file-based storage with backup and restore support.
+ *
+ * [BackupRestoreFileArchiver] will handle the backup and restore based on file path for all
+ * subclasses.
+ *
+ * @param context Context to retrieve data dir
+ * @param storageFilePath Storage file path, which MUST be relative to the [Context.getDataDir]
+ * folder. This is used as the entity name for backup and restore.
+ */
+abstract class BackupRestoreFileStorage(
+ val context: Context,
+ val storageFilePath: String,
+) : BackupRestoreStorage() {
+
+ /** The absolute path of the file to backup. */
+ open val backupFile: File
+ get() = File(context.dataDirCompat, storageFilePath)
+
+ /** The absolute path of the file to restore. */
+ open val restoreFile: File
+ get() = backupFile
+
+ fun checkFilePaths() {
+ if (storageFilePath.isEmpty() || storageFilePath[0] == File.separatorChar) {
+ throw IllegalArgumentException("$storageFilePath is not valid path")
+ }
+ if (!backupFile.isAbsolute) {
+ throw IllegalArgumentException("backupFile is not absolute")
+ }
+ if (!restoreFile.isAbsolute) {
+ throw IllegalArgumentException("restoreFile is not absolute")
+ }
+ }
+
+ /**
+ * Callback before [backupFile] is backed up.
+ *
+ * @param file equals to [backupFile]
+ */
+ open fun prepareBackup(file: File) {}
+
+ /**
+ * Callback when [backupFile] is restored.
+ *
+ * @param file equals to [backupFile]
+ */
+ open fun onBackupFinished(file: File) {}
+
+ /**
+ * Callback when [restoreFile] is restored.
+ *
+ * @param file equals to [restoreFile]
+ */
+ open fun onRestoreFinished(file: File) {}
+
+ final override fun createBackupRestoreEntities(): List<BackupRestoreEntity> = listOf()
+}
+
+internal val Context.dataDirCompat: File
+ get() = ContextCompat.getDataDir(this)!!
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorage.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorage.kt
index 88d9dd6..ea2fb72 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorage.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorage.kt
@@ -22,11 +22,20 @@
import android.app.backup.BackupHelper
import android.os.ParcelFileDescriptor
import android.util.Log
+import androidx.collection.MutableScatterMap
import com.google.common.io.ByteStreams
import java.io.ByteArrayOutputStream
+import java.io.DataInputStream
+import java.io.DataOutputStream
+import java.io.EOFException
+import java.io.FileInputStream
+import java.io.FileOutputStream
import java.io.FilterInputStream
import java.io.InputStream
import java.io.OutputStream
+import java.util.zip.CRC32
+import java.util.zip.CheckedInputStream
+import java.util.zip.CheckedOutputStream
internal const val LOG_TAG = "BackupRestoreStorage"
@@ -47,15 +56,33 @@
private val entities: List<BackupRestoreEntity> by lazy { createBackupRestoreEntities() }
+ /**
+ * Checksum of the data.
+ *
+ * Always call [java.util.zip.Checksum.reset] before using it.
+ */
+ protected val checksum = CRC32()
+
+ /**
+ * Entity states represented by checksum.
+ *
+ * Map key is the entity key, map value is the checksum of backup data.
+ */
+ protected val entityStates = MutableScatterMap<String, Long>()
+
/** Entities to back up and restore. */
abstract fun createBackupRestoreEntities(): List<BackupRestoreEntity>
+ /** Default codec used to encode/decode the entity data. */
+ open fun defaultCodec(): BackupCodec = BackupZipCodec.BEST_COMPRESSION
+
override fun performBackup(
oldState: ParcelFileDescriptor?,
data: BackupDataOutput,
newState: ParcelFileDescriptor,
) {
- val backupContext = BackupContext(oldState, data, newState)
+ oldState.readEntityStates(entityStates)
+ val backupContext = BackupContext(data)
if (!enableBackup(backupContext)) {
Log.i(LOG_TAG, "[$name] Backup disabled")
return
@@ -64,38 +91,57 @@
for (entity in entities) {
val key = entity.key
val outputStream = ByteArrayOutputStream()
+ checksum.reset()
+ val checkedOutputStream = CheckedOutputStream(outputStream, checksum)
+ val codec = entity.codec() ?: defaultCodec()
val result =
try {
- entity.backup(backupContext, wrapBackupOutputStream(outputStream))
+ entity.backup(backupContext, wrapBackupOutputStream(codec, checkedOutputStream))
} catch (exception: Exception) {
Log.e(LOG_TAG, "[$name] Fail to backup entity $key", exception)
continue
}
when (result) {
EntityBackupResult.UPDATE -> {
- val payload = outputStream.toByteArray()
- val size = payload.size
- data.writeEntityHeader(key, size)
- data.writeEntityData(payload, size)
- Log.i(LOG_TAG, "[$name] Backup entity $key: $size bytes")
+ if (updateEntityState(key)) {
+ val payload = outputStream.toByteArray()
+ val size = payload.size
+ data.writeEntityHeader(key, size)
+ data.writeEntityData(payload, size)
+ Log.i(LOG_TAG, "[$name] Backup entity $key: $size bytes")
+ } else {
+ Log.i(
+ LOG_TAG,
+ "[$name] Backup entity $key unchanged: ${outputStream.size()} bytes"
+ )
+ }
}
EntityBackupResult.INTACT -> {
Log.i(LOG_TAG, "[$name] Backup entity $key intact")
}
EntityBackupResult.DELETE -> {
+ entityStates.remove(key)
data.writeEntityHeader(key, -1)
Log.i(LOG_TAG, "[$name] Backup entity $key deleted")
}
}
}
+ newState.writeEntityStates(entityStates)
Log.i(LOG_TAG, "[$name] Backup end")
}
+ private fun updateEntityState(key: String): Boolean {
+ val value = checksum.value
+ return entityStates.put(key, value) != value
+ }
+
/** Returns if backup is enabled. */
open fun enableBackup(backupContext: BackupContext): Boolean = true
- fun wrapBackupOutputStream(outputStream: OutputStream): OutputStream {
- return outputStream
+ open fun wrapBackupOutputStream(codec: BackupCodec, outputStream: OutputStream): OutputStream {
+ // write a codec id header for safe restore
+ outputStream.write(codec.id.toInt())
+ return codec.encode(outputStream)
}
override fun restoreEntity(data: BackupDataInputStream) {
@@ -111,8 +157,13 @@
}
Log.i(LOG_TAG, "[$name] Restore $key: ${data.size()} bytes")
val restoreContext = RestoreContext(key)
+ val codec = entity.codec() ?: defaultCodec()
+ val inputStream = LimitedNoCloseInputStream(data)
+ checksum.reset()
+ val checkedInputStream = CheckedInputStream(inputStream, checksum)
try {
- entity.restore(restoreContext, wrapRestoreInputStream(data))
+ entity.restore(restoreContext, wrapRestoreInputStream(codec, checkedInputStream))
+ entityStates[key] = checksum.value
} catch (exception: Exception) {
Log.e(LOG_TAG, "[$name] Fail to restore entity $key", exception)
}
@@ -121,11 +172,76 @@
/** Returns if restore is enabled. */
open fun enableRestore(): Boolean = true
- fun wrapRestoreInputStream(inputStream: BackupDataInputStream): InputStream {
- return LimitedNoCloseInputStream(inputStream)
+ open fun wrapRestoreInputStream(
+ codec: BackupCodec,
+ inputStream: InputStream,
+ ): InputStream {
+ // read the codec id first to check if it is expected codec
+ val id = inputStream.read()
+ val expectedId = codec.id.toInt()
+ if (id == expectedId) return codec.decode(inputStream)
+ Log.i(LOG_TAG, "Expect codec id $expectedId but got $id")
+ return BackupCodec.fromId(id.toByte()).decode(inputStream)
}
- override fun writeNewStateDescription(newState: ParcelFileDescriptor) {}
+ final override fun writeNewStateDescription(newState: ParcelFileDescriptor) {
+ newState.writeEntityStates(entityStates)
+ onRestoreFinished()
+ }
+
+ /** Callbacks when restore finished. */
+ open fun onRestoreFinished() {}
+
+ private fun ParcelFileDescriptor?.readEntityStates(state: MutableScatterMap<String, Long>) {
+ state.clear()
+ if (this == null) return
+ // do not close the streams
+ val fileInputStream = FileInputStream(fileDescriptor)
+ val dataInputStream = DataInputStream(fileInputStream)
+ try {
+ val version = dataInputStream.readByte()
+ if (version != STATE_VERSION) {
+ Log.w(
+ LOG_TAG,
+ "[$name] Unexpected state version, read:$version, expected:$STATE_VERSION"
+ )
+ return
+ }
+ var count = dataInputStream.readInt()
+ while (count-- > 0) {
+ val key = dataInputStream.readUTF()
+ val checksum = dataInputStream.readLong()
+ state[key] = checksum
+ }
+ } catch (exception: Exception) {
+ if (exception is EOFException) {
+ Log.d(LOG_TAG, "[$name] Hit EOF when read state file")
+ } else {
+ Log.e(LOG_TAG, "[$name] Fail to read state file", exception)
+ }
+ state.clear()
+ }
+ }
+
+ private fun ParcelFileDescriptor.writeEntityStates(state: MutableScatterMap<String, Long>) {
+ // do not close the streams
+ val fileOutputStream = FileOutputStream(fileDescriptor)
+ val dataOutputStream = DataOutputStream(fileOutputStream)
+ try {
+ dataOutputStream.writeByte(STATE_VERSION.toInt())
+ dataOutputStream.writeInt(state.size)
+ state.forEach { key, value ->
+ dataOutputStream.writeUTF(key)
+ dataOutputStream.writeLong(value)
+ }
+ } catch (exception: Exception) {
+ Log.e(LOG_TAG, "[$name] Fail to write state file", exception)
+ }
+ }
+
+ companion object {
+ private const val STATE_VERSION: Byte = 0
+ }
}
/**
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt
index 221e2e8..0e39493 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/BackupRestoreStorageManager.kt
@@ -46,12 +46,22 @@
/**
* Adds all the registered [BackupRestoreStorage] as the helpers of given [BackupAgentHelper].
*
+ * All [BackupRestoreFileStorage]s will be wrapped as a single [BackupRestoreFileArchiver].
+ *
* @see BackupAgentHelper.addHelper
*/
fun addBackupAgentHelpers(backupAgentHelper: BackupAgentHelper) {
+ val fileStorages = mutableListOf<BackupRestoreFileStorage>()
for ((keyPrefix, storage) in storages) {
- backupAgentHelper.addHelper(keyPrefix, storage)
+ if (storage is BackupRestoreFileStorage) {
+ fileStorages.add(storage)
+ } else {
+ backupAgentHelper.addHelper(keyPrefix, storage)
+ }
}
+ // Always add file archiver even fileStorages is empty to handle forward compatibility
+ val fileArchiver = BackupRestoreFileArchiver(application, fileStorages)
+ backupAgentHelper.addHelper(fileArchiver.name, fileArchiver)
}
/**
@@ -87,6 +97,7 @@
* The storage MUST implement [KeyedObservable] or [Observable].
*/
fun add(storage: BackupRestoreStorage) {
+ if (storage is BackupRestoreFileStorage) storage.checkFilePaths()
val name = storage.name
val oldStorage = storages.put(name, storage)
if (oldStorage != null) {
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
new file mode 100644
index 0000000..0c1b417
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.content.Context
+import android.content.SharedPreferences
+import android.os.Build
+import android.util.Log
+import androidx.core.content.ContextCompat
+import java.io.File
+
+/**
+ * [SharedPreferences] based storage.
+ *
+ * The backup and restore is handled by [BackupRestoreFileArchiver] to achieve forward-compatibility
+ * just like `PersistentBackupAgentHelper`.
+ *
+ * Simple file based backup and restore is not safe, which incurs multi-thread file writes in
+ * SharedPreferences file. Additionally, SharedPreferences has in-memory state, so reload is needed.
+ * However, there is no public reload API on SharedPreferences and listeners are not notified in
+ * current private implementation. As such, an intermediate SharedPreferences file is introduced for
+ * backup and restore.
+ *
+ * Note that existing entries in the SharedPreferences will NOT be deleted before restore.
+ *
+ * @param context Context to get SharedPreferences
+ * @param name Name of the SharedPreferences
+ * @param mode Operating mode, see [Context.getSharedPreferences]
+ * @param verbose Verbose logging on key/value pairs during backup/restore. Enable for dev only!
+ * @param filter Filter of key/value pairs for backup and restore.
+ */
+class SharedPreferencesStorage
+@JvmOverloads
+constructor(
+ context: Context,
+ override val name: String,
+ mode: Int,
+ private val verbose: Boolean = (Build.TYPE == "eng"),
+ private val filter: (String, Any?) -> Boolean = { _, _ -> true },
+) :
+ BackupRestoreFileStorage(context, context.getSharedPreferencesFilePath(name)),
+ KeyedObservable<String> by KeyedDataObservable() {
+
+ private val sharedPreferences = context.getSharedPreferences(name, mode)
+
+ /** Name of the intermediate SharedPreferences. */
+ private val intermediateName: String
+ get() = "_br_$name"
+
+ private val intermediateSharedPreferences: SharedPreferences
+ get() {
+ // use MODE_MULTI_PROCESS to ensure a reload
+ return context.getSharedPreferences(intermediateName, Context.MODE_MULTI_PROCESS)
+ }
+
+ private val sharedPreferencesListener =
+ SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
+ if (key != null) {
+ notifyChange(key, ChangeReason.UPDATE)
+ } else {
+ // On Android >= R, SharedPreferences.Editor.clear() will trigger this case
+ notifyChange(ChangeReason.DELETE)
+ }
+ }
+
+ init {
+ // listener is weakly referenced, so unregister is optional
+ sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferencesListener)
+ }
+
+ override val backupFile: File
+ // use a different file to avoid multi-thread file write
+ get() = context.getSharedPreferencesFile(intermediateName)
+
+ override fun prepareBackup(file: File) {
+ val editor = intermediateSharedPreferences.merge(sharedPreferences.all, "Backup")
+ // commit to ensure data is write to disk synchronously
+ if (!editor.commit()) {
+ Log.w(LOG_TAG, "[$name] fail to commit")
+ }
+ }
+
+ override fun onBackupFinished(file: File) {
+ intermediateSharedPreferences.delete(intermediateName)
+ }
+
+ override fun onRestoreFinished(file: File) {
+ // Unregister listener to avoid notify observer during restore because there might be
+ // dependency between keys. BackupRestoreStorageManager.onRestoreFinished will notify
+ // observers consistently once restore finished.
+ sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener)
+ val restored = intermediateSharedPreferences
+ val editor = sharedPreferences.merge(restored.all, "Restore")
+ editor.apply() // apply to avoid blocking
+ sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferencesListener)
+ // clear the intermediate SharedPreferences
+ restored.delete(intermediateName)
+ }
+
+ private fun SharedPreferences.delete(name: String) {
+ if (deleteSharedPreferences(name)) {
+ Log.i(LOG_TAG, "SharedPreferences $name deleted")
+ } else {
+ edit().clear().apply()
+ }
+ }
+
+ private fun deleteSharedPreferences(name: String): Boolean =
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ context.deleteSharedPreferences(name)
+ } else {
+ false
+ }
+
+ private fun SharedPreferences.merge(
+ entries: Map<String, Any?>,
+ operation: String
+ ): SharedPreferences.Editor {
+ val editor = edit()
+ for ((key, value) in entries) {
+ if (!filter.invoke(key, value)) {
+ if (verbose) Log.v(LOG_TAG, "[$name] $operation skips $key=$value")
+ continue
+ }
+ when (value) {
+ is Boolean -> {
+ editor.putBoolean(key, value)
+ if (verbose) Log.v(LOG_TAG, "[$name] $operation Boolean $key=$value")
+ }
+ is Float -> {
+ editor.putFloat(key, value)
+ if (verbose) Log.v(LOG_TAG, "[$name] $operation Float $key=$value")
+ }
+ is Int -> {
+ editor.putInt(key, value)
+ if (verbose) Log.v(LOG_TAG, "[$name] $operation Int $key=$value")
+ }
+ is Long -> {
+ editor.putLong(key, value)
+ if (verbose) Log.v(LOG_TAG, "[$name] $operation Long $key=$value")
+ }
+ is String -> {
+ editor.putString(key, value)
+ if (verbose) Log.v(LOG_TAG, "[$name] $operation String $key=$value")
+ }
+ is Set<*> -> {
+ val nonString = value.firstOrNull { it !is String }
+ if (nonString != null) {
+ Log.e(
+ LOG_TAG,
+ "[$name] $operation StringSet $key=$value" +
+ " but non string found: $nonString (${nonString.javaClass})",
+ )
+ } else {
+ @Suppress("UNCHECKED_CAST") editor.putStringSet(key, value as Set<String>)
+ if (verbose) Log.v(LOG_TAG, "[$name] $operation StringSet $key=$value")
+ }
+ }
+ else -> {
+ Log.e(
+ LOG_TAG,
+ "[$name] $operation $key=$value, unknown type: ${value?.javaClass}"
+ )
+ }
+ }
+ }
+ return editor
+ }
+
+ companion object {
+ private fun Context.getSharedPreferencesFilePath(name: String): String {
+ val file = getSharedPreferencesFile(name)
+ return file.relativeTo(ContextCompat.getDataDir(this)!!).toString()
+ }
+
+ /** Returns the absolute path of shared preferences file. */
+ @JvmStatic
+ fun Context.getSharedPreferencesFile(name: String): File {
+ // ContextImpl.getSharedPreferencesPath is private
+ return File(getSharedPreferencesDir(), "$name.xml")
+ }
+
+ private fun Context.getSharedPreferencesDir() = File(dataDirCompat, "shared_prefs")
+ }
+}
diff --git a/packages/SettingsLib/Spa/build.gradle.kts b/packages/SettingsLib/Spa/build.gradle.kts
index 335725c..c755623 100644
--- a/packages/SettingsLib/Spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/build.gradle.kts
@@ -29,7 +29,7 @@
allprojects {
extra["androidTop"] = androidTop
- extra["jetpackComposeVersion"] = "1.7.0-alpha03"
+ extra["jetpackComposeVersion"] = "1.7.0-alpha04"
}
subprojects {
diff --git a/packages/SettingsLib/Spa/gradle/libs.versions.toml b/packages/SettingsLib/Spa/gradle/libs.versions.toml
index 609a82e..ff2a1e8 100644
--- a/packages/SettingsLib/Spa/gradle/libs.versions.toml
+++ b/packages/SettingsLib/Spa/gradle/libs.versions.toml
@@ -15,7 +15,7 @@
#
[versions]
-agp = "8.2.2"
+agp = "8.3.0"
compose-compiler = "1.5.10"
dexmaker-mockito = "2.28.3"
jvm = "17"
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.6-bin.zip b/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.6-bin.zip
new file mode 100644
index 0000000..5c96347
--- /dev/null
+++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-8.6-bin.zip
Binary files differ
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
index 516749d..50ff9df 100644
--- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
@@ -16,8 +16,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
-networkTimeout=10000
-validateDistributionUrl=true
+distributionUrl=gradle-8.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts
index a193a2f..f2b9235 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/spa/build.gradle.kts
@@ -57,13 +57,13 @@
api("androidx.slice:slice-builders:1.1.0-alpha02")
api("androidx.slice:slice-core:1.1.0-alpha02")
api("androidx.slice:slice-view:1.1.0-alpha02")
- api("androidx.compose.material3:material3:1.3.0-alpha01")
+ api("androidx.compose.material3:material3:1.3.0-alpha02")
api("androidx.compose.material:material-icons-extended:$jetpackComposeVersion")
api("androidx.compose.runtime:runtime-livedata:$jetpackComposeVersion")
api("androidx.compose.ui:ui-tooling-preview:$jetpackComposeVersion")
api("androidx.lifecycle:lifecycle-livedata-ktx")
api("androidx.lifecycle:lifecycle-runtime-compose")
- api("androidx.navigation:navigation-compose:2.8.0-alpha02")
+ api("androidx.navigation:navigation-compose:2.8.0-alpha03")
api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha")
api("com.google.android.material:material:1.7.0-alpha03")
debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion")
diff --git a/packages/SettingsLib/res/values-fr-feminine/strings.xml b/packages/SettingsLib/res/values-fr-feminine/strings.xml
new file mode 100644
index 0000000..377c42c
--- /dev/null
+++ b/packages/SettingsLib/res/values-fr-feminine/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2015 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"L\'association vous permet d\'accéder à vos contacts et à l\'historique des appels lorsque vous êtes connectée."</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-fr-masculine/strings.xml b/packages/SettingsLib/res/values-fr-masculine/strings.xml
new file mode 100644
index 0000000..5f7d58a
--- /dev/null
+++ b/packages/SettingsLib/res/values-fr-masculine/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2015 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"L\'association vous permet d\'accéder à vos contacts et à l\'historique des appels lorsque vous êtes connecté."</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-fr-neuter/strings.xml b/packages/SettingsLib/res/values-fr-neuter/strings.xml
new file mode 100644
index 0000000..6970587
--- /dev/null
+++ b/packages/SettingsLib/res/values-fr-neuter/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2015 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"L\'association vous permet d\'accéder à vos contacts et à l\'historique des appels lorsque vous êtes connecté·e."</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index e3c1f65b..3353374 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -457,8 +457,7 @@
<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_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – הטעינה הושהתה כדי להגן על הסוללה"</string>
- <!-- no translation found for power_incompatible_charging_settings_home_page (1322050766135126880) -->
- <skip />
+ <string name="power_incompatible_charging_settings_home_page" msgid="1322050766135126880">"<xliff:g id="LEVEL">%1$s</xliff:g> – צריך לבדוק את אביזר הטעינה"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1076561255466053220">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"הזמן הנותר על סמך השימוש שלך: בערך <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 8aac7f1..c540945 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -457,8 +457,7 @@
<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_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> — uzlāde apturēta, lai aizsargātu akumulatoru"</string>
- <!-- no translation found for power_incompatible_charging_settings_home_page (1322050766135126880) -->
- <skip />
+ <string name="power_incompatible_charging_settings_home_page" msgid="1322050766135126880">"<xliff:g id="LEVEL">%1$s</xliff:g> — pārbaudiet uzlādes piederumu"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1076561255466053220">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Ņemot vērā lietojumu, atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java
index ff4d4dd..2b8c2dd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java
@@ -37,6 +37,23 @@
*/
// TODO - b/293578081: Remove once PackageNotAvailableException is propagated to library clients.
/* package */ final class NoOpInfoMediaManager extends InfoMediaManager {
+ /**
+ * Placeholder routing session to return as active session of {@link NoOpInfoMediaManager}.
+ *
+ * <p>Returning this routing session avoids crashes in {@link InfoMediaManager} and maintains
+ * the same client-facing behaviour as if no routing session was found for the target package
+ * name.
+ *
+ * <p>Volume and max volume are set to {@code -1} to emulate a non-existing routing session in
+ * {@link #getSessionVolume()} and {@link #getSessionVolumeMax()}.
+ */
+ private static final RoutingSessionInfo PLACEHOLDER_SESSION =
+ new RoutingSessionInfo.Builder(
+ /* id */ "FAKE_ROUTING_SESSION", /* clientPackageName */ "")
+ .addSelectedRoute(/* routeId */ "FAKE_SELECTED_ROUTE_ID")
+ .setVolumeMax(-1)
+ .setVolume(-1)
+ .build();
NoOpInfoMediaManager(
Context context,
@@ -118,7 +135,7 @@
@NonNull
@Override
protected List<RoutingSessionInfo> getRoutingSessionsForPackage() {
- return Collections.emptyList();
+ return List.of(PLACEHOLDER_SESSION);
}
@Nullable
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/data/repository/SpatializerRepository.kt b/packages/SettingsLib/src/com/android/settingslib/media/data/repository/SpatializerRepository.kt
index a5c63be..7e3f38b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/data/repository/SpatializerRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/media/data/repository/SpatializerRepository.kt
@@ -18,23 +18,18 @@
import android.media.AudioDeviceAttributes
import android.media.Spatializer
-import androidx.concurrent.futures.DirectExecutor
import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.callbackFlow
-import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
interface SpatializerRepository {
- /** Returns true when head tracking is enabled and false the otherwise. */
- val isHeadTrackingAvailable: StateFlow<Boolean>
+ /**
+ * Returns true when head tracking is available for the [audioDeviceAttributes] and false the
+ * otherwise.
+ */
+ suspend fun isHeadTrackingAvailableForDevice(
+ audioDeviceAttributes: AudioDeviceAttributes
+ ): Boolean
/**
* Returns true when Spatial audio feature is supported for the [audioDeviceAttributes] and
@@ -65,22 +60,14 @@
class SpatializerRepositoryImpl(
private val spatializer: Spatializer,
- coroutineScope: CoroutineScope,
private val backgroundContext: CoroutineContext,
) : SpatializerRepository {
- override val isHeadTrackingAvailable: StateFlow<Boolean> =
- callbackFlow {
- val listener =
- Spatializer.OnHeadTrackerAvailableListener { _, available ->
- launch { send(available) }
- }
- spatializer.addOnHeadTrackerAvailableListener(DirectExecutor.INSTANCE, listener)
- awaitClose { spatializer.removeOnHeadTrackerAvailableListener(listener) }
- }
- .onStart { emit(spatializer.isHeadTrackerAvailable) }
- .flowOn(backgroundContext)
- .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), false)
+ override suspend fun isHeadTrackingAvailableForDevice(
+ audioDeviceAttributes: AudioDeviceAttributes
+ ): Boolean {
+ return withContext(backgroundContext) { spatializer.hasHeadTracker(audioDeviceAttributes) }
+ }
override suspend fun isSpatialAudioAvailableForDevice(
audioDeviceAttributes: AudioDeviceAttributes
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/domain/interactor/SpatializerInteractor.kt b/packages/SettingsLib/src/com/android/settingslib/media/domain/interactor/SpatializerInteractor.kt
index 0347403..5589733 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/domain/interactor/SpatializerInteractor.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/media/domain/interactor/SpatializerInteractor.kt
@@ -18,17 +18,17 @@
import android.media.AudioDeviceAttributes
import com.android.settingslib.media.data.repository.SpatializerRepository
-import kotlinx.coroutines.flow.StateFlow
class SpatializerInteractor(private val repository: SpatializerRepository) {
- /** Checks if head tracking is available. */
- val isHeadTrackingAvailable: StateFlow<Boolean>
- get() = repository.isHeadTrackingAvailable
-
+ /** Checks if spatial audio is available. */
suspend fun isSpatialAudioAvailable(audioDeviceAttributes: AudioDeviceAttributes): Boolean =
repository.isSpatialAudioAvailableForDevice(audioDeviceAttributes)
+ /** Checks if head tracking is available. */
+ suspend fun isHeadTrackingAvailable(audioDeviceAttributes: AudioDeviceAttributes): Boolean =
+ repository.isHeadTrackingAvailableForDevice(audioDeviceAttributes)
+
/** Checks if spatial audio is enabled for the [audioDeviceAttributes]. */
suspend fun isSpatialAudioEnabled(audioDeviceAttributes: AudioDeviceAttributes): Boolean =
repository.getSpatialAudioCompatibleDevices().contains(audioDeviceAttributes)
diff --git a/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractor.kt b/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractor.kt
index 794cf83..7719c4b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractor.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractor.kt
@@ -48,6 +48,9 @@
/** Checks if [notificationPolicy] allows media. */
val isMediaAllowed: Flow<Boolean?> = notificationPolicy.map { it?.allowMedia() }
+ /** Checks if [notificationPolicy] allows system sounds. */
+ val isSystemAllowed: Flow<Boolean?> = notificationPolicy.map { it?.allowSystem() }
+
/** Checks if [notificationPolicy] allows ringer. */
val isRingerAllowed: Flow<Boolean?> =
notificationPolicy.map { policy ->
@@ -62,31 +65,29 @@
areAlarmsAllowed.filterNotNull(),
isMediaAllowed.filterNotNull(),
isRingerAllowed.filterNotNull(),
- ) { zenMode, areAlarmsAllowed, isMediaAllowed, isRingerAllowed ->
- if (zenMode.zenMode == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS) {
- return@combine true
+ isSystemAllowed.filterNotNull(),
+ ) { zenMode, areAlarmsAllowed, isMediaAllowed, isRingerAllowed, isSystemAllowed ->
+ when (zenMode.zenMode) {
+ // Everything is muted
+ Settings.Global.ZEN_MODE_NO_INTERRUPTIONS -> return@combine true
+ Settings.Global.ZEN_MODE_ALARMS ->
+ return@combine stream.value == AudioManager.STREAM_RING ||
+ stream.value == AudioManager.STREAM_NOTIFICATION ||
+ stream.value == AudioManager.STREAM_SYSTEM
+ Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS -> {
+ when {
+ stream.value == AudioManager.STREAM_ALARM && !areAlarmsAllowed ->
+ return@combine true
+ stream.value == AudioManager.STREAM_MUSIC && !isMediaAllowed ->
+ return@combine true
+ stream.value == AudioManager.STREAM_SYSTEM && !isSystemAllowed ->
+ return@combine true
+ (stream.value == AudioManager.STREAM_RING ||
+ stream.value == AudioManager.STREAM_NOTIFICATION) && !isRingerAllowed ->
+ return@combine true
+ }
+ }
}
-
- val isNotificationOrRing =
- stream.value == AudioManager.STREAM_RING ||
- stream.value == AudioManager.STREAM_NOTIFICATION
- if (isNotificationOrRing && zenMode.zenMode == Settings.Global.ZEN_MODE_ALARMS) {
- return@combine true
- }
- if (zenMode.zenMode != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
- return@combine false
- }
-
- if (stream.value == AudioManager.STREAM_ALARM && !areAlarmsAllowed) {
- return@combine true
- }
- if (stream.value == AudioManager.STREAM_MUSIC && !isMediaAllowed) {
- return@combine true
- }
- if (isNotificationOrRing && !isRingerAllowed) {
- return@combine true
- }
-
return@combine false
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java
new file mode 100644
index 0000000..d630301
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/NoOpInfoMediaManagerTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.media;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/**
+ * Tests for {@link NoOpInfoMediaManager} to avoid exceptions in {@link InfoMediaManager}.
+ *
+ * <p>While {@link NoOpInfoMediaManager} should not perform any actions, it should still return
+ * placeholder information in certain cases to not change the behaviour of {@link InfoMediaManager}
+ * and prevent crashes.
+ */
+@RunWith(RobolectricTestRunner.class)
+public class NoOpInfoMediaManagerTest {
+ private InfoMediaManager mInfoMediaManager;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = ApplicationProvider.getApplicationContext();
+ mInfoMediaManager =
+ new NoOpInfoMediaManager(
+ mContext,
+ /* packageName */ "FAKE_PACKAGE_NAME",
+ /* localBluetoothManager */ null);
+ }
+
+ @Test
+ public void getSessionVolumeMax_returnsNotFound() {
+ assertThat(mInfoMediaManager.getSessionVolumeMax()).isEqualTo(-1);
+ }
+
+ @Test
+ public void getSessionVolume_returnsNotFound() {
+ assertThat(mInfoMediaManager.getSessionVolume()).isEqualTo(-1);
+ }
+
+ @Test
+ public void getSessionName_returnsNull() {
+ assertThat(mInfoMediaManager.getSessionName()).isNull();
+ }
+
+ @Test
+ public void getRoutingSessionForPackage_returnsPlaceholderSession() {
+ // Make sure we return a placeholder routing session so that we avoid OOB exceptions.
+ assertThat(mInfoMediaManager.getRoutingSessionsForPackage()).hasSize(1);
+ }
+
+ @Test
+ public void getSelectedMediaDevices_returnsEmptyList() {
+ assertThat(mInfoMediaManager.getSelectedMediaDevices()).isEmpty();
+ }
+}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 04cb88d..40e39e9 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -302,6 +302,7 @@
"androidx.activity_activity-compose",
"androidx.compose.animation_animation-graphics",
],
+ skip_jarjar_repackage: true,
}
android_library {
@@ -352,6 +353,7 @@
test: true,
extra_check_modules: ["SystemUILintChecker"],
},
+ skip_jarjar_repackage: true,
}
android_app {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 12e8f57..98591e9 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -273,6 +273,9 @@
<!-- to control accessibility volume -->
<uses-permission android:name="android.permission.CHANGE_ACCESSIBILITY_VOLUME" />
+ <!-- to change spatial audio -->
+ <uses-permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS" />
+
<!-- to access ResolverRankerServices -->
<uses-permission android:name="android.permission.BIND_RESOLVER_RANKER_SERVICE" />
diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/volume/panel/component/spatialaudio/SpatialAudioModule.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/volume/panel/component/spatialaudio/SpatialAudioModule.kt
new file mode 100644
index 0000000..a066b38
--- /dev/null
+++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/volume/panel/component/spatialaudio/SpatialAudioModule.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2024 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.volume.panel.component.spatialaudio
+
+import dagger.Module
+
+@Module interface SpatialAudioModule
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 078da1c86..eb6d303 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -66,6 +66,7 @@
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
@@ -74,6 +75,7 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
@@ -93,6 +95,7 @@
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
@@ -118,6 +121,7 @@
import com.android.systemui.communal.ui.compose.extensions.observeTapsWithoutConsuming
import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel
+import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.res.R
import kotlinx.coroutines.launch
@@ -150,6 +154,8 @@
val contentPadding = gridContentPadding(viewModel.isEditMode, toolbarSize)
val contentOffset = beforeContentPadding(contentPadding).toOffset()
+ ScrollOnNewSmartspaceEffect(viewModel, gridState)
+
Box(
modifier =
modifier
@@ -218,6 +224,17 @@
widgetConfigurator = widgetConfigurator,
)
+ // TODO(b/326060686): Remove this once keyguard indication area can persist over hub
+ if (viewModel is CommunalViewModel) {
+ val isUnlocked by viewModel.deviceUnlocked.collectAsState(initial = false)
+ LockStateIcon(
+ modifier =
+ Modifier.align(Alignment.BottomCenter)
+ .padding(bottom = Dimensions.LockIconBottomPadding),
+ isUnlocked = isUnlocked,
+ )
+ }
+
if (viewModel.isEditMode && onOpenWidgetPicker != null && onEditDone != null) {
Toolbar(
isDraggingToRemove = isDraggingToRemove,
@@ -266,6 +283,34 @@
}
}
+@Composable
+private fun ScrollOnNewSmartspaceEffect(
+ viewModel: BaseCommunalViewModel,
+ gridState: LazyGridState
+) {
+ val communalContent by viewModel.communalContent.collectAsState(initial = emptyList())
+ var smartspaceCount by remember { mutableStateOf(0) }
+
+ LaunchedEffect(communalContent) {
+ snapshotFlow { gridState.firstVisibleItemIndex }
+ .collect { index ->
+ val existingSmartspaceCount = smartspaceCount
+ smartspaceCount = communalContent.count { it.isSmartspace() }
+ val firstIndex = communalContent.indexOfFirst { it.isSmartspace() }
+
+ // Scroll to the beginning of the smartspace area whenever the number of
+ // smartspace elements grows
+ if (
+ existingSmartspaceCount < smartspaceCount &&
+ !viewModel.isEditMode &&
+ index > firstIndex
+ ) {
+ gridState.animateScrollToItem(firstIndex)
+ }
+ }
+ }
+}
+
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun BoxScope.CommunalHubLazyGrid(
@@ -364,6 +409,26 @@
}
}
+@Composable
+private fun LockStateIcon(
+ isUnlocked: Boolean,
+ modifier: Modifier = Modifier,
+) {
+ val colors = LocalAndroidColorScheme.current
+ val resource =
+ if (isUnlocked) {
+ R.drawable.ic_unlocked
+ } else {
+ R.drawable.ic_lock
+ }
+ Icon(
+ painter = painterResource(id = resource),
+ contentDescription = null,
+ tint = colors.onPrimaryContainer,
+ modifier = modifier.size(Dimensions.LockIconSize),
+ )
+}
+
/**
* Toolbar that contains action buttons to
* 1) open the widget picker
@@ -923,6 +988,9 @@
horizontal = ToolbarButtonPaddingHorizontal,
)
val IconSize = 48.dp
+
+ val LockIconSize = 52.dp
+ val LockIconBottomPadding = 70.dp
}
private object Colors {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/modifier/BurnInModifiers.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/modifier/BurnInModifiers.kt
index 0728daf..2a99039 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/modifier/BurnInModifiers.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/modifier/BurnInModifiers.kt
@@ -26,6 +26,7 @@
import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel
import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
import com.android.systemui.keyguard.ui.viewmodel.BurnInScaleViewModel
+import kotlinx.coroutines.flow.map
/**
* Modifies the composable to account for anti-burn in translation, alpha, and scaling.
@@ -38,9 +39,18 @@
params: BurnInParameters,
isClock: Boolean = false,
): Modifier {
- val translationX by viewModel.translationX(params).collectAsState(initial = 0f)
- val translationY by viewModel.translationY(params).collectAsState(initial = 0f)
- val scaleViewModel by viewModel.scale(params).collectAsState(initial = BurnInScaleViewModel())
+ val burnIn = viewModel.movement(params)
+ val translationX by burnIn.map { it.translationX.toFloat() }.collectAsState(initial = 0f)
+ val translationY by burnIn.map { it.translationY.toFloat() }.collectAsState(initial = 0f)
+ val scaleViewModel by
+ burnIn
+ .map {
+ BurnInScaleViewModel(
+ scale = it.scale,
+ scaleClockOnly = it.scaleClockOnly,
+ )
+ }
+ .collectAsState(initial = BurnInScaleViewModel())
return this.graphicsLayer {
val scale =
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt
new file mode 100644
index 0000000..ae267e2
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2024 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.volume.panel.component.selector.ui.composable
+
+import androidx.compose.animation.core.animateOffsetAsState
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.CornerSize
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.CornerRadius
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.onGloballyPositioned
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.dp
+
+/**
+ * Radio button group for the Volume Panel. It allows selecting a single item
+ *
+ * @param indicatorBackgroundPadding is the distance between the edge of the indicator and the
+ * indicator background
+ * @param labelIndicatorBackgroundSpacing is the distance between indicator background and labels
+ * row
+ */
+@Composable
+fun VolumePanelRadioButtonBar(
+ modifier: Modifier = Modifier,
+ indicatorBackgroundPadding: Dp =
+ VolumePanelRadioButtonBarDefaults.DefaultIndicatorBackgroundPadding,
+ spacing: Dp = VolumePanelRadioButtonBarDefaults.DefaultSpacing,
+ labelIndicatorBackgroundSpacing: Dp =
+ VolumePanelRadioButtonBarDefaults.DefaultLabelIndicatorBackgroundSpacing,
+ indicatorCornerRadius: CornerRadius =
+ VolumePanelRadioButtonBarDefaults.defaultIndicatorCornerRadius(),
+ indicatorBackgroundCornerSize: CornerSize =
+ CornerSize(VolumePanelRadioButtonBarDefaults.DefaultIndicatorBackgroundCornerRadius),
+ colors: VolumePanelRadioButtonBarColors = VolumePanelRadioButtonBarDefaults.defaultColors(),
+ content: VolumePanelRadioButtonBarScope.() -> Unit
+) {
+ val scope =
+ VolumePanelRadioButtonBarScopeImpl().apply(content).apply {
+ require(hasSelectedItem) { "At least one item should be selected" }
+ }
+
+ val items = scope.items
+
+ var selectedIndex by remember { mutableIntStateOf(items.indexOfFirst { it.isSelected }) }
+
+ var size by remember { mutableStateOf(IntSize(0, 0)) }
+ val spacingPx = with(LocalDensity.current) { spacing.toPx() }
+ val indicatorWidth = size.width / items.size - (spacingPx * (items.size - 1) / items.size)
+ val offset by
+ animateOffsetAsState(
+ targetValue =
+ Offset(
+ selectedIndex * indicatorWidth + (spacingPx * selectedIndex),
+ 0f,
+ ),
+ label = "VolumePanelRadioButtonOffsetAnimation",
+ finishedListener = {
+ for (itemIndex in items.indices) {
+ val item = items[itemIndex]
+ if (itemIndex == selectedIndex) {
+ item.onItemSelected()
+ break
+ }
+ }
+ }
+ )
+
+ Column(modifier = modifier) {
+ Box(modifier = Modifier.height(IntrinsicSize.Max)) {
+ Canvas(
+ modifier =
+ Modifier.fillMaxSize()
+ .background(
+ colors.indicatorBackgroundColor,
+ RoundedCornerShape(indicatorBackgroundCornerSize),
+ )
+ .padding(indicatorBackgroundPadding)
+ .onGloballyPositioned { size = it.size }
+ ) {
+ drawRoundRect(
+ color = colors.indicatorColor,
+ topLeft = offset,
+ size = Size(indicatorWidth, size.height.toFloat()),
+ cornerRadius = indicatorCornerRadius,
+ )
+ }
+ Row(
+ modifier = Modifier.padding(indicatorBackgroundPadding),
+ horizontalArrangement = Arrangement.spacedBy(spacing)
+ ) {
+ for (itemIndex in items.indices) {
+ TextButton(
+ modifier = Modifier.weight(1f),
+ onClick = { selectedIndex = itemIndex },
+ ) {
+ val item = items[itemIndex]
+ if (item.icon !== Empty) {
+ with(items[itemIndex]) { icon() }
+ }
+ }
+ }
+ }
+ }
+
+ Row(
+ modifier =
+ Modifier.padding(
+ start = indicatorBackgroundPadding,
+ top = labelIndicatorBackgroundSpacing,
+ end = indicatorBackgroundPadding
+ ),
+ horizontalArrangement = Arrangement.spacedBy(spacing),
+ ) {
+ for (itemIndex in items.indices) {
+ TextButton(
+ modifier = Modifier.weight(1f),
+ onClick = { selectedIndex = itemIndex },
+ ) {
+ val item = items[itemIndex]
+ if (item.icon !== Empty) {
+ with(items[itemIndex]) { label() }
+ }
+ }
+ }
+ }
+ }
+}
+
+data class VolumePanelRadioButtonBarColors(
+ /** Color of the indicator. */
+ val indicatorColor: Color,
+ /** Color of the indicator background. */
+ val indicatorBackgroundColor: Color,
+)
+
+object VolumePanelRadioButtonBarDefaults {
+
+ val DefaultIndicatorBackgroundPadding = 8.dp
+ val DefaultSpacing = 24.dp
+ val DefaultLabelIndicatorBackgroundSpacing = 12.dp
+ val DefaultIndicatorCornerRadius = 20.dp
+ val DefaultIndicatorBackgroundCornerRadius = 20.dp
+
+ @Composable
+ fun defaultIndicatorCornerRadius(
+ x: Dp = DefaultIndicatorCornerRadius,
+ y: Dp = DefaultIndicatorCornerRadius,
+ ): CornerRadius = with(LocalDensity.current) { CornerRadius(x.toPx(), y.toPx()) }
+
+ /**
+ * Returns the default VolumePanelRadioButtonBar colors.
+ *
+ * @param indicatorColor is the color of the indicator
+ * @param indicatorBackgroundColor is the color of the indicator background
+ */
+ @Composable
+ fun defaultColors(
+ indicatorColor: Color = MaterialTheme.colorScheme.primaryContainer,
+ indicatorBackgroundColor: Color = MaterialTheme.colorScheme.surface,
+ ): VolumePanelRadioButtonBarColors =
+ VolumePanelRadioButtonBarColors(
+ indicatorColor = indicatorColor,
+ indicatorBackgroundColor = indicatorBackgroundColor,
+ )
+}
+
+/** [VolumePanelRadioButtonBar] content scope. Use [item] to add more items. */
+interface VolumePanelRadioButtonBarScope {
+
+ /**
+ * Adds a single item to the radio button group.
+ *
+ * @param isSelected true when the item is selected and false the otherwise
+ * @param onItemSelected is called when the item is selected
+ * @param icon of the to show in the indicator bar
+ * @param label to show below the indicator bar for the corresponding [icon]
+ */
+ fun item(
+ isSelected: Boolean,
+ onItemSelected: () -> Unit,
+ icon: @Composable RowScope.() -> Unit = Empty,
+ label: @Composable RowScope.() -> Unit = Empty,
+ )
+}
+
+private val Empty: @Composable RowScope.() -> Unit = {}
+
+private class VolumePanelRadioButtonBarScopeImpl : VolumePanelRadioButtonBarScope {
+
+ var hasSelectedItem: Boolean = false
+ private set
+
+ private val mutableItems: MutableList<Item> = mutableListOf()
+ val items: List<Item> = mutableItems
+
+ override fun item(
+ isSelected: Boolean,
+ onItemSelected: () -> Unit,
+ icon: @Composable RowScope.() -> Unit,
+ label: @Composable RowScope.() -> Unit,
+ ) {
+ require(!isSelected || !hasSelectedItem) { "Only one item should be selected at a time" }
+ hasSelectedItem = hasSelectedItem || isSelected
+ mutableItems.add(
+ Item(
+ isSelected = isSelected,
+ onItemSelected = onItemSelected,
+ icon = icon,
+ label = label,
+ )
+ )
+ }
+}
+
+private class Item(
+ val isSelected: Boolean,
+ val onItemSelected: () -> Unit,
+ val icon: @Composable RowScope.() -> Unit,
+ val label: @Composable RowScope.() -> Unit,
+)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/SpatialAudioModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/SpatialAudioModule.kt
new file mode 100644
index 0000000..da29d58
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/SpatialAudioModule.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 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.volume.panel.component.spatialaudio
+
+import com.android.systemui.volume.panel.component.button.ui.composable.ButtonComponent
+import com.android.systemui.volume.panel.component.shared.model.VolumePanelComponents
+import com.android.systemui.volume.panel.component.spatial.domain.SpatialAudioAvailabilityCriteria
+import com.android.systemui.volume.panel.component.spatial.ui.viewmodel.SpatialAudioViewModel
+import com.android.systemui.volume.panel.component.spatialaudio.ui.composable.SpatialAudioPopup
+import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
+import com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.IntoMap
+import dagger.multibindings.StringKey
+
+/** Dagger module, that provides Spatial Audio Volume Panel UI functionality. */
+@Module
+interface SpatialAudioModule {
+
+ @Binds
+ @IntoMap
+ @StringKey(VolumePanelComponents.SPATIAL_AUDIO)
+ fun bindComponentAvailabilityCriteria(
+ criteria: SpatialAudioAvailabilityCriteria
+ ): ComponentAvailabilityCriteria
+
+ companion object {
+
+ @Provides
+ @IntoMap
+ @StringKey(VolumePanelComponents.SPATIAL_AUDIO)
+ fun provideVolumePanelUiComponent(
+ viewModel: SpatialAudioViewModel,
+ popup: SpatialAudioPopup,
+ ): VolumePanelUiComponent = ButtonComponent(viewModel.spatialAudioButton, popup::show)
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt
new file mode 100644
index 0000000..bed0ae8
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 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.volume.panel.component.spatialaudio.ui.composable
+
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.SideEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import com.android.systemui.animation.Expandable
+import com.android.systemui.common.ui.compose.Icon
+import com.android.systemui.common.ui.compose.toColor
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.volume.panel.component.popup.ui.composable.VolumePanelPopup
+import com.android.systemui.volume.panel.component.selector.ui.composable.VolumePanelRadioButtonBar
+import com.android.systemui.volume.panel.component.spatial.ui.viewmodel.SpatialAudioViewModel
+import javax.inject.Inject
+
+class SpatialAudioPopup
+@Inject
+constructor(
+ private val viewModel: SpatialAudioViewModel,
+ private val volumePanelPopup: VolumePanelPopup,
+) {
+
+ /** Shows a popup with the [expandable] animation. */
+ fun show(expandable: Expandable) {
+ volumePanelPopup.show(expandable, { Title() }, { Content(it) })
+ }
+
+ @Composable
+ private fun Title() {
+ Text(
+ text = stringResource(R.string.volume_panel_spatial_audio_title),
+ style = MaterialTheme.typography.titleMedium,
+ textAlign = TextAlign.Center,
+ maxLines = 1,
+ )
+ }
+
+ @Composable
+ private fun Content(dialog: SystemUIDialog) {
+ val isAvailable by viewModel.isAvailable.collectAsState()
+
+ if (!isAvailable) {
+ SideEffect { dialog.dismiss() }
+ return
+ }
+
+ val enabledModelStates by viewModel.spatialAudioButtonByEnabled.collectAsState()
+ if (enabledModelStates.isEmpty()) {
+ return
+ }
+ VolumePanelRadioButtonBar {
+ for (buttonViewModel in enabledModelStates) {
+ item(
+ isSelected = buttonViewModel.button.isChecked,
+ onItemSelected = { viewModel.setEnabled(buttonViewModel.model) },
+ icon = {
+ Icon(
+ icon = buttonViewModel.button.icon,
+ tint = buttonViewModel.iconColor.toColor(),
+ )
+ },
+ label = {
+ Text(
+ text = buttonViewModel.button.label.toString(),
+ style = MaterialTheme.typography.labelMedium,
+ color = buttonViewModel.labelColor.toColor(),
+ )
+ }
+ )
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 563aad1..8f802b8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -39,6 +39,7 @@
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel.Companion.POPUP_AUTO_HIDE_TIMEOUT_MS
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -113,6 +114,7 @@
kosmos.communalInteractor,
kosmos.communalTutorialInteractor,
kosmos.shadeInteractor,
+ kosmos.deviceEntryInteractor,
mediaHost,
logcatLogBuffer("CommunalViewModelTest"),
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/homecontrols/HomeControlsDreamServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/homecontrols/HomeControlsDreamServiceTest.kt
index 0a3aea7..723f6a2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/homecontrols/HomeControlsDreamServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/homecontrols/HomeControlsDreamServiceTest.kt
@@ -27,6 +27,8 @@
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.wakelock.WakeLockFake
+import com.google.common.truth.Truth.assertThat
import java.util.Optional
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -44,6 +46,9 @@
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
+ private lateinit var fakeWakeLockBuilder: WakeLockFake.Builder
+ private lateinit var fakeWakeLock: WakeLockFake
+
@Mock private lateinit var taskFragmentComponentFactory: TaskFragmentComponent.Factory
@Mock private lateinit var taskFragmentComponent: TaskFragmentComponent
@Mock private lateinit var activity: Activity
@@ -57,6 +62,10 @@
whenever(taskFragmentComponentFactory.create(any(), any(), any(), any()))
.thenReturn(taskFragmentComponent)
+ fakeWakeLock = WakeLockFake()
+ fakeWakeLockBuilder = WakeLockFake.Builder(context)
+ fakeWakeLockBuilder.setWakeLock(fakeWakeLock)
+
whenever(controlsComponent.getControlsListingController())
.thenReturn(Optional.of(controlsListingController))
@@ -87,12 +96,29 @@
verify(taskFragmentComponentFactory, never()).create(any(), any(), any(), any())
}
+ @Test
+ fun testAttachWindow_wakeLockAcquired() =
+ testScope.runTest {
+ underTest.onAttachedToWindow()
+ assertThat(fakeWakeLock.isHeld).isTrue()
+ }
+ @Test
+ fun testDetachWindow_wakeLockCanBeReleased() =
+ testScope.runTest {
+ underTest.onAttachedToWindow()
+ assertThat(fakeWakeLock.isHeld).isTrue()
+
+ underTest.onDetachedFromWindow()
+ assertThat(fakeWakeLock.isHeld).isFalse()
+ }
+
private fun buildService(activityProvider: DreamActivityProvider): HomeControlsDreamService =
with(kosmos) {
return HomeControlsDreamService(
controlsSettingsRepository = FakeControlsSettingsRepository(),
taskFragmentFactory = taskFragmentComponentFactory,
homeControlsComponentInteractor = homeControlsComponentInteractor,
+ fakeWakeLockBuilder,
dreamActivityProvider = activityProvider,
bgDispatcher = testDispatcher,
logBuffer = logcatLogBuffer("HomeControlsDreamServiceTest")
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 128b465..19b80da 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -25,7 +25,6 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
-import com.android.systemui.common.shared.model.Position
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.DozeMachine
import com.android.systemui.doze.DozeTransitionCallback
@@ -152,24 +151,6 @@
}
@Test
- fun clockPosition() =
- testScope.runTest {
- assertThat(underTest.clockPosition.value).isEqualTo(Position(0, 0))
-
- underTest.setClockPosition(0, 1)
- assertThat(underTest.clockPosition.value).isEqualTo(Position(0, 1))
-
- underTest.setClockPosition(1, 9)
- assertThat(underTest.clockPosition.value).isEqualTo(Position(1, 9))
-
- underTest.setClockPosition(1, 0)
- assertThat(underTest.clockPosition.value).isEqualTo(Position(1, 0))
-
- underTest.setClockPosition(3, 1)
- assertThat(underTest.clockPosition.value).isEqualTo(Position(3, 1))
- }
-
- @Test
fun dozeTimeTick() =
testScope.runTest {
val lastDozeTimeTick by collectLastValue(underTest.dozeTimeTick)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModelTest.kt
new file mode 100644
index 0000000..87d1cd5
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModelTest.kt
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2024 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.keyguard.ui.viewmodel
+
+import android.hardware.fingerprint.FingerprintManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.shared.model.FaceFailureMessage
+import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.FingerprintFailureMessage
+import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthenticationStatus
+import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AlternateBouncerMessageAreaViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val fingerprintAuthRepository by lazy {
+ kosmos.fakeDeviceEntryFingerprintAuthRepository
+ }
+ private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository }
+ private val bouncerRepository by lazy { kosmos.fakeKeyguardBouncerRepository }
+ private val biometricSettingsRepository by lazy { kosmos.fakeBiometricSettingsRepository }
+ private val underTest: AlternateBouncerMessageAreaViewModel =
+ kosmos.alternateBouncerMessageAreaViewModel
+
+ @Before
+ fun setUp() {
+ biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+ biometricSettingsRepository.setIsFaceAuthCurrentlyAllowed(true)
+ }
+
+ @Test
+ fun noInitialValue() =
+ testScope.runTest {
+ val message by collectLastValue(underTest.message)
+ bouncerRepository.setAlternateVisible(true)
+ assertThat(message).isNull()
+ }
+
+ @Test
+ fun fingerprintMessage() =
+ testScope.runTest {
+ val message by collectLastValue(underTest.message)
+ bouncerRepository.setAlternateVisible(true)
+ runCurrent()
+ fingerprintAuthRepository.setAuthenticationStatus(FailFingerprintAuthenticationStatus)
+ assertThat(message).isInstanceOf(FingerprintFailureMessage::class.java)
+ }
+
+ @Test
+ fun fingerprintLockoutMessage_notShown() =
+ testScope.runTest {
+ val message by collectLastValue(underTest.message)
+ bouncerRepository.setAlternateVisible(true)
+ runCurrent()
+ fingerprintAuthRepository.setAuthenticationStatus(
+ ErrorFingerprintAuthenticationStatus(
+ msgId = FingerprintManager.FINGERPRINT_ERROR_LOCKOUT,
+ msg = "test lockout",
+ )
+ )
+ assertThat(message).isNull()
+ }
+
+ @Test
+ fun alternateBouncerNotVisible_messagesNeverShow() =
+ testScope.runTest {
+ val message by collectLastValue(underTest.message)
+ bouncerRepository.setAlternateVisible(false)
+ runCurrent()
+ fingerprintAuthRepository.setAuthenticationStatus(FailFingerprintAuthenticationStatus)
+ assertThat(message).isNull()
+
+ faceAuthRepository.setAuthenticationStatus(FailedFaceAuthenticationStatus())
+ assertThat(message).isNull()
+ }
+
+ @Test
+ fun faceFailMessage() =
+ testScope.runTest {
+ val message by collectLastValue(underTest.message)
+ bouncerRepository.setAlternateVisible(true)
+ runCurrent()
+ faceAuthRepository.setAuthenticationStatus(FailedFaceAuthenticationStatus())
+ assertThat(message).isInstanceOf(FaceFailureMessage::class.java)
+ }
+
+ @Test
+ fun faceThenFingerprintMessage() =
+ testScope.runTest {
+ val message by collectLastValue(underTest.message)
+ bouncerRepository.setAlternateVisible(true)
+ runCurrent()
+ faceAuthRepository.setAuthenticationStatus(FailedFaceAuthenticationStatus())
+ assertThat(message).isInstanceOf(FaceFailureMessage::class.java)
+
+ fingerprintAuthRepository.setAuthenticationStatus(FailFingerprintAuthenticationStatus)
+ assertThat(message).isInstanceOf(FingerprintFailureMessage::class.java)
+ }
+
+ @Test
+ fun fingerprintMessagePreventsFaceMessageFromShowing() =
+ testScope.runTest {
+ val message by collectLastValue(underTest.message)
+ bouncerRepository.setAlternateVisible(true)
+ runCurrent()
+ fingerprintAuthRepository.setAuthenticationStatus(FailFingerprintAuthenticationStatus)
+ assertThat(message).isInstanceOf(FingerprintFailureMessage::class.java)
+
+ faceAuthRepository.setAuthenticationStatus(FailedFaceAuthenticationStatus())
+ assertThat(message).isInstanceOf(FingerprintFailureMessage::class.java)
+ }
+
+ @Test
+ fun fingerprintMessageAllowsFaceMessageAfter4000ms() =
+ testScope.runTest {
+ val message by collectLastValue(underTest.message)
+ bouncerRepository.setAlternateVisible(true)
+ runCurrent()
+ fingerprintAuthRepository.setAuthenticationStatus(FailFingerprintAuthenticationStatus)
+ assertThat(message).isInstanceOf(FingerprintFailureMessage::class.java)
+
+ advanceTimeBy(4000)
+
+ faceAuthRepository.setAuthenticationStatus(FailedFaceAuthenticationStatus())
+ assertThat(message).isInstanceOf(FaceFailureMessage::class.java)
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
index b0f59fe..de659cf 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
@@ -71,7 +71,7 @@
mSetFlagsRule.disableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
MockitoAnnotations.initMocks(this)
- whenever(burnInInteractor.keyguardBurnIn).thenReturn(burnInFlow)
+ whenever(burnInInteractor.burnIn(anyInt(), anyInt())).thenReturn(burnInFlow)
kosmos.burnInInteractor = burnInInteractor
whenever(goneToAodTransitionViewModel.enterFromTopTranslationY(anyInt()))
.thenReturn(emptyFlow())
@@ -81,18 +81,18 @@
}
@Test
- fun translationY_initializedToZero() =
+ fun movement_initializedToZero() =
testScope.runTest {
- val translationY by collectLastValue(underTest.translationY(burnInParameters))
- assertThat(translationY).isEqualTo(0)
+ val movement by collectLastValue(underTest.movement(burnInParameters))
+ assertThat(movement?.translationY).isEqualTo(0)
+ assertThat(movement?.translationX).isEqualTo(0)
+ assertThat(movement?.scale).isEqualTo(0f)
}
@Test
fun translationAndScale_whenNotDozing() =
testScope.runTest {
- val translationX by collectLastValue(underTest.translationX(burnInParameters))
- val translationY by collectLastValue(underTest.translationY(burnInParameters))
- val scale by collectLastValue(underTest.scale(burnInParameters))
+ val movement by collectLastValue(underTest.movement(burnInParameters))
// Set to not dozing (on lockscreen)
keyguardTransitionRepository.sendTransitionStep(
@@ -113,24 +113,17 @@
scale = 0.5f,
)
- assertThat(translationX).isEqualTo(0)
- assertThat(translationY).isEqualTo(0)
- assertThat(scale)
- .isEqualTo(
- BurnInScaleViewModel(
- scale = 1f,
- scaleClockOnly = true,
- )
- )
+ assertThat(movement?.translationX).isEqualTo(0)
+ assertThat(movement?.translationY).isEqualTo(0)
+ assertThat(movement?.scale).isEqualTo(1f)
+ assertThat(movement?.scaleClockOnly).isEqualTo(true)
}
@Test
fun translationAndScale_whenFullyDozing() =
testScope.runTest {
burnInParameters = burnInParameters.copy(minViewY = 100)
- val translationX by collectLastValue(underTest.translationX(burnInParameters))
- val translationY by collectLastValue(underTest.translationY(burnInParameters))
- val scale by collectLastValue(underTest.scale(burnInParameters))
+ val movement by collectLastValue(underTest.movement(burnInParameters))
// Set to dozing (on AOD)
keyguardTransitionRepository.sendTransitionStep(
@@ -150,15 +143,10 @@
scale = 0.5f,
)
- assertThat(translationX).isEqualTo(20)
- assertThat(translationY).isEqualTo(30)
- assertThat(scale)
- .isEqualTo(
- BurnInScaleViewModel(
- scale = 0.5f,
- scaleClockOnly = true,
- )
- )
+ assertThat(movement?.translationX).isEqualTo(20)
+ assertThat(movement?.translationY).isEqualTo(30)
+ assertThat(movement?.scale).isEqualTo(0.5f)
+ assertThat(movement?.scaleClockOnly).isEqualTo(true)
// Set to the beginning of GONE->AOD transition
keyguardTransitionRepository.sendTransitionStep(
@@ -170,15 +158,10 @@
),
validateStep = false,
)
- assertThat(translationX).isEqualTo(0)
- assertThat(translationY).isEqualTo(0)
- assertThat(scale)
- .isEqualTo(
- BurnInScaleViewModel(
- scale = 1f,
- scaleClockOnly = true,
- )
- )
+ assertThat(movement?.translationX).isEqualTo(0)
+ assertThat(movement?.translationY).isEqualTo(0)
+ assertThat(movement?.scale).isEqualTo(1f)
+ assertThat(movement?.scaleClockOnly).isEqualTo(true)
}
@Test
@@ -191,9 +174,7 @@
minViewY = 100,
topInset = 80,
)
- val translationX by collectLastValue(underTest.translationX(burnInParameters))
- val translationY by collectLastValue(underTest.translationY(burnInParameters))
- val scale by collectLastValue(underTest.scale(burnInParameters))
+ val movement by collectLastValue(underTest.movement(burnInParameters))
// Set to dozing (on AOD)
keyguardTransitionRepository.sendTransitionStep(
@@ -213,16 +194,11 @@
translationY = -30,
scale = 0.5f,
)
- assertThat(translationX).isEqualTo(20)
+ assertThat(movement?.translationX).isEqualTo(20)
// -20 instead of -30, due to inset of 80
- assertThat(translationY).isEqualTo(-20)
- assertThat(scale)
- .isEqualTo(
- BurnInScaleViewModel(
- scale = 0.5f,
- scaleClockOnly = true,
- )
- )
+ assertThat(movement?.translationY).isEqualTo(-20)
+ assertThat(movement?.scale).isEqualTo(0.5f)
+ assertThat(movement?.scaleClockOnly).isEqualTo(true)
// Set to the beginning of GONE->AOD transition
keyguardTransitionRepository.sendTransitionStep(
@@ -234,15 +210,10 @@
),
validateStep = false,
)
- assertThat(translationX).isEqualTo(0)
- assertThat(translationY).isEqualTo(0)
- assertThat(scale)
- .isEqualTo(
- BurnInScaleViewModel(
- scale = 1f,
- scaleClockOnly = true,
- )
- )
+ assertThat(movement?.translationX).isEqualTo(0)
+ assertThat(movement?.translationY).isEqualTo(0)
+ assertThat(movement?.scale).isEqualTo(1f)
+ assertThat(movement?.scaleClockOnly).isEqualTo(true)
}
@Test
@@ -255,9 +226,7 @@
minViewY = 100,
topInset = 80,
)
- val translationX by collectLastValue(underTest.translationX(burnInParameters))
- val translationY by collectLastValue(underTest.translationY(burnInParameters))
- val scale by collectLastValue(underTest.scale(burnInParameters))
+ val movement by collectLastValue(underTest.movement(burnInParameters))
// Set to dozing (on AOD)
keyguardTransitionRepository.sendTransitionStep(
@@ -277,16 +246,11 @@
translationY = -30,
scale = 0.5f,
)
- assertThat(translationX).isEqualTo(20)
+ assertThat(movement?.translationX).isEqualTo(20)
// -20 instead of -30, due to inset of 80
- assertThat(translationY).isEqualTo(-20)
- assertThat(scale)
- .isEqualTo(
- BurnInScaleViewModel(
- scale = 0.5f,
- scaleClockOnly = true,
- )
- )
+ assertThat(movement?.translationY).isEqualTo(-20)
+ assertThat(movement?.scale).isEqualTo(0.5f)
+ assertThat(movement?.scaleClockOnly).isEqualTo(true)
// Set to the beginning of GONE->AOD transition
keyguardTransitionRepository.sendTransitionStep(
@@ -298,15 +262,10 @@
),
validateStep = false,
)
- assertThat(translationX).isEqualTo(0)
- assertThat(translationY).isEqualTo(0)
- assertThat(scale)
- .isEqualTo(
- BurnInScaleViewModel(
- scale = 1f,
- scaleClockOnly = true,
- )
- )
+ assertThat(movement?.translationX).isEqualTo(0)
+ assertThat(movement?.translationY).isEqualTo(0)
+ assertThat(movement?.scale).isEqualTo(1f)
+ assertThat(movement?.scaleClockOnly).isEqualTo(true)
}
@Test
@@ -314,9 +273,7 @@
testScope.runTest {
whenever(clockController.config.useAlternateSmartspaceAODTransition).thenReturn(true)
- val translationX by collectLastValue(underTest.translationX(burnInParameters))
- val translationY by collectLastValue(underTest.translationY(burnInParameters))
- val scale by collectLastValue(underTest.scale(burnInParameters))
+ val movement by collectLastValue(underTest.movement(burnInParameters))
// Set to dozing (on AOD)
keyguardTransitionRepository.sendTransitionStep(
@@ -337,8 +294,9 @@
scale = 0.5f,
)
- assertThat(translationX).isEqualTo(0)
- assertThat(translationY).isEqualTo(0)
- assertThat(scale).isEqualTo(BurnInScaleViewModel(scale = 0.5f, scaleClockOnly = false))
+ assertThat(movement?.translationX).isEqualTo(0)
+ assertThat(movement?.translationY).isEqualTo(0)
+ assertThat(movement?.scale).isEqualTo(0.5f)
+ assertThat(movement?.scaleClockOnly).isEqualTo(false)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
new file mode 100644
index 0000000..04c270d
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2024 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.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.Flags as AConfigFlags
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.doze.util.BurnInHelperWrapper
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
+import com.android.systemui.keyguard.shared.model.BurnInModel
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class KeyguardIndicationAreaViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ @Mock private lateinit var burnInHelperWrapper: BurnInHelperWrapper
+ @Mock private lateinit var shortcutsCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel
+
+ @Mock private lateinit var burnInInteractor: BurnInInteractor
+ private val burnInFlow = MutableStateFlow(BurnInModel())
+
+ private lateinit var bottomAreaInteractor: KeyguardBottomAreaInteractor
+ private lateinit var underTest: KeyguardIndicationAreaViewModel
+ private lateinit var repository: FakeKeyguardRepository
+
+ private val startButtonFlow =
+ MutableStateFlow<KeyguardQuickAffordanceViewModel>(
+ KeyguardQuickAffordanceViewModel(
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId()
+ )
+ )
+ private val endButtonFlow =
+ MutableStateFlow<KeyguardQuickAffordanceViewModel>(
+ KeyguardQuickAffordanceViewModel(
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId()
+ )
+ )
+ private val alphaFlow = MutableStateFlow<Float>(1f)
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ mSetFlagsRule.disableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
+ mSetFlagsRule.disableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+
+ whenever(burnInHelperWrapper.burnInOffset(anyInt(), any()))
+ .thenReturn(RETURNED_BURN_IN_OFFSET)
+ whenever(burnInInteractor.burnIn(anyInt(), anyInt())).thenReturn(burnInFlow)
+
+ val withDeps = KeyguardInteractorFactory.create()
+ val keyguardInteractor = withDeps.keyguardInteractor
+ repository = withDeps.repository
+
+ val bottomAreaViewModel: KeyguardBottomAreaViewModel = mock()
+ whenever(bottomAreaViewModel.startButton).thenReturn(startButtonFlow)
+ whenever(bottomAreaViewModel.endButton).thenReturn(endButtonFlow)
+ whenever(bottomAreaViewModel.alpha).thenReturn(alphaFlow)
+ bottomAreaInteractor = KeyguardBottomAreaInteractor(repository = repository)
+ underTest =
+ KeyguardIndicationAreaViewModel(
+ keyguardInteractor = keyguardInteractor,
+ bottomAreaInteractor = bottomAreaInteractor,
+ keyguardBottomAreaViewModel = bottomAreaViewModel,
+ burnInHelperWrapper = burnInHelperWrapper,
+ burnInInteractor = burnInInteractor,
+ shortcutsCombinedViewModel = shortcutsCombinedViewModel,
+ configurationInteractor = ConfigurationInteractor(FakeConfigurationRepository()),
+ )
+ }
+
+ @Test
+ fun alpha() =
+ testScope.runTest {
+ val value = collectLastValue(underTest.alpha)
+
+ assertThat(value()).isEqualTo(1f)
+ alphaFlow.value = 0.1f
+ assertThat(value()).isEqualTo(0.1f)
+ alphaFlow.value = 0.5f
+ assertThat(value()).isEqualTo(0.5f)
+ alphaFlow.value = 0.2f
+ assertThat(value()).isEqualTo(0.2f)
+ alphaFlow.value = 0f
+ assertThat(value()).isEqualTo(0f)
+ }
+
+ @Test
+ fun isIndicationAreaPadded() =
+ testScope.runTest {
+ repository.setKeyguardShowing(true)
+ val value = collectLastValue(underTest.isIndicationAreaPadded)
+
+ assertThat(value()).isFalse()
+ startButtonFlow.value = startButtonFlow.value.copy(isVisible = true)
+ assertThat(value()).isTrue()
+ endButtonFlow.value = endButtonFlow.value.copy(isVisible = true)
+ assertThat(value()).isTrue()
+ startButtonFlow.value = startButtonFlow.value.copy(isVisible = false)
+ assertThat(value()).isTrue()
+ endButtonFlow.value = endButtonFlow.value.copy(isVisible = false)
+ assertThat(value()).isFalse()
+ }
+
+ @Test
+ fun indicationAreaTranslationX() =
+ testScope.runTest {
+ val value = collectLastValue(underTest.indicationAreaTranslationX)
+
+ assertThat(value()).isEqualTo(0f)
+ bottomAreaInteractor.setClockPosition(100, 100)
+ assertThat(value()).isEqualTo(100f)
+ bottomAreaInteractor.setClockPosition(200, 100)
+ assertThat(value()).isEqualTo(200f)
+ bottomAreaInteractor.setClockPosition(200, 200)
+ assertThat(value()).isEqualTo(200f)
+ bottomAreaInteractor.setClockPosition(300, 100)
+ assertThat(value()).isEqualTo(300f)
+ }
+
+ @Test
+ fun indicationAreaTranslationY() =
+ testScope.runTest {
+ val value =
+ collectLastValue(underTest.indicationAreaTranslationY(DEFAULT_BURN_IN_OFFSET))
+
+ // Negative 0 - apparently there's a difference in floating point arithmetic - FML
+ assertThat(value()).isEqualTo(-0f)
+ val expected1 = setDozeAmountAndCalculateExpectedTranslationY(0.1f)
+ assertThat(value()).isEqualTo(expected1)
+ val expected2 = setDozeAmountAndCalculateExpectedTranslationY(0.2f)
+ assertThat(value()).isEqualTo(expected2)
+ val expected3 = setDozeAmountAndCalculateExpectedTranslationY(0.5f)
+ assertThat(value()).isEqualTo(expected3)
+ val expected4 = setDozeAmountAndCalculateExpectedTranslationY(1f)
+ assertThat(value()).isEqualTo(expected4)
+ }
+
+ private fun setDozeAmountAndCalculateExpectedTranslationY(dozeAmount: Float): Float {
+ repository.setDozeAmount(dozeAmount)
+ return dozeAmount * (RETURNED_BURN_IN_OFFSET - DEFAULT_BURN_IN_OFFSET)
+ }
+
+ companion object {
+ private const val DEFAULT_BURN_IN_OFFSET = 5
+ private const val RETURNED_BURN_IN_OFFSET = 3
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorTest.kt
index e188f5b..8e765f7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsSoundPolicyInteractorTest.kt
@@ -196,10 +196,14 @@
}
@Test
- fun zenModeAlarms_ringAndNotifications_muted() {
+ fun zenModeAlarms_ringedStreams_muted() {
with(kosmos) {
val expectedToBeMuted =
- setOf(AudioManager.STREAM_RING, AudioManager.STREAM_NOTIFICATION)
+ setOf(
+ AudioManager.STREAM_RING,
+ AudioManager.STREAM_NOTIFICATION,
+ AudioManager.STREAM_SYSTEM,
+ )
testScope.runTest {
notificationsSoundPolicyRepository.updateNotificationPolicy()
notificationsSoundPolicyRepository.updateZenMode(ZenMode(Global.ZEN_MODE_ALARMS))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 0de15b8..deb1976 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -34,6 +34,7 @@
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.keyguard.shared.model.BurnInModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
@@ -66,7 +67,7 @@
@RunWith(AndroidJUnit4::class)
class SharedNotificationContainerViewModelTest : SysuiTestCase() {
val aodBurnInViewModel = mock(AodBurnInViewModel::class.java)
- lateinit var translationYFlow: MutableStateFlow<Float>
+ lateinit var movementFlow: MutableStateFlow<BurnInModel>
val kosmos =
testKosmos().apply {
@@ -95,8 +96,8 @@
@Before
fun setUp() {
overrideResource(R.bool.config_use_split_notification_shade, false)
- translationYFlow = MutableStateFlow(0f)
- whenever(aodBurnInViewModel.translationY(any())).thenReturn(translationYFlow)
+ movementFlow = MutableStateFlow(BurnInModel())
+ whenever(aodBurnInViewModel.movement(any())).thenReturn(movementFlow)
underTest = kosmos.sharedNotificationContainerViewModel
}
@@ -608,7 +609,7 @@
showLockscreen()
assertThat(translationY).isEqualTo(0)
- translationYFlow.value = 150f
+ movementFlow.value = BurnInModel(translationY = 150)
assertThat(translationY).isEqualTo(150f)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/SpatialAudioAvailabilityCriteriaTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/SpatialAudioAvailabilityCriteriaTest.kt
index 36be90e..449e8bf 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/SpatialAudioAvailabilityCriteriaTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/SpatialAudioAvailabilityCriteriaTest.kt
@@ -78,7 +78,7 @@
with(kosmos) {
testScope.runTest {
localMediaRepository.updateCurrentConnectedDevice(bluetoothMediaDevice)
- spatializerRepository.setIsHeadTrackingAvailable(false)
+ spatializerRepository.defaultHeadTrackingAvailable = false
spatializerRepository.defaultSpatialAudioAvailable = false
val isAvailable by collectLastValue(underTest.isAvailable())
@@ -94,7 +94,7 @@
with(kosmos) {
testScope.runTest {
localMediaRepository.updateCurrentConnectedDevice(bluetoothMediaDevice)
- spatializerRepository.setIsHeadTrackingAvailable(false)
+ spatializerRepository.defaultHeadTrackingAvailable = false
spatializerRepository.defaultSpatialAudioAvailable = true
val isAvailable by collectLastValue(underTest.isAvailable())
@@ -110,7 +110,7 @@
with(kosmos) {
testScope.runTest {
localMediaRepository.updateCurrentConnectedDevice(bluetoothMediaDevice)
- spatializerRepository.setIsHeadTrackingAvailable(true)
+ spatializerRepository.defaultHeadTrackingAvailable = true
spatializerRepository.defaultSpatialAudioAvailable = true
val isAvailable by collectLastValue(underTest.isAvailable())
@@ -125,7 +125,7 @@
fun spatialAudio_headTracking_noDevice_unavailable() {
with(kosmos) {
testScope.runTest {
- spatializerRepository.setIsHeadTrackingAvailable(true)
+ spatializerRepository.defaultHeadTrackingAvailable = true
spatializerRepository.defaultSpatialAudioAvailable = true
val isAvailable by collectLastValue(underTest.isAvailable())
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorTest.kt
index eb6f0b2..06ae220 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorTest.kt
@@ -82,7 +82,7 @@
),
true
)
- spatializerRepository.setIsHeadTrackingAvailable(true)
+ spatializerRepository.defaultHeadTrackingAvailable = true
underTest =
SpatialAudioComponentInteractor(
diff --git a/packages/SystemUI/res/drawable/ic_head_tracking.xml b/packages/SystemUI/res/drawable/ic_head_tracking.xml
new file mode 100644
index 0000000..d4a44fd
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_head_tracking.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ Copyright (C) 2024 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="24dp"
+ android:height="24dp"
+ android:tint="?attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M480,520Q414,520 367,473Q320,426 320,360Q320,294 367,247Q414,200 480,200Q546,200 593,247Q640,294 640,360Q640,426 593,473Q546,520 480,520ZM160,840L160,728Q160,695 177,666Q194,637 224,622Q275,596 339,578Q403,560 480,560Q557,560 621,578Q685,596 736,622Q766,637 783,666Q800,695 800,728L800,840L160,840ZM240,760L720,760L720,728Q720,717 714.5,708Q709,699 700,694Q664,676 607.5,658Q551,640 480,640Q409,640 352.5,658Q296,676 260,694Q251,699 245.5,708Q240,717 240,728L240,760ZM480,440Q513,440 536.5,416.5Q560,393 560,360Q560,327 536.5,303.5Q513,280 480,280Q447,280 423.5,303.5Q400,327 400,360Q400,393 423.5,416.5Q447,440 480,440ZM39,200L39,120Q56,120 70,113.5Q84,107 95,96Q106,85 112,71Q118,57 118,40L199,40Q199,73 186.5,102Q174,131 152,153Q130,175 101,187.5Q72,200 39,200ZM39,361L39,281Q90,281 133.5,262Q177,243 209,210Q241,177 260,133.5Q279,90 279,40L360,40Q360,106 335,164.5Q310,223 266,267Q222,311 164,336Q106,361 39,361ZM920,361Q854,361 795.5,336Q737,311 693,267Q649,223 624,164.5Q599,106 599,40L679,40Q679,90 698,133.5Q717,177 750,210Q783,243 826.5,262Q870,281 920,281L920,361ZM920,200Q887,200 858,187.5Q829,175 807,153Q785,131 772.5,102Q760,73 760,40L840,40Q840,57 846.5,71Q853,85 864,96Q875,107 889,113.5Q903,120 920,120L920,200ZM480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360ZM480,760L480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760L480,760L480,760Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_spatial_audio.xml b/packages/SystemUI/res/drawable/ic_spatial_audio.xml
new file mode 100644
index 0000000..0ee609a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_spatial_audio.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ Copyright (C) 2024 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="24dp"
+ android:height="24dp"
+ android:tint="?attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M920,401Q848,401 782,373.5Q716,346 665,295Q614,244 586.5,178Q559,112 559,40L639,40Q639,97 660,148Q681,199 721,239Q761,279 812,300.5Q863,322 920,322L920,401ZM920,242Q879,242 842.5,227Q806,212 777,183Q748,154 733,117.5Q718,81 718,40L797,40Q797,65 806.5,87.5Q816,110 833,127Q850,144 872.5,153Q895,162 920,162L920,242ZM400,520Q334,520 287,473Q240,426 240,360Q240,294 287,247Q334,200 400,200Q466,200 513,247Q560,294 560,360Q560,426 513,473Q466,520 400,520ZM80,840L80,728Q80,695 97,666Q114,637 144,622Q195,596 259,578Q323,560 400,560Q477,560 541,578Q605,596 656,622Q686,637 703,666Q720,695 720,728L720,840L80,840ZM160,760L640,760L640,728Q640,717 634.5,708Q629,699 620,694Q584,676 527.5,658Q471,640 400,640Q329,640 272.5,658Q216,676 180,694Q171,699 165.5,708Q160,717 160,728L160,760ZM400,440Q433,440 456.5,416.5Q480,393 480,360Q480,327 456.5,303.5Q433,280 400,280Q367,280 343.5,303.5Q320,327 320,360Q320,393 343.5,416.5Q367,440 400,440ZM400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360ZM400,760L400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760L400,760L400,760Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_spatial_audio_off.xml b/packages/SystemUI/res/drawable/ic_spatial_audio_off.xml
new file mode 100644
index 0000000..c7d3272
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_spatial_audio_off.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ Copyright (C) 2024 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="24dp"
+ android:height="24dp"
+ android:tint="?attr/colorControlNormal"
+ android:viewportHeight="960"
+ android:viewportWidth="960">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M750,550L806,494Q766,454 743.5,402.5Q721,351 721,294Q721,237 743.5,186Q766,135 806,95L750,37Q699,88 670,155Q641,222 641,294Q641,366 670,432.5Q699,499 750,550ZM862,436L918,380Q901,363 891,341Q881,319 881,294Q881,269 891,247Q901,225 918,208L862,151Q833,180 817,216Q801,252 801,293Q801,334 817,371Q833,408 862,436ZM400,520Q334,520 287,473Q240,426 240,360Q240,294 287,247Q334,200 400,200Q466,200 513,247Q560,294 560,360Q560,426 513,473Q466,520 400,520ZM80,840L80,728Q80,695 97,666Q114,637 144,622Q195,596 259,578Q323,560 400,560Q477,560 541,578Q605,596 656,622Q686,637 703,666Q720,695 720,728L720,840L80,840ZM160,760L640,760L640,728Q640,717 634.5,708Q629,699 620,694Q584,676 527.5,658Q471,640 400,640Q329,640 272.5,658Q216,676 180,694Q171,699 165.5,708Q160,717 160,728L160,760ZM400,440Q433,440 456.5,416.5Q480,393 480,360Q480,327 456.5,303.5Q433,280 400,280Q367,280 343.5,303.5Q320,327 320,360Q320,393 343.5,416.5Q367,440 400,440ZM400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360ZM400,760L400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760L400,760L400,760Z" />
+</vector>
diff --git a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
index ac781ec..13355f3 100644
--- a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
+++ b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
@@ -181,12 +181,11 @@
<TextView
android:id="@+id/bluetooth_auto_on_toggle_info_text"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:paddingStart="36dp"
android:paddingEnd="40dp"
- android:text="@string/turn_on_bluetooth_auto_info"
android:textAppearance="@style/TextAppearance.Dialog.Body.Message"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 515ef61..9197149 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Voeg meer legstukke by"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Langdruk om legstukke te pasmaak"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Pasmaak legstukke"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"App-ikoon vir gedeaktiveerde legstuk"</string>
<string name="edit_widget" msgid="9030848101135393954">"Wysig legstuk"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Verwyder"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Voeg legstuk by"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Aan/af-kieslys"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Bladsy <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Sluitskerm"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Jy kan hierdie foon met Kry My Toestel opspoor selfs wanneer dit afgeskakel is"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Sit tans af …"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Sien versorgingstappe"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Sien versorgingstappe"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Prop jou toestel uit"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Keer die foon om vir hoër resolusie"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Voubare toestel word ontvou"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Voubare toestel word omgekeer"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batterykrag oor"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Koppel jou stilus aan ’n laaier"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Stilus se battery is amper pap"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 9763ff2..a4aa842 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ተጨማሪ ምግብሮችን ያክሉ"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ምግብሮችን ለማበጀት በረጅሙ ይጫኑ"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"ምግብሮችን አብጅ"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"የመተግበሪያ አዶ ለተሰናከለ ምግብር"</string>
<string name="edit_widget" msgid="9030848101135393954">"ምግብርን አርትዕ"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"አስወግድ"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ምግብር አክል"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"የኃይል ምናሌ"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ገፅ <xliff:g id="ID_1">%1$d</xliff:g> ከ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"ማያ ገፅ ቁልፍ"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"ይህ መሣሪያ ኃይል ጠፍቶ ቢሆንም እንኳን በየእኔን መሣሪያ አግኝ ማግኘት ይችላሉ"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"በመዝጋት ላይ…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"የእንክብካቤ ደረጃዎችን ይመልከቱ"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"የእንክብካቤ ደረጃዎችን ይመልከቱ"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"መሣሪያዎን ይንቀሉ"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ለከፍተኛ ጥራት ስልኩን ይቀይሩ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"መታጠፍ የሚችል መሣሪያ እየተዘረጋ ነው"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"መታጠፍ የሚችል መሣሪያ እየተገለበጠ ነው"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ባትሪ ይቀራል"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"ብሮስፌዎን ከኃይል መሙያ ጋር ያገናኙ"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"የብሮስፌ ባትሪ ዝቅተኛ ነው"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1b7e303..07a5bfc 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"إضافة المزيد من التطبيقات المصغّرة"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"اضغط مع الاستمرار لتخصيص التطبيقات المصغّرة."</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"تخصيص التطبيقات المصغَّرة"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"رمز التطبيق المصغّر غير المفعّل"</string>
<string name="edit_widget" msgid="9030848101135393954">"تعديل التطبيق المصغَّر"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"إزالة"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"إضافة تطبيق مصغّر"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"قائمة زر التشغيل"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"الصفحة <xliff:g id="ID_1">%1$d</xliff:g> من <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"شاشة القفل"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"يمكنك تحديد مكان هذا الهاتف باستخدام تطبيق \"العثور على جهازي\" حتى عندما يكون مُطفئًا."</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"جارٍ إيقاف التشغيل…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"الاطّلاع على خطوات العناية"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"الاطّلاع على خطوات العناية"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"افصِل جهازك"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"للحصول على درجة دقة أعلى، اقلِب الهاتف."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"جهاز قابل للطي يجري فتحه"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"جهاز قابل للطي يجري قلبه"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"النسبة المئوية المتبقية من شحن البطارية: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"عليك توصيل قلم الشاشة بشاحن."</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"بطارية قلم الشاشة منخفضة"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 429f03e..13bb7ea 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"অধিক ৱিজেট যোগ দিয়ক"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ৱিজেট কাষ্টমাইজ কৰিবলৈ দীঘলীয়াকৈ টিপক"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"ৱিজেট কাষ্টমাইজ কৰক"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"অক্ষম কৰা ৱিজেটৰ বাবে এপৰ চিহ্ন"</string>
<string name="edit_widget" msgid="9030848101135393954">"ৱিজেট সম্পাদনা কৰক"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"আঁতৰাওক"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ৱিজেট যোগ দিয়ক"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"পাৱাৰ মেনু"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>ৰ পৃষ্ঠা <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্ৰীন"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"পাৱাৰ অফ কৰা থাকিলেও Find My Deviceৰ জৰিয়তে আপুনি এই ফ’নটোৰ অৱস্থান নিৰ্ধাৰণ কৰিব পাৰে"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"বন্ধ কৰি থকা হৈছে…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"যত্ন লোৱাৰ পদক্ষেপসমূহ চাওক"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"যত্ন লোৱাৰ পদক্ষেপসমূহ চাওক"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"আপোনাৰ ডিভাইচটো আনপ্লাগ কৰক"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"অধিক ৰিজ’লিউছনৰ বাবে, ফ’নটো লুটিয়াই দিয়ক"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"জপাব পৰা ডিভাইচৰ জাপ খুলি থকা হৈছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"জপাব পৰা ডিভাইচৰ ওলোটাই থকা হৈছে"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> বেটাৰী বাকী আছে"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"আপোনাৰ ষ্টাইলাছ এটা চাৰ্জাৰৰ সৈতে সংযোগ কৰক"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"ষ্টাইলাছৰ বেটাৰী কম আছে"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 639cbbc..19cb29b 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Vidcetlər əlavə edin"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Basıb saxlayaraq vidcetləri fərdiləşdirin"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Vidcetləri fərdiləşdirin"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Deaktiv edilmiş vidcet üçün tətbiq ikonası"</string>
<string name="edit_widget" msgid="9030848101135393954">"Vidceti redaktə edin"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Silin"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Vidcet əlavə edin"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Qidalanma düyməsi menyusu"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> səhifədən <xliff:g id="ID_1">%1$d</xliff:g> səhifə"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran kilidi"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Bu telefon sönülü olsa belə, Cihazın Tapılması ilə onu tapa bilərsiniz"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Söndürülür…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ehtiyat tədbiri mərhələlərinə baxın"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ehtiyat tədbiri mərhələlərinə baxın"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Cihazınızı ayırın"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Daha yüksək ayırdetmə dəqiqliyi üçün telefonu çevirin"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Qatlana bilən cihaz açılır"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Qatlana bilən cihaz fırladılır"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> enerji qalıb"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Qələmi adapterə qoşun"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Qələm enerjisi azdır"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index e97dbec..6604001 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodajte još vidžeta"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Dugi pritisak za prilagođavanje vidžeta"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Prilagodi vidžete"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ikona aplikacije za onemogućen vidžet"</string>
<string name="edit_widget" msgid="9030848101135393954">"Izmeni vidžet"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Ukloni"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodaj vidžet"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meni dugmeta za uključivanje"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. strana od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključan ekran"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Možete da locirate ovaj telefon pomoću usluge Pronađi moj uređaj čak i kada je isključen"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Isključuje se…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Pogledajte upozorenja"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pogledajte upozorenja"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Isključite uređaj"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za veću rezoluciju obrnite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Uređaj na preklop se otvara"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Uređaj na preklop se obrće"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostalo je još<xliff:g id="PERCENTAGE">%s</xliff:g> baterije"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Povežite pisaljku sa punjačem"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Nizak nivo baterije pisaljke"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 3b06d05..de4fc99 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Дадаць іншыя віджэты"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Доўга націскайце, каб наладзіць віджэты"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Наладзіць віджэты"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Значок праграмы для адключанага віджэта"</string>
<string name="edit_widget" msgid="9030848101135393954">"Змяніць віджэт"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Выдаліць"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Дадаць віджэт"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню кнопкі сілкавання"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Старонка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Экран блакіроўкі"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Вы можаце знайсці свой тэлефон з дапамогай праграмы \"Знайсці прыладу\", нават калі ён выключаны"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Ідзе завяршэнне працы…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Глядзець паэтапную дапамогу"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Глядзець паэтапную дапамогу"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Адключыце прыладу"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Каб зрабіць фота з больш высокай раздзяляльнасцю, павярніце тэлефон"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складная прылада ў раскладзеным выглядзе"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Перавернутая складная прылада"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Засталося зараду: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Падключыце пяро да зараднай прылады"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Нізкі ўзровень зараду пяра"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 643ef9c..475076f 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Добавете още приспособления"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Натиснете продължително за персонализ. на приспос."</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Персонализиране на приспособленията"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Икона на приложение за деактивирано приспособление"</string>
<string name="edit_widget" msgid="9030848101135393954">"Редактиране на приспособлението"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Премахване"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Добавяне на приспособление"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню за включване/изключване"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Страница <xliff:g id="ID_1">%1$d</xliff:g> от <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Заключен екран"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Можете да откриете този телефон посредством „Намиране на устройството ми“ дори когато е изключен"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Изключва се…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Вижте стъпките, които да предприемете"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Вижте стъпките, които да предприемете"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Изключете устройството си"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"За по-висока разделителна способност обърнете телефона"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Разгъване на сгъваемо устройство"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Обръщане на сгъваемо устройство"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Оставаща батерия: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Свържете писалката към зарядно устройство"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Батерията на писалката е изтощена"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 9a2f040..c1808a9 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"আরও উইজেট যোগ করুন"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"উইজেট কাস্টমাইজ করতে বেশিক্ষণ প্রেস করুন"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"উইজেট কাস্টমাইজ করুন"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"বন্ধ করা উইজেটের জন্য অ্যাপের আইকন"</string>
<string name="edit_widget" msgid="9030848101135393954">"উইজেট এডিট করুন"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"সরান"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"উইজেট যোগ করুন"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"পাওয়ার মেনু"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>টির মধ্যে <xliff:g id="ID_1">%1$d</xliff:g> নং পৃষ্ঠা"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্রিন"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Find My Device-এর মাধ্যমে, ফোনটি বন্ধ করা থাকলেও এটির লোকেশন শনাক্ত করতে পারবেন"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"বন্ধ হচ্ছে…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ডিভাইস রক্ষণাবেক্ষণের ধাপগুলি দেখুন"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ডিভাইস রক্ষণাবেক্ষণের ধাপগুলি দেখুন"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"আপনার ডিভাইস আনপ্লাগ করা"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"আরও বেশি রেজোলিউশনের জন্য, ফোন ফ্লিপ করুন"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ফোল্ড করা যায় এমন ডিভাইস খোলা হচ্ছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ফোল্ড করা যায় এমন ডিভাইস উল্টানো হচ্ছে"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ব্যাটারির চার্জ বাকি আছে"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"কোনও চার্জারের সাথে আপনার স্টাইলাস কানেক্ট করুন"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"স্টাইলাস ব্যাটারিতে চার্জ কম আছে"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index db102a0..a08edd2 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodajte još vidžeta"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Pritisnite i zadržite da prilagodite vidžete"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Prilagodite vidžete"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ikona aplikacije za onemogućeni vidžet"</string>
<string name="edit_widget" msgid="9030848101135393954">"Uredite vidžet"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Uklanjanje"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodajte vidžet"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meni napajanja"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključani ekran"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Možete pronaći telefon putem usluge Pronađi moj uređaj čak i kada je isključen"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Isključivanje…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Pogledajte korake za zaštitu"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pogledajte korake za zaštitu"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Iskopčajte uređaj"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za višu rezoluciju obrnite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Sklopivi uređaj se rasklapa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Sklopivi uređaj se obrće"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostalo baterije: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Priključite pisaljku na punjač"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Baterija pisaljke je slaba"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index c528734..5755353 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Afegeix més widgets"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantén premut per personalitzar els widgets"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personalitza els widgets"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Icona de l\'aplicació per a widget desactivat"</string>
<string name="edit_widget" msgid="9030848101135393954">"Edita el widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Suprimeix"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Afegeix un widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú d\'engegada"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pàgina <xliff:g id="ID_1">%1$d</xliff:g> (<xliff:g id="ID_2">%2$d</xliff:g> en total)"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueig"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Pots localitzar aquest telèfon amb Troba el meu dispositiu fins i tot quan estigui apagat"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"S\'està apagant…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Mostra els passos de manteniment"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Mostra els passos de manteniment"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Desconnecta el dispositiu"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Per a una resolució més alta, gira el telèfon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositiu plegable desplegant-se"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositiu plegable girant"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de bateria"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connecta el llapis òptic a un carregador"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Bateria del llapis òptic baixa"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f29dabb..18391eb 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Přidat další widgety"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Dlouhým stisknutím můžete přizpůsobit widgety"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Přizpůsobit widgety"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ikona aplikace s deaktivovaným widgetem"</string>
<string name="edit_widget" msgid="9030848101135393954">"Upravit widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Odstranit"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Přidat widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Nabídka vypínače"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Stránka <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Obrazovka uzamčení"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Tento telefon můžete pomocí funkce Najdi moje zařízení najít, i když je vypnutý"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Vypínání…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Zobrazit pokyny, co dělat"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Zobrazit pokyny, co dělat"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Odpojte zařízení"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Otočte telefon, abyste dosáhli vyššího rozlišení"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozkládání rozkládacího zařízení"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Otáčení rozkládacího zařízení"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g> baterie"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Připojte dotykové pero k nabíječce"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Slabá baterie dotykového pera"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index ec899f2..ad4ff92 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Tilføj flere widgets"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Hold fingeren nede for at tilpasse widgets"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Tilpas widgets"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Appikon for deaktiveret widget"</string>
<string name="edit_widget" msgid="9030848101135393954">"Rediger widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Fjern"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Tilføj widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu for afbryderknappen"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Side <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Låseskærm"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Du kan finde denne telefon med Find min enhed, også selvom den er slukket"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Lukker ned…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Se håndteringsvejledning"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Se håndteringsvejledning"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Træk stikket ud af din enhed"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Vend telefonen for at få højere opløsning"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldbar enhed foldes ud"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldbar enhed vendes om"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteri tilbage"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Slut din styluspen til en oplader"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Lavt batteriniveau på styluspen"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index f7e74c9..a2c9f66 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Weitere Widgets hinzufügen"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Lange drücken, um Widgets anzupassen"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Widgets anpassen"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"App-Symbol für deaktiviertes Widget"</string>
<string name="edit_widget" msgid="9030848101135393954">"Widget bearbeiten"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Entfernen"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Widget hinzufügen"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Ein-/Aus-Menü"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Seite <xliff:g id="ID_1">%1$d</xliff:g> von <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Sperrbildschirm"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Du kannst dieses Smartphone über „Mein Gerät finden“ orten, auch wenn es ausgeschaltet ist"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Wird heruntergefahren…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Schritte zur Abkühlung des Geräts ansehen"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Schritte zur Abkühlung des Geräts ansehen"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Gerät vom Stromnetz trennen"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Für höhere Auflösung Smartphone umdrehen"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Faltbares Gerät wird geöffnet"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Faltbares Gerät wird umgeklappt"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akku bei <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Schließe deinen Eingabestift an ein Ladegerät an"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Stylus-Akkustand niedrig"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6b341fd..7ab38b7 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Προσθήκη περισσότερων γραφικών στοιχείων"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Παρατεταμένο πάτημα για προσαρμογή γραφ. στοιχείων"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Προσαρμογή γραφικών στοιχείων"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Εικονίδιο εφαρμογής για απενεργοποιημένο γραφικό στοιχείο"</string>
<string name="edit_widget" msgid="9030848101135393954">"Επεξεργασία γραφικού στοιχείου"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Κατάργηση"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Προσθήκη γραφικού στοιχείου"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Μενού λειτουργίας"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Σελίδα <xliff:g id="ID_1">%1$d</xliff:g> από <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Οθόνη κλειδώματος"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Μπορείτε να εντοπίσετε το συγκεκριμένο τηλέφωνο με την Εύρεση συσκευής ακόμα και όταν είναι απενεργοποιημένο"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Τερματισμός λειτουργίας…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Δείτε βήματα αντιμετώπισης."</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Δείτε βήματα αντιμετώπισης."</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Αποσυνδέστε τη συσκευή"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Για υψηλότερη ανάλυση, αναστρέψτε το τηλέφωνο"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Αναδιπλούμενη συσκευή που ξεδιπλώνει"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Αναδιπλούμενη συσκευή που διπλώνει"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Απομένει το <xliff:g id="PERCENTAGE">%s</xliff:g> της μπαταρίας"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Συνδέστε τη γραφίδα σε έναν φορτιστή"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Χαμηλή στάθμη μπαταρίας γραφίδας"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 021f7db..4a65cc2 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"For higher resolution, flip the phone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 14cb7a0..63b2f4a 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"For higher resolution, flip the phone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
index 2576b60..d97c4c9 100644
--- a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
@@ -126,9 +126,11 @@
<item msgid="8259411607272330225">"Off"</item>
<item msgid="578444932039713369">"On"</item>
</string-array>
- <!-- no translation found for tile_states_record_issue:0 (1727196795383575383) -->
- <!-- no translation found for tile_states_record_issue:1 (9061144428113385092) -->
- <!-- no translation found for tile_states_record_issue:2 (2984256114867200368) -->
+ <string-array name="tile_states_record_issue">
+ <item msgid="1727196795383575383">"Unavailable"</item>
+ <item msgid="9061144428113385092">"Off"</item>
+ <item msgid="2984256114867200368">"On"</item>
+ </string-array>
<string-array name="tile_states_reverse">
<item msgid="3574611556622963971">"Unavailable"</item>
<item msgid="8707481475312432575">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 021f7db..4a65cc2 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"For higher resolution, flip the phone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 021f7db..4a65cc2 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"For higher resolution, flip the phone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index af690e4..a0d2231 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"For higher resolution, flip the phone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
index 42daf8a..2facf58 100644
--- a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
@@ -126,9 +126,11 @@
<item msgid="8259411607272330225">"Off"</item>
<item msgid="578444932039713369">"On"</item>
</string-array>
- <!-- no translation found for tile_states_record_issue:0 (1727196795383575383) -->
- <!-- no translation found for tile_states_record_issue:1 (9061144428113385092) -->
- <!-- no translation found for tile_states_record_issue:2 (2984256114867200368) -->
+ <string-array name="tile_states_record_issue">
+ <item msgid="1727196795383575383">"Unavailable"</item>
+ <item msgid="9061144428113385092">"Off"</item>
+ <item msgid="2984256114867200368">"On"</item>
+ </string-array>
<string-array name="tile_states_reverse">
<item msgid="3574611556622963971">"Unavailable"</item>
<item msgid="8707481475312432575">"Off"</item>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1798e9a..ede1a74 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para obtener una resolución más alta, gira el teléfono"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable siendo desplegado"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable siendo girado"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de batería restante"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecta tu pluma stylus a un cargador"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"La pluma stylus tiene poca batería"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 73c913f..d487ec1 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Añade más widgets"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantén pulsado para personalizar los widgets"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personalizar widgets"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Icono de la aplicación de widget inhabilitado"</string>
<string name="edit_widget" msgid="9030848101135393954">"Editar widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Quitar"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Añadir widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú de encendido"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueo"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Puedes localizar este teléfono con Encontrar mi dispositivo, aunque esté apagado"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Apagando…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ver pasos de mantenimiento"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver pasos de mantenimiento"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Desenchufa tu dispositivo"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para una mayor resolución, gira el teléfono"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable desplegándose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable mostrado desde varios ángulos"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batería restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecta tu lápiz óptico a un cargador"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Batería del lápiz óptico baja"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 6fa7044..1ccc036 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Lisage rohkem vidinaid"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Vajutage pikalt vidinate kohandamiseks"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Kohanda vidinaid"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Keelatud vidina rakenduseikoon"</string>
<string name="edit_widget" msgid="9030848101135393954">"Muuda vidinat"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Eemalda"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Lisa vidin"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Toitemenüü"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Leht <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Lukustuskuva"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Saate selle telefoni funktsiooniga Leia mu seade leida ka siis, kui see on välja lülitatud"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Väljalülitamine …"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Vaadake hooldusjuhiseid"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Vaadake hooldusjuhiseid"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Eemaldage seade"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Suurema eraldusvõime saavutamiseks pöörake telefon ümber"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Volditava seadme lahtivoltimine"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Volditava seadme ümberpööramine"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akutase on <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ühendage elektronpliiats laadijaga"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Elektronpliiatsi akutase on madal"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 564fbb3..5776e091 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Gehitu widget gehiago"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Widgetak pertsonalizatzeko, sakatu luze"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Pertsonalizatu widgetak"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Desgaitutako widgetaren aplikazio-ikonoa"</string>
<string name="edit_widget" msgid="9030848101135393954">"Editatu widgeta"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Kendu"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Gehitu widget bat"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Itzaltzeko menua"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g> orria"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Pantaila blokeatua"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Itzalita badago ere aurki dezakezu telefonoa Bilatu nire gailua erabilita"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Itzaltzen…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ikusi zaintzeko urratsak"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ikusi zaintzeko urratsak"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Deskonektatu gailua"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Irauli telefonoa bereizmen handiago a lortzeko"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Gailu tolesgarria zabaltzen"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Gailu tolesgarria biratzen"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateriaren <xliff:g id="PERCENTAGE">%s</xliff:g> geratzen da"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Konektatu arkatza kargagailu batera"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Arkatzak bateria gutxi du"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 95f17b0..6017209 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"افزودن ابزارکهای بیشتر"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"برای سفارشیسازی ابزارکها، فشار طولانی دهید"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"سفارشیسازی ابزارکها"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"نماد برنامه برای ابزارک غیرفعال"</string>
<string name="edit_widget" msgid="9030848101135393954">"ویرایش ابزارک"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"برداشتن"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"افزودن ابزارک"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"منوی روشن/خاموش"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"صفحه <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"صفحه قفل"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"حتی وقتی این تلفن خاموش است، میتوانید با «پیدا کردن دستگاهم» آن را مکانیابی کنید"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"درحال خاموش شدن…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"دیدن اقدامات محافظتی"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"دیدن اقدامات محافظتی"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"دستگاه را جدا کنید"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"برای وضوح بیشتر، تلفن را برگردانید"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"دستگاه تاشو درحال باز شدن"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"دستگاه تاشو درحال چرخش به اطراف"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> باتری باقی مانده است"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"قلم را به شارژر وصل کنید"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"باتری قلم ضعیف است"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index ab022dd..7872ef0 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Lisää widgetejä"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Yksilöi widgetit pitkällä painalluksella"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Muokkaa widgettejä"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Käytöstä poistetun widgetin sovelluskuvake"</string>
<string name="edit_widget" msgid="9030848101135393954">"Muokkaa widgetiä"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Poista"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Lisää widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Virtavalikko"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Sivu <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Lukitusnäyttö"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Voit löytää tämän puhelimen Paikanna laite ‑sovelluksella, vaikka se olisi sammutettuna"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Sammutetaan…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Katso huoltovaiheet"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Katso huoltovaiheet"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Irrota laite"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Resoluutio on parempi, kun käännät puhelimen"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Taitettava laite taitetaan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Taitettava laite käännetään ympäri"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akkua jäljellä <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Yhdistä näyttökynä laturiin"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Näyttökynän akku vähissä"</string>
diff --git a/packages/SystemUI/res/values-fr-feminine/strings.xml b/packages/SystemUI/res/values-fr-feminine/strings.xml
new file mode 100644
index 0000000..ebdc3fb
--- /dev/null
+++ b/packages/SystemUI/res/values-fr-feminine/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, 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:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangée par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+ <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangée par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+ <string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invitée"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fr-masculine/strings.xml b/packages/SystemUI/res/values-fr-masculine/strings.xml
new file mode 100644
index 0000000..6b94970
--- /dev/null
+++ b/packages/SystemUI/res/values-fr-masculine/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, 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:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+ <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+ <string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invité"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fr-neuter/strings.xml b/packages/SystemUI/res/values-fr-neuter/strings.xml
new file mode 100644
index 0000000..e9d0191
--- /dev/null
+++ b/packages/SystemUI/res/values-fr-neuter/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, 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:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="zen_priority_introduction" msgid="3159291973383796646">"Vous ne serez pas dérangé·e par des sons ou des vibrations, hormis ceux des alarmes, des rappels, des événements et des appelants de votre choix. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+ <string name="zen_alarms_introduction" msgid="3987266042682300470">"Vous ne serez pas dérangé·e par des sons ou des vibrations, hormis ceux des alarmes. Vous entendrez encore les sons que vous choisirez de jouer, notamment la musique, les vidéos et les jeux."</string>
+ <string name="guest_wipe_session_title" msgid="7147965814683990944">"Heureux de vous revoir, Invité·e"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 1186c81..b1c8944 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Ajouter plus de widgets"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Maintenez le doigt pour personnaliser les widgets"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personnaliser les widgets"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Icône d\'application pour un widget désactivé"</string>
<string name="edit_widget" msgid="9030848101135393954">"Modifier le widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Retirer"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ajouter un widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu de l\'interrupteur"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Écran de verrouillage"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Vous pouvez localiser ce téléphone à l\'aide de Localiser mon appareil, même lorsqu\'il est éteint"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Arrêt en cours…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Afficher les étapes d\'entretien"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Afficher les étapes d\'entretien"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Débranchez votre appareil"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Pour une meilleure résolution, retournez le téléphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable en cours de dépliage"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable en train d\'être retourné"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Charge restante de la pile : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connectez votre stylet à un chargeur"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Pile du stylet faible"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a02c9f7..665e81d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Ajouter des widgets"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Appuyez de manière prolongée pour personnaliser les widgets"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personnaliser les widgets"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Icône d\'appli du widget désactivé"</string>
<string name="edit_widget" msgid="9030848101135393954">"Modifier le widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Supprimer"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ajouter un widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu Marche/Arrêt"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Écran de verrouillage"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Vous pouvez localiser ce téléphone avec Localiser mon appareil même lorsqu\'il est éteint"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Arrêt…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Afficher les étapes d\'entretien"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Afficher les étapes d\'entretien"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Débrancher votre appareil"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Pour une résolution plus élevée, retournez le téléphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable qui est déplié"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable qui est retourné"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de batterie restante"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connectez votre stylet à un chargeur"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"La batterie du stylet est faible"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index e758af8..3764b0f 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Engadir máis widgets"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Pulsación longa para personalizar os widgets"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personalizar widgets"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Icona da aplicación de widget desactivado"</string>
<string name="edit_widget" msgid="9030848101135393954">"Editar widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Quitar"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Engadir widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú de acendido"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Páxina <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueo"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Podes atopar este teléfono (mesmo se está apagado) con Localizar o meu dispositivo"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Apagando…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ver pasos de mantemento"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver pasos de mantemento"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Desconectar o dispositivo"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Dálle a volta ao teléfono para gozar dunha maior resolución"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pregable abríndose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pregable xirando"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batería restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecta o lapis óptico a un cargador"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"O lapis óptico ten pouca batería"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 6d1d8df..52fb9ee 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"વધુ વિજેટ ઉમેરો"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"વિજેટ કસ્ટમાઇઝ કરવા માટે થોડીવાર દબાવી રાખો"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"વિજેટ કસ્ટમાઇઝ કરો"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"બંધ કરેલા વિજેટ માટેની ઍપનું આઇકન"</string>
<string name="edit_widget" msgid="9030848101135393954">"વિજેટમાં ફેરફાર કરો"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"કાઢી નાખો"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"વિજેટ ઉમેરો"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"પાવર મેનૂ"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> માંથી <xliff:g id="ID_1">%1$d</xliff:g> પૃષ્ઠ"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"લૉક સ્ક્રીન"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"આ ફોનનો પાવર બંધ હોય ત્યારે પણ Find My Device વડે તમે તેનું લોકેશન જાણી શકો છો"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"શટ ડાઉન કરી રહ્યાં છીએ…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"સારસંભાળના પગલાં જુઓ"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"સારસંભાળના પગલાં જુઓ"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"તમારા ડિવાઇસને અનપ્લગ કરો"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"વધુ રિઝોલ્યુશન માટે, ફોનને ફ્લિપ કરો"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ફોલ્ડ કરી શકાય એવું ડિવાઇસ અનફોલ્ડ કરવામાં આવી રહ્યું છે"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ફોલ્ડ કરી શકાય એવું ડિવાઇસ ફ્લિપ કરવામાં આવી રહ્યું છે"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> બૅટરી બાકી છે"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"તમારા સ્ટાઇલસને ચાર્જર સાથે કનેક્ટ કરો"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"સ્ટાઇલસની બૅટરીમાં ચાર્જ ઓછો છે"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 2035429..892fa62 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ज़्यादा विजेट जोड़ें"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"विजेट पसंद के मुताबिक बनाने के लिए उसे दबाकर रखें"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"विजेट अपनी पसंद के मुताबिक बनाएं"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"बंद किए गए विजेट के लिए ऐप्लिकेशन आइकॉन"</string>
<string name="edit_widget" msgid="9030848101135393954">"विजेट में बदलाव करें"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"हटाएं"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"विजेट जोड़ें"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"पावर मेन्यू"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"पेज <xliff:g id="ID_2">%2$d</xliff:g> में से <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"लॉक स्क्रीन"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Find My Device की मदद से, फ़ोन बंद होने पर भी इस फ़ोन की जगह की जानकारी का पता लगाया जा सकता है"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"बंद हो रहा है…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"डिवाइस के रखरखाव के तरीके देखें"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"डिवाइस के रखरखाव के तरीके देखें"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"डिवाइस को अनप्लग करें"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"बेहतर रिज़ॉल्यूशन वाली फ़ोटो खींचने के लिए, फ़ोन को फ़्लिप करें"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फ़ोल्ड किया जा सकने वाला डिवाइस अनफ़ोल्ड किया जा रहा है"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फ़ोल्ड किया जा सकने वाला डिवाइस पलटा जा रहा है"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> बैटरी बची है"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"अपने स्टाइलस को चार्ज करें"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"स्टाइलस की बैटरी कम है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index d50a951..f641463 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodavanje još widgeta"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Dugo pritisnite za prilagodbu widgeta"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Prilagodi widgete"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ikona aplikacije za onemogućeni widget"</string>
<string name="edit_widget" msgid="9030848101135393954">"Uredi widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Ukloni"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodaj widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Izbornik tipke za uključivanje/isključivanje"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključani zaslon"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Telefon možete pronaći pomoću usluge Pronađi moj uređaj čak i kada je isključen"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Isključivanje…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Pročitajte upute za održavanje"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pročitajte upute za održavanje"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Iskopčajte uređaj"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za višu razlučivost okrenite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rasklopljen sklopivi uređaj"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Okretanje sklopivog uređaja sa svih strana"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostalo je <xliff:g id="PERCENTAGE">%s</xliff:g> baterije"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Priključite pisaljku na punjač"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Slaba baterija pisaljke"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index b09419b..eadc7da 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"További modulok hozzáadása"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Nyomja meg hosszan a modulok személyre szabásához"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Modulok személyre szabása"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Letiltott modul alkalmazásikonja"</string>
<string name="edit_widget" msgid="9030848101135393954">"Modul szerkesztése"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Eltávolítás"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Modul hozzáadása"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Bekapcsológombhoz tartozó menü"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. oldal, összesen: <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Lezárási képernyő"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"A Készülékkereső segítségével akár a kikapcsolt telefon helyét is meghatározhatja."</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Leállítás…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Olvassa el a kímélő használat lépéseit"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Olvassa el a kímélő használat lépéseit"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Húzza ki az eszközt"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"A nagyobb felbontás érdekében fordítsa meg a telefont"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Összehajtható eszköz kihajtása"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Összehajtható eszköz körbeforgatása"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akkumulátor töltöttségi szintje: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Tegye töltőre az érintőceruzát"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Az érintőceruza töltöttsége alacsony"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4ea86d0..032b57b 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Ավելացնել վիջեթներ"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Երկար սեղմեք՝ վիջեթները հարմարեցնելու համար"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Հարմարեցնել վիջեթները"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Հավելվածի պատկերակ անջատված վիջեթի համար"</string>
<string name="edit_widget" msgid="9030848101135393954">"Փոփոխել վիջեթը"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Հեռացնել"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ավելացնել վիջեթ"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Սնուցման կոճակի ընտրացանկ"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Էջ <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Կողպէկրան"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"«Գտնել իմ սարքը» ծառայության օգնությամբ դուք կարող եք տեղորոշել այս հեռախոսը, նույնիսկ եթե այն անջատված է"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Անջատվում է…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Քայլեր գերտաքացման ահազանգի դեպքում"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Քայլեր գերտաքացման ահազանգի դեպքում"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Անջատեք սարքը"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Ավելի մեծ լուծաչափի համար շրջեք հեռախոսը"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ծալովի սարք՝ բացված վիճակում"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Ծալովի սարք՝ շրջված վիճակում"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ձեր ստիլուսը միացրեք լիցքավորիչի"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Ստիլուսի մարտկոցի լիցքի ցածր մակարդակ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 188f3fb..5442499 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -1226,6 +1226,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Untuk resolusi lebih tinggi, balik ponsel"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Perangkat foldable sedang dibentangkan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Perangkat foldable sedang dibalik"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Baterai tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Hubungkan stilus ke pengisi daya"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Baterai stilus lemah"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 47756c2..077e4de 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Bæta við fleiri græjum"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Haltu inni til að sérsníða græjur"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Sérsníða græjur"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Forritstákn fyrir græju sem slökkt er á"</string>
<string name="edit_widget" msgid="9030848101135393954">"Breyta græju"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Fjarlægja"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Bæta græju við"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Aflrofavalmynd"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Blaðsíða <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Lásskjár"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Þú getur fundið þennan síma með „Finna tækið mitt“, jafnvel þótt slökkt sé á honum"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Slekkur…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Sjá varúðarskref"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Sjá varúðarskref"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Taktu tækið úr sambandi"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Snúðu símanum til að fá betri upplausn"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Samanbrjótanlegt tæki opnað"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Samanbrjótanlegu tæki snúið við"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> hleðsla eftir á rafhlöðu"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Tengdu pennann við hleðslutæki"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Rafhlaða pennans er að tæmast"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 5bad44c..102690a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Aggiungi altri widget"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Premi a lungo per personalizzare i widget"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personalizza widget"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Icona dell\'app per widget disattivati"</string>
<string name="edit_widget" msgid="9030848101135393954">"Modifica widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Rimuovi"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Aggiungi widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu del tasto di accensione"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> di <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Schermata di blocco"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Puoi trovare questo smartphone tramite Trova il mio dispositivo anche quando è spento"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Arresto in corso…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Leggi le misure da adottare"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Leggi le misure da adottare"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Scollega il dispositivo"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Gira il telefono per una maggiore risoluzione"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pieghevole che viene aperto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pieghevole che viene capovolto"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteria rimanente"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connetti lo stilo a un caricabatterie"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Batteria stilo in esaurimento"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 154de15..daca4e3 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"הוספת ווידג\'טים"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"לוחצים לחיצה ארוכה כדי להתאים אישית את הווידג\'טים"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"התאמה אישית של ווידג\'טים"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"סמל האפליקציה לווידג\'ט שהושבת"</string>
<string name="edit_widget" msgid="9030848101135393954">"עריכת הווידג\'ט"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"הסרה"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"הוספת ווידג\'ט"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"תפריט הפעלה"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"דף <xliff:g id="ID_1">%1$d</xliff:g> מתוך <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"מסך נעילה"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"אפשר לאתר את הטלפון הזה עם שירות \'איפה המכשיר שלי\' גם כשהוא כבוי"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"בתהליך כיבוי…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"לצפייה בשלבי הטיפול"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"לצפייה בשלבי הטיפול"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"ניתוק המכשיר"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"כדי לצלם תמונה ברזולוציה גבוהה יותר, כדאי להפוך את הטלפון"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"מכשיר מתקפל עובר למצב לא מקופל"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"מכשיר מתקפל עובר למצב מהופך"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"רמת הטעינה שנותרה בסוללה: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"כדאי לחבר את הסטיילוס למטען"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"הסוללה של הסטיילוס חלשה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 227edd3..a33b95b 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"高解像度で撮るにはスマートフォンを裏返してください"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"折りたたみ式デバイスが広げられている"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"折りたたみ式デバイスがひっくり返されている"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"バッテリー残量 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"タッチペンを充電器に接続してください"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"タッチペンのバッテリー残量が少なくなっています"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 70eeb33..7e3afd9 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ვიჯეტების დამატება"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ხანგრძლივად დააჭირეთ ვიჯეტების მოსარგებად"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"ვიჯეტების მორგება"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"აპის ხატულა გათიშული ვიჯეტისთვის"</string>
<string name="edit_widget" msgid="9030848101135393954">"ვიჯეტის რედაქტირება"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"ამოშლა"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ვიჯეტის დამატება"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ჩართვის მენიუ"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"გვერდი <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>-დან"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"ჩაკეტილი ეკრანი"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"შეგიძლიათ დაადგინოთ ამ ტელეფონის მდებარეობა ფუნქციით „ჩემი მოწყობილობის პოვნა“, მაშინაც კი, როდესაც ის გამორთულია"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"მიმდინარეობს გამორთვა…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"მისაღები ზომების გაცნობა"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"მისაღები ზომების გაცნობა"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"გამოაერᲗეᲗ Თქვენი მოწყობილობა"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"მაღალი გარჩევადობისთვის ამოაბრუნეთ ტელეფონი"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"დასაკეცი მოწყობილობა იხსნება"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"დასაკეცი მოწყობილობა ტრიალებს"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"დარჩენილია ბატარეის <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"დააკავშირეთ თქვენი სტილუსი დამტენს"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"სტილუსის ბატარეა დაცლის პირასაა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index c2525d9..58c3767 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Басқа виджеттер қосыңыз."</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Виджеттерді бейімдеу үшін ұзақ басып тұрыңыз."</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Виджеттерді реттеу"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Өшірілген виджеттің қолданба белгішесі"</string>
<string name="edit_widget" msgid="9030848101135393954">"Виджетті өзгерту"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Өшіру"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Виджет қосу"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Қуат мәзірі"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ішінен <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Құлыптаулы экран"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Сіз бұл телефонды, ол тіпті өшірулі тұрса да Find My Device арқылы таба аласыз."</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Өшіріліп жатыр…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Пайдалану нұсқаулығын қараңыз"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Пайдалану нұсқаулығын қараңыз"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Құрылғыны ажыратыңыз"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Жоғары ажыратымдылық үшін телефонды айналдырыңыз."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Бүктемелі құрылғы ашылып жатыр."</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Бүктемелі құрылғы аударылып жатыр."</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Қалған батарея заряды: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Стилусты зарядтағышқа жалғаңыз."</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Стилус батареясының заряды аз"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 0d25033..7a2291d 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"បញ្ចូលធាតុក្រាហ្វិកច្រើនទៀត"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ចុចឱ្យយូរ ដើម្បីប្ដូរធាតុក្រាហ្វិកតាមបំណង"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"ប្ដូរធាតុក្រាហ្វិកតាមបំណង"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"រូបកម្មវិធីសម្រាប់ធាតុក្រាហ្វិកដែលបានបិទ"</string>
<string name="edit_widget" msgid="9030848101135393954">"កែធាតុក្រាហ្វិក"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"ដកចេញ"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"បញ្ចូលធាតុក្រាហ្វិក"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ម៉ឺនុយថាមពល"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ទំព័រ <xliff:g id="ID_1">%1$d</xliff:g> នៃ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"អេក្រង់ចាក់សោ"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"អ្នកអាចកំណត់ទីតាំងទូរសព្ទនេះដោយប្រើ \"រកឧបករណ៍របស់ខ្ញុំ\" សូម្បីនៅពេលបិទថាមពល"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"កំពុងបិទ…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"មើលជំហានថែទាំ"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"មើលជំហានថែទាំ"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"ដកឧបករណ៍របស់អ្នក"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"សម្រាប់កម្រិតគុណភាពកាន់តែខ្ពស់ សូមត្រឡប់ទូរសព្ទ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ឧបករណ៍អាចបត់បានកំពុងត្រូវបានលា"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ឧបករណ៍អាចបត់បានកំពុងត្រូវបានលា"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"ថ្មនៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"ភ្ជាប់ប៊ិករបស់អ្នកជាមួយឆ្នាំងសាក"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"ថ្មប៊ិកនៅសល់តិច"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 66b8e72..46442ee 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ಹೆಚ್ಚಿನ ವಿಜೆಟ್ಗಳನ್ನು ಸೇರಿಸಿ"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ವಿಜೆಟ್ಗಳನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ದೀರ್ಘಕಾಲ ಒತ್ತಿರಿ"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"ವಿಜೆಟ್ಗಳನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾದ ವಿಜೆಟ್ಗಾಗಿ ಆ್ಯಪ್ ಐಕಾನ್"</string>
<string name="edit_widget" msgid="9030848101135393954">"ವಿಜೆಟ್ ಅನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"ತೆಗೆದುಹಾಕಿ"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ವಿಜೆಟ್ ಅನ್ನು ಸೇರಿಸಿ"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ಪವರ್ ಮೆನು"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="ID_1">%1$d</xliff:g> ಪುಟ"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"ಲಾಕ್ ಪರದೆ"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"ಪವರ್ ಆಫ್ ಆಗಿರುವಾಗಲೂ ನೀವು Find My Device ಮೂಲಕ ಈ ಫೋನ್ ಅನ್ನು ಪತ್ತೆ ಮಾಡಬಹುದು"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"ಶಟ್ ಡೌನ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ಕಾಳಜಿಯ ಹಂತಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ಕಾಳಜಿಯ ಹಂತಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್ಪ್ಲಗ್ ಮಾಡಿ"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ಅಧಿಕ ರೆಸಲ್ಯೂಷನ್ಗಾಗಿ, ಫೋನ್ ಅನ್ನು ಫ್ಲಿಪ್ ಮಾಡಿ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ಫೋಲ್ಡ್ ಮಾಡಬಹುದಾದ ಸಾಧನವನ್ನು ಅನ್ಫೋಲ್ಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ಫೋಲ್ಡ್ ಮಾಡಬಹುದಾದ ಸಾಧನವನ್ನು ಸುತ್ತಲೂ ತಿರುಗಿಸಲಾಗುತ್ತಿದೆ"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಬ್ಯಾಟರಿ ಉಳಿದಿದೆ"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"ನಿಮ್ಮ ಸ್ಟೈಲಸ್ ಅನ್ನು ಚಾರ್ಜರ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"ಸ್ಟೈಲಸ್ ಬ್ಯಾಟರಿ ಕಡಿಮೆಯಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 028c8cf..ffca4bc 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"더 많은 위젯 추가"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"위젯을 맞춤설정하려면 길게 누르기"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"위젯 맞춤설정"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"사용 중지된 위젯의 앱 아이콘"</string>
<string name="edit_widget" msgid="9030848101135393954">"위젯 수정"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"삭제"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"위젯 추가"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"전원 메뉴"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>페이지 중 <xliff:g id="ID_1">%1$d</xliff:g>페이지"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"잠금 화면"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"전원이 꺼져 있을 때도 내 기기 찾기로 이 휴대전화를 찾을 수 있습니다."</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"종료 중…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"해결 방법 확인하기"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"해결 방법 확인하기"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"기기 분리하기"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"해상도를 높이려면 후면 카메라를 사용하세요."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"폴더블 기기를 펼치는 모습"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"폴더블 기기를 뒤집는 모습"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"배터리 <xliff:g id="PERCENTAGE">%s</xliff:g> 남음"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"스타일러스를 충전기에 연결하세요"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"스타일러스 배터리 부족"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 0f00555..9de6b66 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Көбүрөөк виджеттерди кошуу"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Виджеттерди ыңгайлаштыруу үчүн кое бербей басып туруңуз"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Виджеттерди ыңгайлаштыруу"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Өчүрүлгөн виджет үчүн колдонмонун сүрөтчөсү"</string>
<string name="edit_widget" msgid="9030848101135393954">"Виджетти түзөтүү"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Өчүрүү"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Виджет кошуу"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Кубат баскычынын менюсу"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ичинен <xliff:g id="ID_1">%1$d</xliff:g>-бет"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Кулпуланган экран"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Бул телефон өчүк болсо да, аны \"Түзмөгүм кайда?\" кызматы аркылуу таба аласыз"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Өчүрүлүүдө…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Тейлөө кадамдарын көрүңүз"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Тейлөө кадамдарын көрүңүз"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Түзмөктү сууруп коюңуз"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Жогорку дааналык үчүн телефондун арткы камерасын колдонуңуз"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ачылып турган бүктөлмө түзмөк"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Оодарылып жаткан бүктөлмө түзмөк"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Батареянын кубаты: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Стилусту кубаттаңыз"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Стилустун батареясы отурайын деп калды"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index db97655..18ca935 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ເພື່ອຄວາມລະອຽດທີ່ສູງຂຶ້ນ, ໃຫ້ປີ້ນໂທລະສັບ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ອຸປະກອນທີ່ພັບໄດ້ກຳລັງກາງອອກ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ອຸປະກອນທີ່ພັກໄດ້ກຳລັງປີ້ນໄປມາ"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"ແບັດເຕີຣີເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"ເຊື່ອມຕໍ່ປາກກາຂອງທ່ານກັບສາຍສາກ"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"ແບັດເຕີຣີປາກກາເຫຼືອໜ້ອຍ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 9eaab8f..4ea2187 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Pridėkite daugiau valdiklių"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Ilgai paspauskite, kad tinkintumėte valdiklius"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Tinkinti valdiklius"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Išjungto valdiklio programos piktograma"</string>
<string name="edit_widget" msgid="9030848101135393954">"Redaguoti valdiklį"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Pašalinti"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Pridėti valdiklį"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Įjungimo meniu"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g> psl. iš <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Užrakinimo ekranas"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Šį telefoną galite rasti naudodami programą „Rasti įrenginį“, net jei jis išjungtas"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Išjungiama…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Žr. priežiūros veiksmus"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Žr. priežiūros veiksmus"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Atjunkite įrenginį"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Kad raiška būtų geresnė, apverskite telefoną"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Lankstomasis įrenginys išlankstomas"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Lankstomasis įrenginys apverčiamas"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Liko akumuliatoriaus įkrovos: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Prijunkite rašiklį prie kroviklio"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Senka rašiklio akumuliatorius"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index f69afb9..82911ee 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Pievienot citus logrīkus"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Nospiediet un turiet, lai pielāgotu logrīkus."</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Pielāgot logrīkus"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Lietotnes ikona atspējotam logrīkam"</string>
<string name="edit_widget" msgid="9030848101135393954">"Rediģēt logrīku"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Noņemt"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Pievienot logrīku"</string>
@@ -575,10 +574,8 @@
<string name="volume_ringer_status_normal" msgid="1339039682222461143">"Zvanīt"</string>
<string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"Vibrēt"</string>
<string name="volume_ringer_status_silent" msgid="3691324657849880883">"Izslēgt skaņu"</string>
- <!-- no translation found for media_device_cast (4786241789687569892) -->
- <skip />
- <!-- no translation found for stream_notification_unavailable (4313854556205836435) -->
- <skip />
+ <string name="media_device_cast" msgid="4786241789687569892">"Apraide"</string>
+ <string name="stream_notification_unavailable" msgid="4313854556205836435">"Nevar mainīt, jo izslēgts skaņas signāls"</string>
<string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"%1$s. Pieskarieties, lai ieslēgtu skaņu."</string>
<string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"%1$s. Pieskarieties, lai iestatītu uz vibrozvanu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string>
<string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. Pieskarieties, lai izslēgtu skaņu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string>
@@ -839,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Barošanas izvēlne"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. lpp. no <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Bloķēšanas ekrāns"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Lietotni “Atrast ierīci” var izmantot šī tālruņa atrašanās vietas noteikšanai arī tad, ja tālrunis ir izslēgts."</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Notiek izslēgšana…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Skatīt apkopes norādījumus"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Skatīt apkopes norādījumus"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Atvienojiet savu ierīci"</string>
@@ -1228,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Lai izmantotu augstāku izšķirtspēju, apvērsiet tālruni"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Salokāma ierīce tiek atlocīta"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Salokāma ierīce tiek apgriezta"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Atlikušais uzlādes līmenis: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Pievienojiet skārienekrāna pildspalvu lādētājam"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Zems skārienekrāna pildspalvas akumulatora līmenis"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 6ea4d1f..64959bf 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Додајте повеќе виџети"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Притиснете долго за да ги приспособите виџетите"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Приспособете ги виџетите"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Икона за апликација за оневозможен виџет"</string>
<string name="edit_widget" msgid="9030848101135393954">"Изменување виџети"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Отстранува"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Додајте виџет"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Мени на копчето за вклучување"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Страница <xliff:g id="ID_1">%1$d</xliff:g> од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Заклучен екран"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Може да го лоцирате телефонов со „Најди го мојот уред“ дури и кога е исклучен"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Се исклучува…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Прикажи ги чекорите за грижа за уредот"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Прикажи ги чекорите за грижа за уредот"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Исклучете го уредот од кабел"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Отворете го телефонот за да добиете повисока резолуција"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Преклопувачки уред се отклопува"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Преклопувачки уред се врти"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Преостаната батерија: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Поврзете го пенкалото со полнач"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Слаба батерија на пенкало"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 82d257a..aa35171 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ഉയർന്ന റെസല്യൂഷന്, ഫോൺ ഫ്ലിപ്പ് ചെയ്യുക"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ഫോൾഡ് ചെയ്യാവുന്ന ഉപകരണം അൺഫോൾഡ് ആകുന്നു"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ഫോൾഡ് ചെയ്യാവുന്ന ഉപകരണം, കറങ്ങുന്ന വിധത്തിൽ ഫ്ലിപ്പ് ആകുന്നു"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ബാറ്ററി ചാർജ് ശേഷിക്കുന്നു"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"നിങ്ങളുടെ സ്റ്റൈലസ് ചാർജറുമായി കണക്റ്റ് ചെയ്യുക"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"സ്റ്റൈലസിന്റെ ബാറ്ററി ചാർജ് കുറവാണ്"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index aad6a13..4ee598c 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Илүү олон виджет нэмэх"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Виджетүүдийг өөрчлөхийн тулд удаан дарна уу"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Виджетүүдийг өөрчлөх"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Идэвхгүй болгосон виджетийн аппын дүрс тэмдэг"</string>
<string name="edit_widget" msgid="9030848101135393954">"Виджетийг засах"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Хасах"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Виджет нэмэх"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Асаах/унтраах цэс"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>-н <xliff:g id="ID_1">%1$d</xliff:g>-р хуудас"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Түгжээтэй дэлгэц"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Та энэ утсыг унтраалттай байсан ч Миний төхөөрөмжийг олохоор байршлыг нь тогтоох боломжтой"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Унтрааж байна…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Хянамж болгоомжийн алхмыг харах"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Хянамж болгоомжийн алхмыг харах"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Төхөөрөмжөө салгана уу"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Илүү өндөр нягтрал авах бол утсыг хөнтөрнө үү"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Эвхэгддэг төхөөрөмжийг дэлгэж байна"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Эвхэгддэг төхөөрөмжийг хөнтөрч байна"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> батарей үлдлээ"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Мэдрэгч үзгээ цэнэглэгчтэй холбоорой"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Мэдрэгч үзэгний батарей бага байна"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index d7acf5f..326c479 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"आणखी विजेट जोडा"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"विजेट कस्टमाइझ करण्यासाठी प्रेस करून ठेवा"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"विजेट कस्टमाइझ करा"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"बंद केलेल्या विजेटच्या अॅपचे आयकन"</string>
<string name="edit_widget" msgid="9030848101135393954">"विजेट संपादित करा"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"काढून टाका"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"विजेट जोडा"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"पॉवर मेनू"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> पैकी <xliff:g id="ID_1">%1$d</xliff:g> पेज"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"लॉक स्क्रीन"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"तुम्ही हा फोन बंद असतानादेखील Find My Device वापरून तो शोधू शकता"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"बंद होत आहे…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"काय काळजी घ्यावी ते पहा"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"काय काळजी घ्यावी ते पहा"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"तुमचे डिव्हाइस अनप्लग करा"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"उच्च रेझोल्यूशनसाठी, फोन फ्लिप करा"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फोल्ड करता येण्यासारखे डिव्हाइस अनफोल्ड केले जात आहे"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फोल्ड करता येण्यासारखे डिव्हाइस आजूबाजूला फ्लिप केले जात आहे"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> बॅटरी शिल्लक आहे"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"तुमचे स्टायलस चार्जरशी कनेक्ट करा"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"स्टायलस बॅटरी कमी आहे"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 03cd0a0..b2afce9 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Tambahkan lagi widget"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Tekan lama untuk menyesuaikan widget"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Sesuaikan widget"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ikon apl untuk melumpuhkan widget"</string>
<string name="edit_widget" msgid="9030848101135393954">"Edit widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Alih keluar"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Tambahkan widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu kuasa"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> daripada <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Kunci skrin"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Anda boleh mengesan telefon ini dengan Find My Device walaupun apabila telefon ini dimatikan kuasa"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Mematikan…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Lihat langkah penjagaan"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Lihat langkah penjagaan"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Cabut palam peranti anda"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Untuk peleraian lebih tinggi, balikkan telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Peranti boleh lipat dibuka"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Peranti boleh lipat diterbalikkan"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateri tinggal <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Sambungkan stilus anda kepada pengecas"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Bateri stilus lemah"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index c6d46bc..a4f91fa 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"နောက်ထပ်ဝိဂျက်များ ထည့်ရန်"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ဝိဂျက်များ စိတ်ကြိုက်လုပ်ရန် ကြာကြာနှိပ်ထားပါ"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"ဝိဂျက်များကို စိတ်ကြိုက်လုပ်ရန်"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"ပိတ်ထားသော ဝိဂျက်အတွက် အက်ပ်သင်္ကေတ"</string>
<string name="edit_widget" msgid="9030848101135393954">"ဝိဂျက်ပြင်ရန်"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"ဖယ်ရှားရန်"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ဝိဂျက်ထည့်ရန်"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ပါဝါမီနူး"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"စာမျက်နှာ <xliff:g id="ID_2">%2$d</xliff:g> အနက်မှ စာမျက်နှာ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"လော့ခ်ချထားချိန် မျက်နှာပြင်"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"ပါဝါပိတ်ထားသော်လည်း Find My Device ဖြင့် ဤဖုန်းကို ရှာနိုင်သည်"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"စက်ပိတ်နေသည်…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ဂရုပြုစရာ အဆင့်များ ကြည့်ရန်"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ဂရုပြုစရာ အဆင့်များ ကြည့်ရန်"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"သင့်စက်ကို ပလတ်ဖြုတ်ပါ"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ပုံရိပ် ပိုမိုပြတ်သားစေရန် ဖုန်းကို တစ်ဖက်သို့ လှန်လိုက်ပါ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ခေါက်နိုင်သောစက်ကို ဖြန့်လိုက်သည်"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ခေါက်နိုင်သောစက်ကို တစ်ဘက်သို့ လှန်လိုက်သည်"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"ဘက်ထရီ <xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်သေးသည်"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"စတိုင်လပ်စ်ကို အားသွင်းကိရိယာနှင့် ချိတ်ဆက်ခြင်း"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"စတိုင်လပ်စ် ဘက်ထရီ အားနည်းနေသည်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a2b97ee..e968fb5 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Legg til flere moduler"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Trykk lenge for å tilpasse modulene"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Tilpass moduler"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Appikon for deaktivert modul"</string>
<string name="edit_widget" msgid="9030848101135393954">"Endre modul"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Fjern"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Legg til modul"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Av/på-meny"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Side <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Låseskjerm"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Du kan finne denne telefonen med Finn enheten min, selv når den er slått av"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Slår av …"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Se vedlikeholdstrinnene"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Se vedlikeholdstrinnene"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Koble fra enheten"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Brett ut telefonen for å få høyere oppløsning"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En sammenleggbar enhet blir brettet ut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En sammenleggbar enhet blir snudd"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteri gjenstår"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Koble pekepennen til en lader"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Det er lite batteri i pekepennen"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 1388a85..f12bd70 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"थप विजेटहरू हाल्नुहोस्"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"विजेटहरू कस्टमाइज गर्न केही बेरसम्म थिच्नुहोस्"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"विजेटहरू कस्टमाइज गर्नुहोस्"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"अफ गरिएको विजेटको एप जनाउने आइकन"</string>
<string name="edit_widget" msgid="9030848101135393954">"विजेट सम्पादन गर्नुहोस्"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"हटाउनुहोस्"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"विजेट हाल्नुहोस्"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"पावर मेनु"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> मध्ये पृष्ठ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"लक स्क्रिन"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"तपाईं Find My Device प्रयोग गरी यो फोन अफ भए पनि यसको लोकेसन पत्ता लगाउन सक्नुहुन्छ"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"सट डाउन गरिँदै छ..."</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"डिभाइसको हेरचाह गर्ने तरिका हेर्नुहोस्"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"डिभाइसको हेरचाह गर्ने तरिका हेर्नुहोस्"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"डिभाइस बिजुलीको स्रोतबाट निकाल्नुहोस्"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"उच्च रिजोल्युसनको सेल्फी खिच्न फोन फ्लिप गर्नुहोस्"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फोल्ड गर्न मिल्ने डिभाइस अनफोल्ड गरेको देखाइएको एनिमेसन"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फोल्ड गर्न मिल्ने डिभाइस यताउता पल्टाएर देखाइएको एनिमेसन"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ब्याट्री बाँकी छ"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"आफ्नो स्टाइलस चार्जरमा कनेक्ट गर्नुहोस्"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"स्टाइलसको ब्याट्री लो छ"</string>
diff --git a/packages/SystemUI/res/values-night/styles.xml b/packages/SystemUI/res/values-night/styles.xml
index b6971d3..291f8a2 100644
--- a/packages/SystemUI/res/values-night/styles.xml
+++ b/packages/SystemUI/res/values-night/styles.xml
@@ -53,6 +53,11 @@
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowLightStatusBar">false</item>
+
+ <!--
+ TODO(b/309578419): Make activities handle insets properly and then remove this.
+ -->
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
</style>
<style name="TextAppearance.InternetDialog.Active">
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 09156cf..01aa8db 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Meer widgets toevoegen"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Houd lang ingedrukt om widgets aan te passen"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Widgets aanpassen"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"App-icoon voor uitgezette widget"</string>
<string name="edit_widget" msgid="9030848101135393954">"Widget bewerken"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Verwijderen"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Widget toevoegen"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Aan/uit-menu"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Vergrendelscherm"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Je kunt deze telefoon vinden met Vind mijn apparaat, ook als die uitstaat"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Uitzetten…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Onderhoudsstappen bekijken"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Onderhoudsstappen bekijken"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Je apparaat loskoppelen"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Draai de telefoon om voor een hogere resolutie"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Opvouwbaar apparaat wordt uitgevouwen"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Opvouwbaar apparaat wordt gedraaid"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Nog <xliff:g id="PERCENTAGE">%s</xliff:g> batterijlading"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Verbind je stylus met een oplader"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Batterij van stylus bijna leeg"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index b49c297..9b46c20 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ଅଧିକ ୱିଜେଟ ଯୋଗ କରନ୍ତୁ"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ୱିଜେଟଗୁଡ଼ିକୁ କଷ୍ଟମାଇଜ କରିବା ପାଇଁ ଅଧିକ ସମୟ ଦବାନ୍ତୁ"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"ୱିଜେଟଗୁଡ଼ିକୁ କଷ୍ଟମାଇଜ କରନ୍ତୁ"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"ଅକ୍ଷମ କରାଯାଇଥିବା ୱିଜେଟ ପାଇଁ ଆପ ଆଇକନ"</string>
<string name="edit_widget" msgid="9030848101135393954">"ୱିଜେଟକୁ ଏଡିଟ କରନ୍ତୁ"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"କାଢ଼ି ଦିଅନ୍ତୁ"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ୱିଜେଟ ଯୋଗ କରନ୍ତୁ"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ପାୱାର ମେନୁ"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ପୃଷ୍ଠା <xliff:g id="ID_1">%1$d</xliff:g> ମୋଟ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"ଲକ ସ୍କ୍ରିନ"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"ପାୱାର ବନ୍ଦ ଥିଲେ ମଧ୍ୟ ଆପଣ Find My Device ମାଧ୍ୟମରେ ଏହି ଫୋନକୁ ଖୋଜିପାରିବେ"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"ବନ୍ଦ କରାଯାଉଛି…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ଯତ୍ନ ନେବା ପାଇଁ ଷ୍ଟେପଗୁଡ଼ିକ ଦେଖନ୍ତୁ"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ଯତ୍ନ ନେବା ପାଇଁ ଷ୍ଟେପଗୁଡ଼ିକ ଦେଖନ୍ତୁ"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନପ୍ଲଗ କରନ୍ତୁ"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ଉଚ୍ଚ ରିଜୋଲ୍ୟୁସନ ପାଇଁ ଫୋନକୁ ଫ୍ଲିପ କରନ୍ତୁ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଅନଫୋଲ୍ଡ କରାଯାଉଛି"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଫ୍ଲିପ କରାଯାଉଛି"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ବେଟେରୀ ଚାର୍ଜ ବାକି ଅଛି"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"ଏକ ଚାର୍ଜର ସହ ଆପଣଙ୍କ ଷ୍ଟାଇଲସକୁ କନେକ୍ଟ କରନ୍ତୁ"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"ଷ୍ଟାଇଲସ ବେଟେରୀର ଚାର୍ଜ କମ ଅଛି"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index cd55198..ac2badc 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ਹੋਰ ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ਵਿਜੇਟਾਂ ਨੂੰ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਦਬਾਈ ਰੱਖੋ"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"ਵਿਜੇਟ ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"ਬੰਦ ਵਿਜੇਟ ਲਈ ਐਪ ਪ੍ਰਤੀਕ"</string>
<string name="edit_widget" msgid="9030848101135393954">"ਵਿਜੇਟ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"ਹਟਾਓ"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰੋ"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ਪਾਵਰ ਮੀਨੂ"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ਦਾ <xliff:g id="ID_1">%1$d</xliff:g> ਪੰਨਾ"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">" ਲਾਕ ਸਕ੍ਰੀਨ"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"ਬੰਦ ਹੋਣ \'ਤੇ ਵੀ, ਤੁਸੀਂ ਇਸ ਫ਼ੋਨ ਨੂੰ Find My Device ਦੀ ਮਦਦ ਨਾਲ ਲੱਭ ਸਕਦੇ ਹੋ"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"ਬੰਦ ਹੋ ਰਿਹਾ ਹੈ…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ਦੇਖਭਾਲ ਦੇ ਪੜਾਅ ਦੇਖੋ"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ਦੇਖਭਾਲ ਦੇ ਪੜਾਅ ਦੇਖੋ"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"ਆਪਣਾ ਡੀਵਾਈਸ ਅਣਪਲੱਗ ਕਰੋ"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ਉੱਚ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਲਈ, ਫ਼ੋਨ ਨੂੰ ਫਲਿੱਪ ਕਰੋ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ਮੋੜਨਯੋਗ ਡੀਵਾਈਸ ਨੂੰ ਖੋਲ੍ਹਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ਮੋੜਨਯੋਗ ਡੀਵਾਈਸ ਨੂੰ ਆਲੇ-ਦੁਆਲੇ ਫਲਿੱਪ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬੈਟਰੀ ਬਾਕੀ"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"ਆਪਣੇ ਸਟਾਈਲਸ ਨੂੰ ਚਾਰਜਰ ਨਾਲ ਕਨੈਕਟ ਕਰੋ"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"ਸਟਾਈਲਸ ਦੀ ਬੈਟਰੀ ਘੱਟ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 76547ed..a7d2b0a 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodaj więcej widżetów"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Przytrzymaj, aby dostosować widżety"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Dostosuj widżety"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ikona aplikacji z wyłączonym widżetem"</string>
<string name="edit_widget" msgid="9030848101135393954">"Edytuj widżet"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Usuń"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodaj widżet"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu zasilania"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Strona <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran blokady"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Możesz zlokalizować ten telefon w usłudze Znajdź moje urządzenie, nawet jeśli będzie wyłączony"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Wyłączam…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Zobacz instrukcję postępowania"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Zobacz instrukcję postępowania"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Odłącz urządzenie"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Odwróć telefon, aby uzyskać wyższą rozdzielczość"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Składane urządzenie jest rozkładane"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Składane urządzenie jest obracane"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g> baterii"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Podłącz rysik do ładowarki"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Słaba bateria w rysiku"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 598ef78..8a4ce33 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Adicione mais widgets"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantenha pressionado para personalizar widgets"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personalizar widgets"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ícone do app para widget desativado"</string>
<string name="edit_widget" msgid="9030848101135393954">"Editar widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Remover"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Adicionar widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu liga/desliga"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Tela de bloqueio"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Localize o smartphone com o Encontre Meu Dispositivo mesmo se ele estiver desligado"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Desligando…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ver etapas de cuidado"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver etapas de cuidado"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Desconecte seu dispositivo"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para uma resolução maior, vire o smartphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateria restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecte sua stylus a um carregador"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Bateria da stylus fraca"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 7e5a736..011776c 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para uma resolução superior, inverta o telemóvel"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável a ser desdobrado"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável a ser virado ao contrário"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de bateria restante"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ligue a caneta stylus a um carregador"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Bateria da caneta stylus fraca"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 598ef78..8a4ce33 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Adicione mais widgets"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantenha pressionado para personalizar widgets"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personalizar widgets"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ícone do app para widget desativado"</string>
<string name="edit_widget" msgid="9030848101135393954">"Editar widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Remover"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Adicionar widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu liga/desliga"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Tela de bloqueio"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Localize o smartphone com o Encontre Meu Dispositivo mesmo se ele estiver desligado"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Desligando…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ver etapas de cuidado"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver etapas de cuidado"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Desconecte seu dispositivo"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para uma resolução maior, vire o smartphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateria restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecte sua stylus a um carregador"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Bateria da stylus fraca"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 026e22b..589b768 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Adaugă mai multe widgeturi"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Apasă lung pentru a personaliza widgeturi"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personalizează widgeturile"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Pictograma aplicației pentru widgetul dezactivat"</string>
<string name="edit_widget" msgid="9030848101135393954">"Editează widgetul"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Elimină"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Adaugă un widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meniul de pornire"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> din <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Ecran de blocare"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Poți localiza telefonul folosind aplicația Găsește-mi dispozitivul chiar dacă este închis"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Se închide…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Vezi pașii pentru îngrijire"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Vezi pașii pentru îngrijire"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Deconectează dispozitivul"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Pentru o rezoluție mai mare, deschide telefonul"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispozitiv pliabil care este desfăcut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispozitiv pliabil care este întors"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> baterie rămasă"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conectează-ți creionul la un încărcător"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Nivelul bateriei creionului este scăzut"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 1df112b..5b16bc5 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Добавить виджеты"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Нажмите и удерживайте, чтобы настроить виджеты."</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Настроить виджеты"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Значок приложения для отключенного виджета"</string>
<string name="edit_widget" msgid="9030848101135393954">"Изменить виджет"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Удалить"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Добавить виджет"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню кнопки питания"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Страница <xliff:g id="ID_1">%1$d</xliff:g> из <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Заблокированный экран"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"С помощью приложения \"Найти устройство\" вы можете узнать местоположение телефона, даже когда он выключен."</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Выключение…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Подробнее о действиях при перегреве…"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Подробнее о действиях при перегреве…"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Отключите устройство"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Переверните телефон и используйте основную камеру, чтобы делать снимки с более высоким разрешением."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складное устройство в разложенном виде"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Перевернутое складное устройство"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Уровень заряда батареи: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Поставьте стилус на зарядку."</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Низкий заряд батареи стилуса"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index f4b7d1e..e240c40 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"තවත් විජට් එක් කරන්න"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"විජට් අභිරුචිකරණය කිරීමට දිගු ඔබන්න"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"විජට්ටු අභිරුචි කරන්න"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"අබල කළ විජට් සඳහා යෙදුම් නිරූපකය"</string>
<string name="edit_widget" msgid="9030848101135393954">"විජට්ටු සංස්කරණ කරන්න"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"ඉවත් කරන්න"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"විජට්ටුව එක් කරන්න"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"බල මෙනුව"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> න් <xliff:g id="ID_1">%1$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"අගුලු තිරය"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"බලය ක්රියාවිරහිත වූ විට පවා ඔබට මගේ උපාංගය සෙවීම මගින් මෙම දුරකථනය සොයාගත හැක"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"වසා දමමින්…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"රැකවරණ පියවර බලන්න"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"රැකවරණ පියවර බලන්න"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"ඔබේ උපාංගය ගලවන්න"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ඉහළ විභේදනය සඳහා, දුරකථනය හරවන්න"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"දිග හැරෙමින් පවතින නැමිය හැකි උපාංගය"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"වටා පෙරළෙමින් තිබෙන නැමිය හැකි උපාංගය"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> බැටරිය ඉතිරිව ඇත"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"ඔබේ පන්හිඳ චාජරයකට සම්බන්ධ කරන්න"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"පන්හිඳ බැටරිය අඩුයි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 0f579da..943adb1 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Pridať ďalšie miniaplikácie"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Miniaplikácie prispôsobíte dlhým stlačením"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Prispôsobiť miniaplikácie"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ikona deaktivovanej miniaplikácie"</string>
<string name="edit_widget" msgid="9030848101135393954">"Upraviť miniaplikáciu"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Odstrániť"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Pridať miniaplikáciu"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Ponuka vypínača"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Strana <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Uzamknutá obrazovka"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Pomocou funkcie Nájdi moje zariadenie môžete zistiť polohu tohto telefónu, aj keď je vypnutý"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Vypína sa…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Zobraziť opatrenia"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Zobraziť opatrenia"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Odpojte zariadenie"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Ak chcete vyššie rozlíšenie, prevráťte telefón"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozloženie skladacieho zariadenia"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Prevrátenie skladacieho zariadenia"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g> batérie"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Pripojte dotykové pero k nabíjačke"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Stav batérie dotykového pera je nízky"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 7acaa54..e4b33aa 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodajte več pripomočkov"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Pridržite za prilagajanje pripomočkov"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Prilagajanje pripomočkov"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ikona aplikacije za onemogočen pripomoček"</string>
<string name="edit_widget" msgid="9030848101135393954">"Urejanje pripomočka"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Odstrani"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodajanje pripomočka"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meni za vklop/izklop"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. stran od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Zaklenjen zaslon"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"S storitvijo Poišči mojo napravo lahko ta telefon poiščete, tudi če je izklopljen"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Zaustavljanje …"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Oglejte si navodila za ukrepanje"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Oglejte si navodila za ukrepanje"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Odklopite napravo"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za višjo ločljivost obrnite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Razpiranje zložljive naprave"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Obračanje zložljive naprave"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostanek energije baterije: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Povežite pisalo s polnilnikom."</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Skoraj prazna baterija pisala"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 21a974f..3248a96 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Shto miniaplikacione të tjera"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Shtyp gjatë për të personalizuar miniaplikacionet"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Personalizo miniaplikacionet"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Ikona e aplikacionit për miniaplikacionin e çaktivizuar"</string>
<string name="edit_widget" msgid="9030848101135393954">"Modifiko miniaplikacionin"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Hiq"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Shto miniaplikacionin"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menyja e energjisë"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Faqja <xliff:g id="ID_1">%1$d</xliff:g> nga <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Ekrani i kyçjes"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Mund ta gjesh këtë telefon me \"Gjej pajisjen time\" edhe kur është i fikur"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Po fiket…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Shiko hapat për kujdesin"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Shiko hapat për kujdesin"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Shkëpute pajisjen"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Për rezolucion më të lartë, përmbys telefonin"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Pajisja e palosshme duke u hapur"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Pajisja e palosshme duke u rrotulluar"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Përqindja e mbetur e baterisë: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Lidhe stilolapsin me një karikues"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Bateria e stilolapsit në nivel të ulët"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 2f52f90..a80aee3 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Додајте још виџета"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Дуги притисак за прилагођавање виџета"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Прилагоди виџете"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Икона апликације за онемогућен виџет"</string>
<string name="edit_widget" msgid="9030848101135393954">"Измени виџет"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Уклони"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Додај виџет"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Мени дугмета за укључивање"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. страна од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Закључан екран"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Можете да лоцирате овај телефон помоћу услуге Пронађи мој уређај чак и када је искључен"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Искључује се…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Погледајте упозорења"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Погледајте упозорења"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Искључите уређај"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"За већу резолуцију обрните телефон"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Уређај на преклоп се отвара"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Уређај на преклоп се обрће"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Преостало је још<xliff:g id="PERCENTAGE">%s</xliff:g> батерије"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Повежите писаљку са пуњачем"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Низак ниво батерије писаљке"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 20bc7e7..49ddff0 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Lägg till fler widgetar"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Tryck länge för att anpassa widgetar"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Anpassa widgetar"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Appikon för inaktiverad widget"</string>
<string name="edit_widget" msgid="9030848101135393954">"Redigera widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Ta bort"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Lägg till widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Startmeny"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Sida <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Låsskärm"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Du kan hitta den här telefonen med Hitta min enhet även när den är avstängd"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Avslutar …"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Visa alla skötselråd"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Visa alla skötselråd"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Koppla ur enheten"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Vänd telefonen för högre upplösning"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En vikbar enhet viks upp"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En vikbar enhet vänds"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> av batteriet återstår"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Anslut e-pennan till en laddare"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"E-pennans batterinivå är låg"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index fa0e7b5..7fcdc07 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Weka wijeti zingine"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Bonyeza kwa muda mrefu uweke mapendeleo ya wijeti"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Badilisha wijeti upendavyo"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Aikoni ya programu ya wijeti iliyozimwa"</string>
<string name="edit_widget" msgid="9030848101135393954">"Badilisha wijeti"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Ondoa"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ongeza wijeti"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menyu ya kuzima/kuwasha"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Ukurasa wa <xliff:g id="ID_1">%1$d</xliff:g> kati ya <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Skrini iliyofungwa"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Unaweza kutambua mahali ilipo simu hii ukitumia programu ya Tafuta Kifaa Changu hata kama simu hiyo imezimwa"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Inazima…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Angalia hatua za utunzaji"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Angalia hatua za utunzaji"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Chomoa kifaa chako"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Kwa ubora wa juu, geuza simu"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Kifaa kinachokunjwa kikikunjuliwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Kifaa kinachokunjwa kikigeuzwa"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Chaji ya betri imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Unganisha stylus yako kwenye chaja"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Chaji ya betri ya Stylus imepungua"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 0f360e6..cf2b3ee 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"கூடுதல் விட்ஜெட்களைச் சேருங்கள்"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"விட்ஜெட்களைப் பிரத்தியேகமாக்க நீண்ட நேரம் அழுத்துக"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"விட்ஜெட்களைப் பிரத்தியேகமாக்குங்கள்"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"முடக்கப்பட்ட விட்ஜெட்டுக்கான ஆப்ஸ் ஐகான்"</string>
<string name="edit_widget" msgid="9030848101135393954">"விட்ஜெட்டைத் திருத்து"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"அகற்றும்"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"விட்ஜெட்டைச் சேர்"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"பவர் மெனு"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"பக்கம் <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"லாக் ஸ்கிரீன்"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"மொபைல் பவர் ஆஃப் செய்யப்பட்டிருக்கும்போதும் Find My Device மூலம் அதன் இருப்பிடத்தைக் கண்டறியலாம்"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"ஷட் டவுன் ஆகிறது…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"மேலும் விவரங்களுக்கு இதைப் பார்க்கவும்"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"மேலும் விவரங்களுக்கு இதைப் பார்க்கவும்"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"சாதன இணைப்பைத் துண்டித்தல்"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"உயர் தெளிவுத்திறனுக்கு, மொபைலை ஃபிளிப் செய்யுங்கள்"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"மடக்கத்தக்க சாதனம் திறக்கப்படுகிறது"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"மடக்கத்தக்க சாதனம் ஃபிளிப் செய்யப்பட்டு திருப்பப்படுகிறது"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> பேட்டரி மீதமுள்ளது"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"உங்கள் ஸ்டைலஸைச் சார்ஜருடன் இணையுங்கள்"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"ஸ்டைலஸின் பேட்டரி குறைவாக உள்ளது"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 4e8e2d0..e63ed1f 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"మరిన్ని విడ్జెట్లను జోడించండి"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"విడ్జెట్లను అనుకూలీకరించడానికి, నొక్కి, ఉంచండి"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"విడ్జెట్లను అనుకూలంగా మార్చండి"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"డిజేబుల్ చేయబడిన విడ్జెట్ కోసం యాప్ చిహ్నం"</string>
<string name="edit_widget" msgid="9030848101135393954">"విడ్జెట్ను ఎడిట్ చేయండి"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"తీసివేయండి"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"విడ్జెట్ను జోడించండి"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"పవర్ మెనూ"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>లో <xliff:g id="ID_1">%1$d</xliff:g>వ పేజీ"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"లాక్ స్క్రీన్"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"పవర్ ఆఫ్లో ఉన్నప్పుడు కూడా మీరు Find My Deviceతో ఈ ఫోన్ను గుర్తించవచ్చు"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"షట్ డౌన్ చేయబడుతోంది…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"తీసుకోవాల్సిన జాగ్రత్తలు ఏమిటో చూడండి"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"తీసుకోవాల్సిన జాగ్రత్తలు ఏమిటో చూడండి"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"మీ పరికరాన్ని అన్ప్లగ్ చేయండి"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"అధిక రిజల్యూషన్ కోసం, ఫోన్ను తిప్పండి"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"మడవగల పరికరం విప్పబడుతోంది"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"మడవగల పరికరం చుట్టూ తిప్పబడుతోంది"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> బ్యాటరీ మిగిలి ఉంది"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"మీ స్టైలస్ను ఛార్జర్కి కనెక్ట్ చేయండి"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"తక్కువ స్టైలస్ బ్యాటరీ"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 98075c5..9d3683e 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"เพิ่มวิดเจ็ตอีก"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"กดค้างเพื่อปรับแต่งวิดเจ็ต"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"ปรับแต่งวิดเจ็ต"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"ไอคอนแอปสำหรับวิดเจ็ตที่ปิดใช้อยู่"</string>
<string name="edit_widget" msgid="9030848101135393954">"แก้ไขวิดเจ็ต"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"นำออก"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"เพิ่มวิดเจ็ต"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"เมนูเปิด/ปิด"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"หน้า <xliff:g id="ID_1">%1$d</xliff:g> จาก <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"หน้าจอล็อก"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"คุณจะหาตำแหน่งของโทรศัพท์นี้ได้ด้วยแอปหาอุปกรณ์ของฉันแม้จะปิดเครื่องอยู่ก็ตาม"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"กำลังปิด…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ดูขั้นตอนในการดูแลรักษา"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ดูขั้นตอนในการดูแลรักษา"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"ถอดปลั๊กอุปกรณ์"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"พลิกด้านโทรศัพท์เพื่อให้ได้ภาพที่มีความละเอียดมากขึ้น"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"อุปกรณ์ที่พับได้กำลังกางออก"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"อุปกรณ์ที่พับได้กำลังพลิกไปมา"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"เหลือแบตเตอรี่ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"เชื่อมต่อสไตลัสกับที่ชาร์จ"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"แบตเตอรี่สไตลัสเหลือน้อย"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index ff8d84f..5098f55 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Magdagdag ng higit pang widget"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Pindutin nang matagal para i-customize ang mga widget"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"I-customize ang mga widget"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Icon ng app para sa na-disable na widget"</string>
<string name="edit_widget" msgid="9030848101135393954">"I-edit ang widget"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Alisin"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Magdagdag ng widget"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Power menu"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> ng <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Lock screen"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Puwede mong hanapin ang teleponong ito gamit ang Hanapin ang Aking Device kahit kapag naka-off ito"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Nagsa-shut down…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Tingnan ang mga hakbang sa pangangalaga"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Tingnan ang mga hakbang sa pangangalaga"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Bunutin sa saksakan ang device"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para sa mas mataas na resolution, i-flip ang telepono"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ina-unfold na foldable na device"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Fini-flip na foldable na device"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> baterya na lang ang natitira"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ikonekta sa charger ang iyong stylus"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Paubos na ang baterya ng stylus"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 2cdc6e7..71de31b 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Daha fazla widget ekle"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Widget\'ları özelleştirmek için uzun basın"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Widget\'ları özelleştir"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Devre dışı bırakılan widget\'ın uygulama simgesi"</string>
<string name="edit_widget" msgid="9030848101135393954">"Widget\'ı düzenle"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Kaldır"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Widget ekle"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Güç menüsü"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Sayfa <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Kilit ekranı"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Bu telefonu kapalıyken bile Cihazımı Bul işleviyle bulabilirsiniz."</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Kapanıyor…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Bakımla ilgili adımlara bakın"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Bakımla ilgili adımlara bakın"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Cihazınızın fişini çekin"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Daha yüksek çözünürlük için telefonu çevirin"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Katlanabilir cihaz açılıyor"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Katlanabilir cihaz döndürülüyor"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> pil kaldı"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ekran kaleminizi bir şarj cihazına bağlayın"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Ekran kaleminin pil seviyesi düşük"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index c89ae75..c82acb1 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Додати більше віджетів"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Утримуйте, щоб налаштувати віджети"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Налаштувати віджети"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Значок додатка для вимкненого віджета"</string>
<string name="edit_widget" msgid="9030848101135393954">"Редагувати віджет"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Видалити"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Додати віджет"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню кнопки живлення"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Сторінка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Заблокований екран"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Ви зможете визначити місцеположення цього телефона, навіть коли його вимкнено, за допомогою сервісу Знайти пристрій"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Вимкнення…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Переглянути запобіжні заходи"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Переглянути запобіжні заходи"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Від’єднайте пристрій"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Для вищої роздільної здатності переверніть телефон"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Розкладний пристрій у розкладеному стані"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Розкладний пристрій обертається"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Заряд акумулятора: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Підключіть стилус до зарядного пристрою"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Низький заряд акумулятора стилуса"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 3237f32..16f37bd 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1223,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"زیادہ ریزولوشن کے لیے، فون پلٹائیں"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"فولڈ ہونے والے آلے کو کھولا جا رہا ہے"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"فولڈ ہونے والے آلے کو گھمایا جا رہا ہے"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> بیٹری باقی ہے"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"اپنے اسٹائلس کو چارجر منسلک کریں"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"اسٹائلس بیٹری کم ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 478fcdb..5a5ac38 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Koʻproq vidjetlar qoʻshish"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Vidjetlarni sozlash uchun bosib turing"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Vidjetlarni moslashtirish"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Faolsizlantirilgan vidjet uchun ilova belgisi"</string>
<string name="edit_widget" msgid="9030848101135393954">"Vidjetni tahrirlash"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Olib tashlash"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Vidjet kiritish"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Quvvat menyusi"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>-sahifa, jami: <xliff:g id="ID_2">%2$d</xliff:g> ta sahifa"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran qulfi"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Oʻchiq boʻlsa ham “Qurilmani top” funksiyasi yordamida bu telefonni topish mumkin"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Oʻchirilmoqda…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Batafsil axborot"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Batafsil axborot"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Qurilmani uzing"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Yuqori aniqlik uchun telefonni aylantiring"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Buklanadigan qurilma ochilmoqda"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Buklanadigan qurilma aylantirilmoqda"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batareya quvvati: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Stilusni quvvat manbaiga ulang"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Stilus batareyasi kam"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 7e8638b..8c174c0 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Thêm tiện ích khác"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Nhấn và giữ để tuỳ chỉnh tiện ích"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Tuỳ chỉnh tiện ích"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Biểu tượng ứng dụng của tiện ích đã bị vô hiệu hoá"</string>
<string name="edit_widget" msgid="9030848101135393954">"Chỉnh sửa tiện ích"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Xoá"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Thêm tiện ích"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Trình đơn nguồn"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Trang <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Màn hình khóa"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Bạn có thể định vị chiếc điện thoại này bằng ứng dụng Tìm thiết bị của tôi ngay cả khi điện thoại tắt nguồn"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Đang tắt…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Xem các bước chăm sóc"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Xem các bước chăm sóc"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Rút thiết bị ra"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Để có độ phân giải cao hơn, hãy lật điện thoại"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Thiết bị có thể gập lại đang được mở ra"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Thiết bị có thể gập lại đang được lật ngược"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Còn <xliff:g id="PERCENTAGE">%s</xliff:g> pin"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Hãy kết nối bút cảm ứng với bộ sạc"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Bút cảm ứng bị yếu pin"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 2552138..c0cdb76 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"添加更多微件"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"长按即可自定义微件"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"自定义微件"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"已停用微件的应用图标"</string>
<string name="edit_widget" msgid="9030848101135393954">"修改微件"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"移除"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"添加微件"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"电源菜单"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 页,共 <xliff:g id="ID_2">%2$d</xliff:g> 页"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"锁定屏幕"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"即使手机已关机,您也可以通过“查找我的设备”找到这部手机"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"正在关机…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"查看处理步骤"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"查看处理步骤"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"拔出设备"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"若要获得更高的分辨率,请翻转手机"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展开可折叠设备"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻转可折叠设备"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"电池还剩 <xliff:g id="PERCENTAGE">%s</xliff:g> 的电量"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"请将触控笔连接充电器"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"触控笔电池电量低"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 5941dad..f263240 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"新增更多小工具"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"長按即可自訂小工具"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"自訂小工具"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"已停用小工具的應用程式圖示"</string>
<string name="edit_widget" msgid="9030848101135393954">"編輯小工具"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"移除"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"新增小工具"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源選單"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁 (共 <xliff:g id="ID_2">%2$d</xliff:g> 頁)"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"螢幕鎖定"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"即使手機關機,仍可透過「尋找我的裝置」尋找此手機"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"正在關機…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"查看保養步驟"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"查看保養步驟"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"拔除裝置"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"如要提高解像度,請切換至手機後置鏡頭"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"剩餘電量:<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"將觸控筆連接充電器"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"觸控筆電量不足"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index c46d831..35af972 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"新增更多小工具"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"長按即可自訂小工具"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"自訂小工具"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"所停用小工具的應用程式圖示"</string>
<string name="edit_widget" msgid="9030848101135393954">"編輯小工具"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"移除"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"新增小工具"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源鍵選單"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"鎖定畫面"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"即使這支手機關機,仍可透過「尋找我的裝置」找出手機位置"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"關機中…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"查看處理步驟"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"查看處理步驟"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"拔除裝置"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"如要提高解析度,請切換至手機後置鏡頭"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開的折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"剩餘電量:<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"將觸控筆接上充電器"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"觸控筆電力不足"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 0bbac05..9069964 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -429,8 +429,7 @@
<string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Engeza amawijethi engeziwe"</string>
<string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Cindezela isikhathi eside ukuze wenze ngokwezifiso amawijethi"</string>
<string name="button_to_configure_widgets_text" msgid="4191862850185256901">"Yenza ngokwezifiso amawijethi"</string>
- <!-- no translation found for icon_description_for_disabled_widget (4693151565003206943) -->
- <skip />
+ <string name="icon_description_for_disabled_widget" msgid="4693151565003206943">"Isithonjana se-app sewijethi evaliwe"</string>
<string name="edit_widget" msgid="9030848101135393954">"Hlela amawijethi"</string>
<string name="button_to_remove_widget" msgid="3948204829181214098">"Susa"</string>
<string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Engeza iwijethi"</string>
@@ -837,10 +836,8 @@
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Imenyu yamandla"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Ikhasi <xliff:g id="ID_1">%1$d</xliff:g> kwangu-<xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Khiya isikrini"</string>
- <!-- no translation found for finder_active (7907846989716941952) -->
- <skip />
- <!-- no translation found for shutdown_progress (5464239146561542178) -->
- <skip />
+ <string name="finder_active" msgid="7907846989716941952">"Ungabeka le foni ngokuthi Thola Ifoni Yami ngisho noma ivaliwe"</string>
+ <string name="shutdown_progress" msgid="5464239146561542178">"Iyacisha…"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Bona izinyathelo zokunakekelwa"</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Bona izinyathelo zokunakekelwa"</string>
<string name="high_temp_alarm_title" msgid="8654754369605452169">"Khipha idivayisi yakho"</string>
@@ -1226,6 +1223,12 @@
<string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Ukuze uthole ukulungiswa okuphezulu, phendula ifoni"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Idivayisi egoqekayo iyembulwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Idivayisi egoqekayo iphendulwa nxazonke"</string>
+ <!-- no translation found for quick_settings_rotation_posture_folded (2430280856312528289) -->
+ <skip />
+ <!-- no translation found for quick_settings_rotation_posture_unfolded (6372316273574167114) -->
+ <skip />
+ <!-- no translation found for rotation_tile_with_posture_secondary_label_template (7648496484163318886) -->
+ <skip />
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ibhethri elisele"</string>
<string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Xhuma i-stylus yakho kushaja"</string>
<string name="stylus_battery_low" msgid="7134370101603167096">"Ibhethri le-stylus liphansi"</string>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 71ae0d7..035cfdc 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -223,6 +223,7 @@
<item type="id" name="lock_icon" />
<item type="id" name="lock_icon_bg" />
<item type="id" name="burn_in_layer" />
+ <item type="id" name="burn_in_layer_empty_view" />
<item type="id" name="communal_tutorial_indicator" />
<item type="id" name="nssl_placeholder_barrier_bottom" />
<item type="id" name="ambient_indication_container" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5dbdd18..517f88b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -680,8 +680,10 @@
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate">activate</string>
<!-- QuickSettings: Bluetooth auto on tomorrow [CHAR LIMIT=NONE]-->
<string name="turn_on_bluetooth_auto_tomorrow">Automatically turn on again tomorrow</string>
- <!-- QuickSettings: Bluetooth auto on info text [CHAR LIMIT=NONE]-->
- <string name="turn_on_bluetooth_auto_info">Features like Quick Share, Find My Device, and device location use Bluetooth</string>
+ <!-- QuickSettings: Bluetooth auto on info text when disabled [CHAR LIMIT=NONE]-->
+ <string name="turn_on_bluetooth_auto_info_disabled">Features like Quick Share, Find My Device, and device location use Bluetooth</string>
+ <!-- QuickSettings: Bluetooth auto on info text when enabled [CHAR LIMIT=NONE]-->
+ <string name="turn_on_bluetooth_auto_info_enabled">Bluetooth will turn on tomorrow at 5 AM</string>
<!-- QuickSettings: Bluetooth secondary label for the battery level of a connected device [CHAR LIMIT=20]-->
<string name="quick_settings_bluetooth_secondary_label_battery_level"><xliff:g id="battery_level_as_percentage">%s</xliff:g> battery</string>
@@ -1538,8 +1540,16 @@
<string name="volume_stream_content_description_vibrate_a11y">%1$s. Tap to set to vibrate.</string>
<string name="volume_stream_content_description_mute_a11y">%1$s. Tap to mute.</string>
- <!-- Label for button to enabled/disable live caption [CHAR_LIMIT=30] -->
+ <!-- Label for button to enabled/disable active noise cancellation [CHAR_LIMIT=30] -->
<string name="volume_panel_noise_control_title">Noise Control</string>
+ <!-- Label for button to enabled/disable spatial audio [CHAR_LIMIT=30] -->
+ <string name="volume_panel_spatial_audio_title">Spatial Audio</string>
+ <!-- Label for button to disable spatial audio [CHAR_LIMIT=20] -->
+ <string name="volume_panel_spatial_audio_off">Off</string>
+ <!-- Label for button to enabled spatial audio [CHAR_LIMIT=20] -->
+ <string name="volume_panel_spatial_audio_fixed">Fixed</string>
+ <!-- Label for button to enabled head tracking [CHAR_LIMIT=20] -->
+ <string name="volume_panel_spatial_audio_tracking">Head Tracking</string>
<string name="volume_ringer_change">Tap to change ringer mode</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ce08ca3..4e7809a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -987,6 +987,11 @@
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowLightStatusBar">true</item>
+
+ <!--
+ TODO(b/309578419): Make activities handle insets properly and then remove this.
+ -->
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
</style>
<style name="Theme.EditWidgetsActivity"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 9421f15..c0ae4a1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -53,9 +53,6 @@
import com.android.systemui.animation.ViewHierarchyAnimator;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.shared.model.TransitionState;
-import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.plugins.clocks.ClockController;
import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.power.shared.model.ScreenPowerState;
@@ -104,7 +101,6 @@
private final Rect mClipBounds = new Rect();
private final KeyguardInteractor mKeyguardInteractor;
private final PowerInteractor mPowerInteractor;
- private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private final DozeParameters mDozeParameters;
private View mStatusArea = null;
@@ -112,7 +108,6 @@
private Boolean mSplitShadeEnabled = false;
private Boolean mStatusViewCentered = true;
- private boolean mGoneToAodTransitionRunning = false;
private DumpManager mDumpManager;
private final TransitionListenerAdapter mKeyguardStatusAlignmentTransitionListener =
@@ -181,7 +176,6 @@
KeyguardLogger logger,
InteractionJankMonitor interactionJankMonitor,
KeyguardInteractor keyguardInteractor,
- KeyguardTransitionInteractor keyguardTransitionInteractor,
DumpManager dumpManager,
PowerInteractor powerInteractor) {
super(keyguardStatusView);
@@ -197,7 +191,6 @@
mDumpManager = dumpManager;
mKeyguardInteractor = keyguardInteractor;
mPowerInteractor = powerInteractor;
- mKeyguardTransitionInteractor = keyguardTransitionInteractor;
}
@Override
@@ -232,6 +225,7 @@
mDumpManager.registerDumpable(getInstanceName(), this);
if (migrateClocksToBlueprint()) {
startCoroutines(EmptyCoroutineContext.INSTANCE);
+ mView.setVisibility(View.GONE);
}
}
@@ -247,15 +241,6 @@
dozeTimeTick();
}
}, context);
-
- collectFlow(mView, mKeyguardTransitionInteractor.getGoneToAodTransition(),
- (TransitionStep step) -> {
- if (step.getTransitionState() == TransitionState.RUNNING) {
- mGoneToAodTransitionRunning = true;
- } else {
- mGoneToAodTransitionRunning = false;
- }
- }, context);
}
public KeyguardStatusView getView() {
@@ -326,7 +311,7 @@
* Set keyguard status view alpha.
*/
public void setAlpha(float alpha) {
- if (!mKeyguardVisibilityHelper.isVisibilityAnimating() && !mGoneToAodTransitionRunning) {
+ if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
mView.setAlpha(alpha);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 2000028..f5a6cb3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -88,6 +88,10 @@
boolean keyguardFadingAway,
boolean goingToFullShade,
int oldStatusBarState) {
+ if (migrateClocksToBlueprint()) {
+ log("Ignoring KeyguardVisibilityelper, migrateClocksToBlueprint flag on");
+ return;
+ }
Assert.isMainThread();
PropertyAnimator.cancelAnimation(mView, AnimatableProperty.ALPHA);
boolean isOccluded = mKeyguardStateController.isOccluded();
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java
index 6299739..577bbc0 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java
@@ -22,6 +22,8 @@
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.graphics.PointF;
import android.graphics.Rect;
@@ -435,7 +437,14 @@
}
mMenuAnimationController.flingMenuThenSpringToEdge(
getMenuPosition().x, 100f, 0f);
- mContext.startActivity(getIntentForEditScreen());
+
+ Intent intent = getIntentForEditScreen();
+ PackageManager packageManager = getContext().getPackageManager();
+ List<ResolveInfo> activities = packageManager.queryIntentActivities(intent,
+ PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY));
+ if (!activities.isEmpty()) {
+ mContext.startActivity(intent);
+ }
}
void incrementTexMetricForAllTargets(String metric) {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt
index c64f666..12576d4 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt
@@ -152,4 +152,6 @@
}
fun isWidgetContent() = this is WidgetContent
+
+ fun isSmartspace() = this is Smartspace
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index fc9a7df..35b27aa 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -21,6 +21,7 @@
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.Logger
import com.android.systemui.log.dagger.CommunalLog
@@ -46,6 +47,7 @@
import kotlinx.coroutines.launch
/** The default view model used for showing the communal hub. */
+@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class CommunalViewModel
@Inject
@@ -54,6 +56,7 @@
private val communalInteractor: CommunalInteractor,
tutorialInteractor: CommunalTutorialInteractor,
shadeInteractor: ShadeInteractor,
+ deviceEntryInteractor: DeviceEntryInteractor,
@Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost,
@CommunalLog logBuffer: LogBuffer,
) : BaseCommunalViewModel(communalInteractor, mediaHost) {
@@ -87,6 +90,8 @@
/** Whether touches should be disabled in communal */
val touchesAllowed: Flow<Boolean> = not(shadeInteractor.isAnyFullyExpanded)
+ val deviceUnlocked: Flow<Boolean> = deviceEntryInteractor.isUnlocked
+
init {
// Initialize our media host for the UMO. This only needs to happen once and must be done
// before the MediaHierarchyManager attempts to move the UMO to the hub.
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/HomeControlsDreamService.kt b/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/HomeControlsDreamService.kt
index e74814a..376d312 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/HomeControlsDreamService.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/HomeControlsDreamService.kt
@@ -17,6 +17,7 @@
package com.android.systemui.dreams.homecontrols
import android.content.Intent
+import android.os.PowerManager
import android.service.controls.ControlsProviderService
import android.service.dreams.DreamService
import android.window.TaskFragmentInfo
@@ -27,6 +28,8 @@
import com.android.systemui.dreams.homecontrols.domain.interactor.HomeControlsComponentInteractor.Companion.MAX_UPDATE_CORRELATION_DELAY
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.dagger.DreamLog
+import com.android.systemui.util.wakelock.WakeLock
+import com.android.systemui.util.wakelock.WakeLock.Builder.NO_TIMEOUT
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineDispatcher
@@ -42,14 +45,23 @@
private val controlsSettingsRepository: ControlsSettingsRepository,
private val taskFragmentFactory: TaskFragmentComponent.Factory,
private val homeControlsComponentInteractor: HomeControlsComponentInteractor,
+ private val wakeLockBuilder: WakeLock.Builder,
private val dreamActivityProvider: DreamActivityProvider,
@Background private val bgDispatcher: CoroutineDispatcher,
@DreamLog logBuffer: LogBuffer
) : DreamService() {
+
private val serviceJob = SupervisorJob()
private val serviceScope = CoroutineScope(bgDispatcher + serviceJob)
- private val logger = DreamLogger(logBuffer, "HomeControlsDreamService")
+ private val logger = DreamLogger(logBuffer, TAG)
private lateinit var taskFragmentComponent: TaskFragmentComponent
+ private val wakeLock: WakeLock by lazy {
+ wakeLockBuilder
+ .setMaxTimeout(NO_TIMEOUT)
+ .setTag(TAG)
+ .setLevelsAndFlags(PowerManager.SCREEN_BRIGHT_WAKE_LOCK)
+ .build()
+ }
override fun onAttachedToWindow() {
super.onAttachedToWindow()
@@ -72,6 +84,8 @@
hide = { finish() }
)
.apply { createTaskFragment() }
+
+ wakeLock.acquire(TAG)
}
private fun onTaskFragmentInfoChanged(taskFragmentInfo: TaskFragmentInfo) {
@@ -100,6 +114,7 @@
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
+ wakeLock.release(TAG)
taskFragmentComponent.destroy()
serviceScope.launch {
delay(CANCELLATION_DELAY_AFTER_DETACHED)
@@ -115,5 +130,6 @@
* complete.
*/
val CANCELLATION_DELAY_AFTER_DETACHED = 5.seconds
+ const val TAG = "HomeControlsDreamService"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 3a6423d..1298fa5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -24,7 +24,6 @@
import com.android.systemui.biometrics.data.repository.FacePropertyRepository
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
-import com.android.systemui.common.shared.model.Position
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
@@ -80,12 +79,6 @@
val keyguardAlpha: StateFlow<Float>
/**
- * Observable of the relative offset of the lock-screen clock from its natural position on the
- * screen.
- */
- val clockPosition: StateFlow<Position>
-
- /**
* Observable for whether the keyguard is showing.
*
* Note: this is also `true` when the lock-screen is occluded with an `Activity` "above" it in
@@ -241,11 +234,6 @@
fun setKeyguardAlpha(alpha: Float)
/**
- * Sets the relative offset of the lock-screen clock from its natural position on the screen.
- */
- fun setClockPosition(x: Int, y: Int)
-
- /**
* Returns whether the keyguard bottom area should be constrained to the top of the lock icon
*/
fun isUdfpsSupported(): Boolean
@@ -324,9 +312,6 @@
private val _keyguardAlpha = MutableStateFlow(1f)
override val keyguardAlpha = _keyguardAlpha.asStateFlow()
- private val _clockPosition = MutableStateFlow(Position(0, 0))
- override val clockPosition = _clockPosition.asStateFlow()
-
private val _clockShouldBeCentered = MutableStateFlow(true)
override val clockShouldBeCentered: Flow<Boolean> = _clockShouldBeCentered.asStateFlow()
@@ -678,10 +663,6 @@
_keyguardAlpha.value = alpha
}
- override fun setClockPosition(x: Int, y: Int) {
- _clockPosition.value = Position(x, y)
- }
-
override fun isUdfpsSupported(): Boolean = keyguardUpdateMonitor.isUdfpsSupported
override fun setQuickSettingsVisible(isVisible: Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractor.kt
index 7ae70a9..ca86289 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractor.kt
@@ -19,7 +19,7 @@
import android.content.Context
import androidx.annotation.DimenRes
-import com.android.systemui.common.ui.data.repository.ConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.doze.util.BurnInHelperWrapper
@@ -47,13 +47,15 @@
private val context: Context,
private val burnInHelperWrapper: BurnInHelperWrapper,
@Application private val scope: CoroutineScope,
- private val configurationRepository: ConfigurationRepository,
+ private val configurationInteractor: ConfigurationInteractor,
private val keyguardInteractor: KeyguardInteractor,
) {
val deviceEntryIconXOffset: StateFlow<Int> =
burnInOffsetDefinedInPixels(R.dimen.udfps_burn_in_offset_x, isXAxis = true)
+ .stateIn(scope, SharingStarted.WhileSubscribed(), 0)
val deviceEntryIconYOffset: StateFlow<Int> =
burnInOffsetDefinedInPixels(R.dimen.udfps_burn_in_offset_y, isXAxis = false)
+ .stateIn(scope, SharingStarted.WhileSubscribed(), 0)
val udfpsProgress: StateFlow<Float> =
keyguardInteractor.dozeTimeTick
.mapLatest { burnInHelperWrapper.burnInProgressOffset() }
@@ -63,18 +65,18 @@
burnInHelperWrapper.burnInProgressOffset()
)
- val keyguardBurnIn: Flow<BurnInModel> =
- combine(
- burnInOffset(R.dimen.burn_in_prevention_offset_x, isXAxis = true),
- burnInOffset(R.dimen.burn_in_prevention_offset_y, isXAxis = false).map {
- it * 2 -
- context.resources.getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y)
+ /** Given the max x,y dimens, determine the current translation shifts. */
+ fun burnIn(xDimenResourceId: Int, yDimenResourceId: Int): Flow<BurnInModel> {
+ return combine(
+ burnInOffset(xDimenResourceId, isXAxis = true),
+ burnInOffset(yDimenResourceId, isXAxis = false).map {
+ it * 2 - context.resources.getDimensionPixelSize(yDimenResourceId)
}
) { translationX, translationY ->
BurnInModel(translationX, translationY, burnInHelperWrapper.burnInScale())
}
.distinctUntilChanged()
- .stateIn(scope, SharingStarted.Lazily, BurnInModel())
+ }
/**
* Use for max burn-in offsets that are NOT specified in pixels. This flow will recalculate the
@@ -84,23 +86,14 @@
private fun burnInOffset(
@DimenRes maxBurnInOffsetResourceId: Int,
isXAxis: Boolean,
- ): StateFlow<Int> {
- return configurationRepository.onAnyConfigurationChange
- .flatMapLatest {
- val maxBurnInOffsetPixels =
- context.resources.getDimensionPixelSize(maxBurnInOffsetResourceId)
- keyguardInteractor.dozeTimeTick.mapLatest {
- calculateOffset(maxBurnInOffsetPixels, isXAxis)
- }
+ ): Flow<Int> {
+ return configurationInteractor.onAnyConfigurationChange.flatMapLatest {
+ val maxBurnInOffsetPixels =
+ context.resources.getDimensionPixelSize(maxBurnInOffsetResourceId)
+ keyguardInteractor.dozeTimeTick.mapLatest {
+ calculateOffset(maxBurnInOffsetPixels, isXAxis)
}
- .stateIn(
- scope,
- SharingStarted.Lazily,
- calculateOffset(
- context.resources.getDimensionPixelSize(maxBurnInOffsetResourceId),
- isXAxis,
- )
- )
+ }
}
/**
@@ -111,24 +104,14 @@
private fun burnInOffsetDefinedInPixels(
@DimenRes maxBurnInOffsetResourceId: Int,
isXAxis: Boolean,
- ): StateFlow<Int> {
- return configurationRepository.scaleForResolution
- .flatMapLatest { scale ->
- val maxBurnInOffsetPixels =
- context.resources.getDimensionPixelSize(maxBurnInOffsetResourceId)
- keyguardInteractor.dozeTimeTick.mapLatest {
- calculateOffset(maxBurnInOffsetPixels, isXAxis, scale)
- }
+ ): Flow<Int> {
+ return configurationInteractor.scaleForResolution.flatMapLatest { scale ->
+ val maxBurnInOffsetPixels =
+ context.resources.getDimensionPixelSize(maxBurnInOffsetResourceId)
+ keyguardInteractor.dozeTimeTick.mapLatest {
+ calculateOffset(maxBurnInOffsetPixels, isXAxis, scale)
}
- .stateIn(
- scope,
- SharingStarted.WhileSubscribed(),
- calculateOffset(
- context.resources.getDimensionPixelSize(maxBurnInOffsetResourceId),
- isXAxis,
- configurationRepository.getResolutionScale(),
- )
- )
+ }
}
private fun calculateOffset(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBottomAreaInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBottomAreaInteractor.kt
index d2a7486..b9ec58c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBottomAreaInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBottomAreaInteractor.kt
@@ -22,6 +22,8 @@
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
/** Encapsulates business-logic specifically related to the keyguard bottom area. */
@SysUISingleton
@@ -35,10 +37,13 @@
/** The amount of alpha for the UI components of the bottom area. */
val alpha: Flow<Float> = repository.bottomAreaAlpha
/** The position of the keyguard clock. */
- val clockPosition: Flow<Position> = repository.clockPosition
+ private val _clockPosition = MutableStateFlow(Position(0, 0))
+ /** See [ClockSection] */
+ @Deprecated("with migrateClocksToBlueprint()")
+ val clockPosition: Flow<Position> = _clockPosition.asStateFlow()
fun setClockPosition(x: Int, y: Int) {
- repository.setClockPosition(x, y)
+ _clockPosition.value = Position(x, y)
}
fun setAlpha(alpha: Float) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index f321bd7..143edf9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -27,7 +27,6 @@
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.common.shared.model.NotificationContainerBounds
-import com.android.systemui.common.shared.model.Position
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardRepository
@@ -37,6 +36,7 @@
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
+import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -235,9 +235,6 @@
/** The approximate location on the screen of the face unlock sensor, if one is available. */
val faceSensorLocation: Flow<Point?> = repository.faceSensorLocation
- /** The position of the keyguard clock. */
- val clockPosition: Flow<Position> = repository.clockPosition
-
@Deprecated("Use the relevant TransitionViewModel")
val keyguardAlpha: Flow<Float> = repository.keyguardAlpha
@@ -272,8 +269,11 @@
configurationInteractor
.dimensionPixelSize(R.dimen.keyguard_translate_distance_on_swipe_up)
.flatMapLatest { translationDistance ->
- shadeRepository.legacyShadeExpansion.map {
- if (it == 0f) {
+ combine(
+ shadeRepository.legacyShadeExpansion.onStart { emit(0f) },
+ keyguardTransitionInteractor.transitionValue(GONE).onStart { emit(0f) },
+ ) { legacyShadeExpansion, goneValue ->
+ if (goneValue == 1f || legacyShadeExpansion == 0f) {
// Reset the translation value
0f
} else {
@@ -281,11 +281,12 @@
MathUtils.lerp(
translationDistance,
0,
- Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(it)
+ Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(legacyShadeExpansion)
)
}
}
}
+ .distinctUntilChanged()
val clockShouldBeCentered: Flow<Boolean> = repository.clockShouldBeCentered
@@ -345,10 +346,6 @@
repository.setQuickSettingsVisible(isVisible)
}
- fun setClockPosition(x: Int, y: Int) {
- repository.setClockPosition(x, y)
- }
-
fun setAlpha(alpha: Float) {
repository.setKeyguardAlpha(alpha)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index dc1f33d..fc95ec9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -73,7 +73,6 @@
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
@@ -148,6 +147,7 @@
viewModel.alpha(viewState).collect { alpha ->
view.alpha = alpha
childViews[statusViewId]?.alpha = alpha
+ childViews[burnInLayerId]?.alpha = alpha
}
}
}
@@ -195,66 +195,68 @@
// large clock isn't added to burnInLayer due to its scale transition
// so we also need to add translation to it here
// same as translationX
- burnInParams
- .flatMapLatest { params -> viewModel.translationY(params) }
- .collect { y ->
- childViews[burnInLayerId]?.translationY = y
- childViews[largeClockId]?.translationY = y
- childViews[aodNotificationIconContainerId]?.translationY = y
- }
+ viewModel.translationY.collect { y ->
+ childViews[burnInLayerId]?.translationY = y
+ childViews[largeClockId]?.translationY = y
+ childViews[aodNotificationIconContainerId]?.translationY = y
+ }
}
launch {
- burnInParams
- .flatMapLatest { params -> viewModel.translationX(params) }
- .collect { state ->
- val px = state.value ?: return@collect
- when {
- state.isToOrFrom(KeyguardState.AOD) -> {
- childViews[largeClockId]?.translationX = px
- childViews[burnInLayerId]?.translationX = px
- childViews[aodNotificationIconContainerId]
- ?.translationX = px
- }
- state.isToOrFrom(KeyguardState.GLANCEABLE_HUB) -> {
- for ((key, childView) in childViews.entries) {
- when (key) {
- indicationArea,
- startButton,
- endButton,
- lockIcon -> {
- // Do not move these views
- }
- else -> childView.translationX = px
+ viewModel.translationX.collect { state ->
+ val px = state.value ?: return@collect
+ when {
+ state.isToOrFrom(KeyguardState.AOD) -> {
+ childViews[largeClockId]?.translationX = px
+ childViews[burnInLayerId]?.translationX = px
+ childViews[aodNotificationIconContainerId]?.translationX =
+ px
+ }
+ state.isToOrFrom(KeyguardState.GLANCEABLE_HUB) -> {
+ for ((key, childView) in childViews.entries) {
+ when (key) {
+ indicationArea,
+ startButton,
+ endButton,
+ lockIcon -> {
+ // Do not move these views
}
+ else -> childView.translationX = px
}
}
}
}
+ }
}
launch {
- burnInParams
- .flatMapLatest { params -> viewModel.scale(params) }
- .collect { scaleViewModel ->
- if (scaleViewModel.scaleClockOnly) {
- // For clocks except weather clock, we have scale transition
- // besides translate
- childViews[largeClockId]?.let {
- it.scaleX = scaleViewModel.scale
- it.scaleY = scaleViewModel.scale
- }
- } else {
- // For weather clock, large clock should have only scale
- // transition with other parts in burnInLayer
- childViews[burnInLayerId]?.scaleX = scaleViewModel.scale
- childViews[burnInLayerId]?.scaleY = scaleViewModel.scale
- childViews[aodNotificationIconContainerId]?.scaleX =
- scaleViewModel.scale
- childViews[aodNotificationIconContainerId]?.scaleY =
- scaleViewModel.scale
+ viewModel.scale.collect { scaleViewModel ->
+ if (scaleViewModel.scaleClockOnly) {
+ // For clocks except weather clock, we have scale transition
+ // besides translate
+ childViews[largeClockId]?.let {
+ it.scaleX = scaleViewModel.scale
+ it.scaleY = scaleViewModel.scale
}
+ // Make sure to reset these views, or they will be invisible
+ if (childViews[burnInLayerId]?.scaleX != 1f) {
+ childViews[burnInLayerId]?.scaleX = 1f
+ childViews[burnInLayerId]?.scaleY = 1f
+ childViews[aodNotificationIconContainerId]?.scaleX = 1f
+ childViews[aodNotificationIconContainerId]?.scaleY = 1f
+ view.requestLayout()
+ }
+ } else {
+ // For weather clock, large clock should have only scale
+ // transition with other parts in burnInLayer
+ childViews[burnInLayerId]?.scaleX = scaleViewModel.scale
+ childViews[burnInLayerId]?.scaleY = scaleViewModel.scale
+ childViews[aodNotificationIconContainerId]?.scaleX =
+ scaleViewModel.scale
+ childViews[aodNotificationIconContainerId]?.scaleY =
+ scaleViewModel.scale
}
+ }
}
if (NotificationIconContainerRefactor.isEnabled) {
@@ -311,6 +313,8 @@
}
}
+ launch { burnInParams.collect { viewModel.updateBurnInParams(it) } }
+
if (deviceEntryHapticsInteractor != null && vibratorHelper != null) {
launch {
deviceEntryHapticsInteractor.playSuccessHaptic.collect {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
index 98bebd0..88ce9dc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
@@ -21,6 +21,8 @@
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
+import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
+import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.view.KeyguardRootView
@@ -37,24 +39,24 @@
private val clockViewModel: KeyguardClockViewModel,
) : KeyguardSection() {
private lateinit var burnInLayer: AodBurnInLayer
+ // The burn-in layer requires at least 1 view at all times
+ private val emptyView: View by lazy {
+ View(context, null).apply {
+ id = R.id.burn_in_layer_empty_view
+ visibility = View.GONE
+ }
+ }
override fun addViews(constraintLayout: ConstraintLayout) {
if (!migrateClocksToBlueprint()) {
return
}
- // The burn-in layer requires at least 1 view at all times
- val emptyView = View(context, null).apply { id = View.generateViewId() }
constraintLayout.addView(emptyView)
burnInLayer =
AodBurnInLayer(context).apply {
id = R.id.burn_in_layer
registerListener(rootView)
addView(emptyView)
- if (!migrateClocksToBlueprint()) {
- val statusView =
- constraintLayout.requireViewById<View>(R.id.keyguard_status_view)
- addView(statusView)
- }
}
constraintLayout.addView(burnInLayer)
}
@@ -70,6 +72,13 @@
if (!migrateClocksToBlueprint()) {
return
}
+
+ constraintSet.apply {
+ // The empty view should not occupy any space
+ constrainHeight(R.id.burn_in_layer_empty_view, 1)
+ constrainWidth(R.id.burn_in_layer_empty_view, 0)
+ connect(R.id.burn_in_layer_empty_view, BOTTOM, PARENT_ID, BOTTOM)
+ }
}
override fun removeViews(constraintLayout: ConstraintLayout) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModel.kt
index 9edb4d1..bbe5fed 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModel.kt
@@ -23,13 +23,19 @@
import com.android.systemui.deviceentry.shared.model.FaceTimeoutMessage
import com.android.systemui.deviceentry.shared.model.FingerprintLockoutMessage
import com.android.systemui.deviceentry.shared.model.FingerprintMessage
+import com.android.systemui.statusbar.KeyguardIndicationController.DEFAULT_MESSAGE_TIME
+import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onStart
/** View model for the alternate bouncer message area. */
@ExperimentalCoroutinesApi
@@ -38,19 +44,32 @@
constructor(
biometricMessageInteractor: BiometricMessageInteractor,
alternateBouncerInteractor: AlternateBouncerInteractor,
+ systemClock: com.android.systemui.util.time.SystemClock,
) {
-
- private val faceMessage: Flow<FaceMessage> =
- biometricMessageInteractor.faceMessage.filterNot { it is FaceTimeoutMessage }
+ private val fingerprintMessageWithTimestamp: Flow<Pair<FingerprintMessage?, Long>> =
+ biometricMessageInteractor.fingerprintMessage
+ .filterNot { it is FingerprintLockoutMessage }
+ .map { Pair(it, systemClock.uptimeMillis()) }
+ .filterIsInstance<Pair<FingerprintMessage?, Long>>()
+ .onStart { emit(Pair(null, -3500L)) }
private val fingerprintMessage: Flow<FingerprintMessage> =
- biometricMessageInteractor.fingerprintMessage.filterNot { it is FingerprintLockoutMessage }
+ fingerprintMessageWithTimestamp.filter { it.first != null }.map { it.first!! }
+ private val faceMessage: Flow<FaceMessage> =
+ biometricMessageInteractor.faceMessage
+ .filterNot { it is FaceTimeoutMessage }
+ // Don't show face messages if within the default message time for fp messages to show
+ .sample(fingerprintMessageWithTimestamp, ::Pair)
+ .filter { (_, fpMessage) ->
+ (systemClock.uptimeMillis() - fpMessage.second) >= DEFAULT_MESSAGE_TIME
+ }
+ .map { (faceMsg, _) -> faceMsg }
val message: Flow<BiometricMessage?> =
alternateBouncerInteractor.isVisible.flatMapLatest { isVisible ->
if (isVisible) {
merge(
- faceMessage,
fingerprintMessage,
+ faceMessage,
)
} else {
flowOf(null)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
index 7be390a..f961e08 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.util.Log
import android.util.MathUtils
import com.android.app.animation.Interpolators
import com.android.keyguard.KeyguardClockSwitch
@@ -62,23 +63,26 @@
private val occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel,
private val keyguardClockViewModel: KeyguardClockViewModel,
) {
- /** Horizontal translation for elements that need to apply anti-burn-in tactics. */
- fun translationX(
- params: BurnInParameters,
- ): Flow<Float> {
- return burnIn(params).map { it.translationX.toFloat() }
- }
+ private val TAG = "AodBurnInViewModel"
- /** Vertical translation for elements that need to apply anti-burn-in tactics. */
- fun translationY(
- params: BurnInParameters,
- ): Flow<Float> {
+ /** All burn-in movement: x,y,scale, to shift items and prevent burn-in */
+ fun movement(
+ burnInParams: BurnInParameters,
+ ): Flow<BurnInModel> {
+ val params =
+ if (burnInParams.minViewY < burnInParams.topInset) {
+ // minViewY should never be below the inset. Correct it if needed
+ Log.w(TAG, "minViewY is below topInset: $burnInParams")
+ burnInParams.copy(minViewY = burnInParams.topInset)
+ } else {
+ burnInParams
+ }
return configurationInteractor
.dimensionPixelSize(R.dimen.keyguard_enter_from_top_translation_y)
.flatMapLatest { enterFromTopAmount ->
combine(
keyguardInteractor.keyguardTranslationY.onStart { emit(0f) },
- burnIn(params).map { it.translationY.toFloat() }.onStart { emit(0f) },
+ burnIn(params).onStart { emit(BurnInModel()) },
goneToAodTransitionViewModel
.enterFromTopTranslationY(enterFromTopAmount)
.onStart { emit(StateToValue()) },
@@ -88,32 +92,26 @@
aodToLockscreenTransitionViewModel.translationY(params.translationY).onStart {
emit(StateToValue())
},
- ) { keyguardTranslationY, burnInY, goneToAod, occludedToLockscreen, aodToLockscreen
- ->
- if (isInTransition(aodToLockscreen.transitionState)) {
- aodToLockscreen.value ?: 0f
- } else if (isInTransition(goneToAod.transitionState)) {
- (goneToAod.value ?: 0f) + burnInY
- } else {
- burnInY + occludedToLockscreen + keyguardTranslationY
- }
+ ) {
+ keyguardTranslationY,
+ burnInModel,
+ goneToAod,
+ occludedToLockscreen,
+ aodToLockscreen ->
+ val translationY =
+ if (isInTransition(aodToLockscreen.transitionState)) {
+ aodToLockscreen.value ?: 0f
+ } else if (isInTransition(goneToAod.transitionState)) {
+ (goneToAod.value ?: 0f) + burnInModel.translationY
+ } else {
+ burnInModel.translationY + occludedToLockscreen + keyguardTranslationY
+ }
+ burnInModel.copy(translationY = translationY.toInt())
}
}
.distinctUntilChanged()
}
- /** Scale for elements that need to apply anti-burn-in tactics. */
- fun scale(
- params: BurnInParameters,
- ): Flow<BurnInScaleViewModel> {
- return burnIn(params).map {
- BurnInScaleViewModel(
- scale = it.scale,
- scaleClockOnly = it.scaleClockOnly,
- )
- }
- }
-
private fun isInTransition(state: TransitionState): Boolean {
return state == STARTED || state == RUNNING
}
@@ -125,7 +123,10 @@
keyguardTransitionInteractor.dozeAmountTransition.map {
Interpolators.FAST_OUT_SLOW_IN.getInterpolation(it.value)
},
- burnInInteractor.keyguardBurnIn,
+ burnInInteractor.burnIn(
+ xDimenResourceId = R.dimen.burn_in_prevention_offset_x,
+ yDimenResourceId = R.dimen.burn_in_prevention_offset_y
+ ),
) { interpolated, burnIn ->
val useScaleOnly =
(clockController(params.clockControllerProvider)
@@ -149,7 +150,6 @@
} else {
max(params.topInset, params.minViewY + burnInY) - params.minViewY
}
-
BurnInModel(
translationX = MathUtils.lerp(0, burnIn.translationX, interpolated).toInt(),
translationY = translationY,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
index 6458eda..e35e065 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
@@ -17,10 +17,14 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.Flags.keyguardBottomAreaRefactor
+import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.doze.util.BurnInHelperWrapper
+import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.shared.model.BurnInModel
+import com.android.systemui.res.R
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -32,9 +36,10 @@
@Inject
constructor(
private val keyguardInteractor: KeyguardInteractor,
- bottomAreaInteractor: KeyguardBottomAreaInteractor,
+ private val bottomAreaInteractor: KeyguardBottomAreaInteractor,
keyguardBottomAreaViewModel: KeyguardBottomAreaViewModel,
private val burnInHelperWrapper: BurnInHelperWrapper,
+ private val burnInInteractor: BurnInInteractor,
private val shortcutsCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel,
configurationInteractor: ConfigurationInteractor,
) {
@@ -63,24 +68,37 @@
}
.distinctUntilChanged()
}
+
+ private val burnIn: Flow<BurnInModel> =
+ burnInInteractor
+ .burnIn(
+ xDimenResourceId = R.dimen.burn_in_prevention_offset_x,
+ yDimenResourceId = R.dimen.default_burn_in_prevention_offset,
+ )
+ .distinctUntilChanged()
+
/** An observable for the x-offset by which the indication area should be translated. */
val indicationAreaTranslationX: Flow<Float> =
- if (keyguardBottomAreaRefactor()) {
- keyguardInteractor.clockPosition.map { it.x.toFloat() }.distinctUntilChanged()
+ if (migrateClocksToBlueprint() || keyguardBottomAreaRefactor()) {
+ burnIn.map { it.translationX.toFloat() }
} else {
bottomAreaInteractor.clockPosition.map { it.x.toFloat() }.distinctUntilChanged()
}
/** Returns an observable for the y-offset by which the indication area should be translated. */
fun indicationAreaTranslationY(defaultBurnInOffset: Int): Flow<Float> {
- return keyguardInteractor.dozeAmount
- .map { dozeAmount ->
- dozeAmount *
- (burnInHelperWrapper.burnInOffset(
- /* amplitude = */ defaultBurnInOffset * 2,
- /* xAxis= */ false,
- ) - defaultBurnInOffset)
- }
- .distinctUntilChanged()
+ return if (migrateClocksToBlueprint()) {
+ burnIn.map { it.translationY.toFloat() }
+ } else {
+ keyguardInteractor.dozeAmount
+ .map { dozeAmount ->
+ dozeAmount *
+ (burnInHelperWrapper.burnInOffset(
+ /* amplitude = */ defaultBurnInOffset * 2,
+ /* xAxis= */ false,
+ ) - defaultBurnInOffset)
+ }
+ .distinctUntilChanged()
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index f848717..5ca9215 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -24,9 +24,11 @@
import com.android.systemui.common.shared.model.NotificationContainerBounds
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.BurnInModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
@@ -47,8 +49,11 @@
import com.android.systemui.util.ui.zip
import javax.inject.Inject
import kotlin.math.max
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -57,12 +62,14 @@
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.launch
@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class KeyguardRootViewModel
@Inject
constructor(
+ @Application private val scope: CoroutineScope,
private val deviceEntryInteractor: DeviceEntryInteractor,
private val dozeParameters: DozeParameters,
private val keyguardInteractor: KeyguardInteractor,
@@ -102,6 +109,8 @@
private val aodAlphaViewModel: AodAlphaViewModel,
private val shadeInteractor: ShadeInteractor,
) {
+ private var burnInJob: Job? = null
+ private val burnInModel = MutableStateFlow(BurnInModel())
val burnInLayerVisibility: Flow<Int> =
keyguardTransitionInteractor.startedKeyguardState
@@ -213,21 +222,33 @@
/** For elements that appear and move during the animation -> AOD */
val burnInLayerAlpha: Flow<Float> = aodAlphaViewModel.alpha
- fun translationY(params: BurnInParameters): Flow<Float> {
- return aodBurnInViewModel.translationY(params)
- }
+ val translationY: Flow<Float> = burnInModel.map { it.translationY.toFloat() }
- fun translationX(params: BurnInParameters): Flow<StateToValue> {
- return merge(
- aodBurnInViewModel.translationX(params).map { StateToValue(to = AOD, value = it) },
+ val translationX: Flow<StateToValue> =
+ merge(
+ burnInModel.map { StateToValue(to = AOD, value = it.translationX.toFloat()) },
lockscreenToGlanceableHubTransitionViewModel.keyguardTranslationX,
glanceableHubToLockscreenTransitionViewModel.keyguardTranslationX,
)
+
+ fun updateBurnInParams(params: BurnInParameters) {
+ burnInJob?.cancel()
+
+ burnInJob =
+ scope.launch {
+ aodBurnInViewModel.movement(params).collect {
+ burnInModel.value = it
+ }
+ }
}
- fun scale(params: BurnInParameters): Flow<BurnInScaleViewModel> {
- return aodBurnInViewModel.scale(params)
- }
+ val scale: Flow<BurnInScaleViewModel> =
+ burnInModel.map {
+ BurnInScaleViewModel(
+ scale = it.scale,
+ scaleClockOnly = it.scaleClockOnly,
+ )
+ }
/** Is the notification icon container visible? */
val isNotifIconContainerVisible: Flow<AnimatedValue<Boolean>> =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt
index 7ece6e0..9d53703 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogDelegate.kt
@@ -32,6 +32,7 @@
import android.widget.ProgressBar
import android.widget.Switch
import android.widget.TextView
+import androidx.annotation.StringRes
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
@@ -204,12 +205,17 @@
getAutoOnToggleView(dialog).visibility = uiProperties.autoOnToggleVisibility
}
- internal fun onBluetoothAutoOnUpdated(dialog: SystemUIDialog, isEnabled: Boolean) {
+ internal fun onBluetoothAutoOnUpdated(
+ dialog: SystemUIDialog,
+ isEnabled: Boolean,
+ @StringRes infoResId: Int
+ ) {
getAutoOnToggle(dialog).apply {
isChecked = isEnabled
setEnabled(true)
alpha = ENABLED_ALPHA
}
+ getAutoOnToggleInfoTextView(dialog).text = context.getString(infoResId)
}
private fun setupToggle(dialog: SystemUIDialog) {
@@ -264,6 +270,10 @@
return dialog.requireViewById(R.id.bluetooth_auto_on_toggle_layout)
}
+ private fun getAutoOnToggleInfoTextView(dialog: SystemUIDialog): TextView {
+ return dialog.requireViewById(R.id.bluetooth_auto_on_toggle_info_text)
+ }
+
private fun getProgressBarAnimation(dialog: SystemUIDialog): ProgressBar {
return dialog.requireViewById(R.id.bluetooth_tile_dialog_progress_animation)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
index 0486207..e4f3c19 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
@@ -191,7 +191,14 @@
// bluetoothAutoOnUpdate is emitted when bluetooth auto on on/off state is
// changed.
bluetoothAutoOnInteractor.isEnabled
- .onEach { dialogDelegate.onBluetoothAutoOnUpdated(dialog, it) }
+ .onEach {
+ dialogDelegate.onBluetoothAutoOnUpdated(
+ dialog,
+ it,
+ if (it) R.string.turn_on_bluetooth_auto_info_enabled
+ else R.string.turn_on_bluetooth_auto_info_disabled
+ )
+ }
.launchIn(this)
// bluetoothAutoOnToggle is emitted when user toggles the bluetooth auto on
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
index b42cc98..c4287ca 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
@@ -21,7 +21,9 @@
import android.annotation.IntRange;
import android.content.ContentProvider;
import android.content.ContentResolver;
+import android.content.ContentUris;
import android.content.ContentValues;
+import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.net.Uri;
@@ -50,6 +52,7 @@
import java.io.OutputStream;
import java.time.Duration;
import java.time.Instant;
+import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
@@ -145,32 +148,84 @@
}
/**
- * Export the image using the given executor.
+ * Export the image using the given executor with an auto-generated file name based on display
+ * id.
*
- * @param executor the thread for execution
- * @param bitmap the bitmap to export
+ * @param executor the thread for execution
+ * @param bitmap the bitmap to export
* @param displayId the display id the bitmap comes from.
* @return a listenable future result
*/
public ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap,
UserHandle owner, int displayId) {
- return export(executor, requestId, bitmap, ZonedDateTime.now(), owner, displayId);
+ ZonedDateTime captureTime = ZonedDateTime.now(ZoneId.systemDefault());
+ return export(executor,
+ new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat,
+ mQuality, /* publish */ true, owner, mFlags,
+ createFilename(captureTime, mCompressFormat, displayId)));
+ }
+
+ /**
+ * Export the image using the given executor with a specified file name.
+ *
+ * @param executor the thread for execution
+ * @param bitmap the bitmap to export
+ * @param format the compress format of {@code bitmap} e.g. {@link CompressFormat.PNG}
+ * @param fileName a specified name for the exported file. No need to include file extension in
+ * file name. The extension will be internally appended based on
+ * {@code format}
+ * @return a listenable future result
+ */
+ public ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap,
+ CompressFormat format, UserHandle owner, String fileName) {
+ return export(executor,
+ new Task(mResolver,
+ requestId,
+ bitmap,
+ ZonedDateTime.now(ZoneId.systemDefault()),
+ format,
+ mQuality, /* publish */ true, owner, mFlags,
+ createSystemFileDisplayName(fileName, format),
+ true /* allowOverwrite */));
}
/**
* Export the image to MediaStore and publish.
*
* @param executor the thread for execution
- * @param bitmap the bitmap to export
- *
+ * @param bitmap the bitmap to export
* @return a listenable future result
*/
ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap,
ZonedDateTime captureTime, UserHandle owner, int displayId) {
+ return export(executor, new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat,
+ mQuality, /* publish */ true, owner, mFlags,
+ createFilename(captureTime, mCompressFormat, displayId)));
+ }
- final Task task = new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat,
- mQuality, /* publish */ true, owner, mFlags, displayId);
+ /**
+ * Export the image to MediaStore and publish.
+ *
+ * @param executor the thread for execution
+ * @param bitmap the bitmap to export
+ * @return a listenable future result
+ */
+ ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap,
+ ZonedDateTime captureTime, UserHandle owner, String fileName) {
+ return export(executor, new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat,
+ mQuality, /* publish */ true, owner, mFlags,
+ createSystemFileDisplayName(fileName, mCompressFormat)));
+ }
+ /**
+ * Export the image to MediaStore and publish.
+ *
+ * @param executor the thread for execution
+ * @param task the exporting image {@link Task}.
+ *
+ * @return a listenable future result
+ */
+ private ListenableFuture<Result> export(Executor executor, Task task) {
return CallbackToFutureAdapter.getFuture(
(completer) -> {
executor.execute(() -> {
@@ -220,9 +275,25 @@
private final boolean mPublish;
private final FeatureFlags mFlags;
+ /**
+ * This variable specifies the behavior when a file to be exported has a same name and
+ * format as one of the file on disk. If this is set to true, the new file overwrite the
+ * old file; otherwise, the system adds a number to the end of the newly exported file. For
+ * example, if the file is screenshot.png, the newly exported file's display name will be
+ * screenshot(1).png.
+ */
+ private final boolean mAllowOverwrite;
+
Task(ContentResolver resolver, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime,
CompressFormat format, int quality, boolean publish, UserHandle owner,
- FeatureFlags flags, int displayId) {
+ FeatureFlags flags, String fileName) {
+ this(resolver, requestId, bitmap, captureTime, format, quality, publish, owner, flags,
+ fileName, false /* allowOverwrite */);
+ }
+
+ Task(ContentResolver resolver, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime,
+ CompressFormat format, int quality, boolean publish, UserHandle owner,
+ FeatureFlags flags, String fileName, boolean allowOverwrite) {
mResolver = resolver;
mRequestId = requestId;
mBitmap = bitmap;
@@ -230,9 +301,10 @@
mFormat = format;
mQuality = quality;
mOwner = owner;
- mFileName = createFilename(mCaptureTime, mFormat, displayId);
+ mFileName = fileName;
mPublish = publish;
mFlags = flags;
+ mAllowOverwrite = allowOverwrite;
}
public Result execute() throws ImageExportException, InterruptedException {
@@ -246,7 +318,8 @@
start = Instant.now();
}
- uri = createEntry(mResolver, mFormat, mCaptureTime, mFileName, mOwner, mFlags);
+ uri = createEntry(mResolver, mFormat, mCaptureTime, mFileName, mOwner, mFlags,
+ mAllowOverwrite);
throwIfInterrupted();
writeImage(mResolver, mBitmap, mFormat, mQuality, uri);
@@ -290,21 +363,51 @@
}
private static Uri createEntry(ContentResolver resolver, CompressFormat format,
- ZonedDateTime time, String fileName, UserHandle owner, FeatureFlags flags)
- throws ImageExportException {
+ ZonedDateTime time, String fileName, UserHandle owner, FeatureFlags flags,
+ boolean allowOverwrite) throws ImageExportException {
Trace.beginSection("ImageExporter_createEntry");
try {
final ContentValues values = createMetadata(time, format, fileName);
Uri baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Uri uriWithUserId = ContentProvider.maybeAddUserId(baseUri, owner.getIdentifier());
+ Uri resultUri = null;
- Uri uri = resolver.insert(uriWithUserId, values);
- if (uri == null) {
+ if (allowOverwrite) {
+ // Query to check if there is existing file with the same name and format.
+ Cursor cursor = resolver.query(
+ baseUri,
+ null,
+ MediaStore.MediaColumns.DISPLAY_NAME + "=? AND "
+ + MediaStore.MediaColumns.MIME_TYPE + "=?",
+ new String[]{fileName, getMimeType(format)},
+ null /* CancellationSignal */);
+ if (cursor != null) {
+ if (cursor.moveToFirst()) {
+ // If there is existing file, update the meta-data of its entry. The Entry's
+ // corresponding uri is composed of volume base-uri(or with user-id) and
+ // its row's unique ID.
+ int idIndex = cursor.getColumnIndex(MediaStore.MediaColumns._ID);
+ resultUri = ContentUris.withAppendedId(uriWithUserId,
+ cursor.getLong(idIndex));
+ resolver.update(resultUri, values, null);
+ Log.d(TAG, "Updated existing URI: " + resultUri);
+ }
+ cursor.close();
+ }
+ }
+
+ if (resultUri == null) {
+ // If file overwriting is disabled or there is no existing file to overwrite, create
+ // and insert a new entry.
+ resultUri = resolver.insert(uriWithUserId, values);
+ Log.d(TAG, "Inserted new URI: " + resultUri);
+ }
+
+ if (resultUri == null) {
throw new ImageExportException(RESOLVER_INSERT_RETURNED_NULL);
}
- Log.d(TAG, "Inserted new URI: " + uri);
- return uri;
+ return resultUri;
} finally {
Trace.endSection();
}
@@ -383,6 +486,11 @@
fileExtension(format));
}
+ @VisibleForTesting
+ static String createSystemFileDisplayName(String originalDisplayName, CompressFormat format) {
+ return originalDisplayName + "." + fileExtension(format);
+ }
+
static ContentValues createMetadata(ZonedDateTime captureTime, CompressFormat format,
String fileName) {
ContentValues values = new ContentValues();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotViewProxy.kt
index 2294fc0..d8c3850 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotViewProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotViewProxy.kt
@@ -22,12 +22,14 @@
import android.graphics.Bitmap
import android.graphics.Rect
import android.graphics.drawable.Drawable
+import android.util.Log
import android.view.Display
import android.view.LayoutInflater
import android.view.ScrollCaptureResponse
import android.view.View
import android.view.ViewTreeObserver
import android.view.WindowInsets
+import android.window.OnBackInvokedCallback
import android.window.OnBackInvokedDispatcher
import com.android.internal.logging.UiEventLogger
import com.android.systemui.flags.FeatureFlags
@@ -40,7 +42,6 @@
class LegacyScreenshotViewProxy(context: Context) : ScreenshotViewProxy {
override val view: ScreenshotView =
LayoutInflater.from(context).inflate(R.layout.screenshot, null) as ScreenshotView
- override val internalInsetsListener: ViewTreeObserver.OnComputeInternalInsetsListener
override val screenshotPreview: View
override var defaultDisplay: Int = Display.DEFAULT_DISPLAY
@@ -51,6 +52,9 @@
set(value) {
view.setDefaultTimeoutMillis(value)
}
+ override var onBackInvokedCallback: OnBackInvokedCallback = OnBackInvokedCallback {
+ Log.wtf(TAG, "OnBackInvoked called before being set!")
+ }
override var onKeyListener: View.OnKeyListener? = null
set(value) {
view.setOnKeyListener(value)
@@ -84,7 +88,35 @@
get() = view.isPendingSharedTransition
init {
- internalInsetsListener = view
+
+ view.addOnAttachStateChangeListener(
+ object : View.OnAttachStateChangeListener {
+ override fun onViewAttachedToWindow(view: View) {
+ if (LogConfig.DEBUG_INPUT) {
+ Log.d(TAG, "Registering Predictive Back callback")
+ }
+ view
+ .findOnBackInvokedDispatcher()
+ ?.registerOnBackInvokedCallback(
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT,
+ onBackInvokedCallback
+ )
+ }
+
+ override fun onViewDetachedFromWindow(view: View) {
+ if (LogConfig.DEBUG_INPUT) {
+ Log.d(TAG, "Unregistering Predictive Back callback")
+ }
+ view
+ .findOnBackInvokedDispatcher()
+ ?.unregisterOnBackInvokedCallback(onBackInvokedCallback)
+ }
+ }
+ )
+ if (LogConfig.DEBUG_WINDOW) {
+ Log.d(TAG, "adding OnComputeInternalInsetsListener")
+ }
+ view.viewTreeObserver.addOnComputeInternalInsetsListener(view)
screenshotPreview = view.screenshotPreview
}
@@ -139,12 +171,6 @@
override fun announceForAccessibility(string: String) = view.announceForAccessibility(string)
- override fun addOnAttachStateChangeListener(listener: View.OnAttachStateChangeListener) =
- view.addOnAttachStateChangeListener(listener)
-
- override fun findOnBackInvokedDispatcher(): OnBackInvokedDispatcher? =
- view.findOnBackInvokedDispatcher()
-
override fun getViewTreeObserver(): ViewTreeObserver = view.viewTreeObserver
override fun post(runnable: Runnable) {
@@ -156,4 +182,8 @@
return LegacyScreenshotViewProxy(context)
}
}
+
+ companion object {
+ private const val TAG = "LegacyScreenshotViewProxy"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 13448d2..1ca9b98 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -76,8 +76,6 @@
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
-import android.window.OnBackInvokedCallback;
-import android.window.OnBackInvokedDispatcher;
import android.window.WindowContext;
import com.android.internal.app.ChooserActivity;
@@ -265,13 +263,6 @@
private final UserManager mUserManager;
private final AssistContentRequester mAssistContentRequester;
- private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
- if (DEBUG_INPUT) {
- Log.d(TAG, "Predictive Back callback dispatched");
- }
- respondToKeyDismissal();
- };
-
private final MessageContainerController mMessageContainerController;
private Bitmap mScreenBitmap;
private SaveImageInBackgroundTask mSaveInBgTask;
@@ -594,27 +585,13 @@
}
mMessageContainerController.setView(mViewProxy.getView());
- mViewProxy.addOnAttachStateChangeListener(
- new View.OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(@NonNull View v) {
- if (DEBUG_INPUT) {
- Log.d(TAG, "Registering Predictive Back callback");
- }
- mViewProxy.findOnBackInvokedDispatcher().registerOnBackInvokedCallback(
- OnBackInvokedDispatcher.PRIORITY_DEFAULT, mOnBackInvokedCallback);
- }
-
- @Override
- public void onViewDetachedFromWindow(@NonNull View v) {
- if (DEBUG_INPUT) {
- Log.d(TAG, "Unregistering Predictive Back callback");
- }
- mViewProxy.findOnBackInvokedDispatcher()
- .unregisterOnBackInvokedCallback(mOnBackInvokedCallback);
- }
- });
mViewProxy.setLogger(mUiEventLogger);
+ mViewProxy.setOnBackInvokedCallback(() -> {
+ if (DEBUG_INPUT) {
+ Log.d(TAG, "Predictive Back callback dispatched");
+ }
+ respondToKeyDismissal();
+ });
mViewProxy.setCallbacks(new ScreenshotView.ScreenshotViewCallback() {
@Override
public void onUserInteraction() {
@@ -657,11 +634,6 @@
});
if (DEBUG_WINDOW) {
- Log.d(TAG, "adding OnComputeInternalInsetsListener");
- }
- mViewProxy.getViewTreeObserver().addOnComputeInternalInsetsListener(
- mViewProxy.getInternalInsetsListener());
- if (DEBUG_WINDOW) {
Log.d(TAG, "setContentView: " + mViewProxy.getView());
}
setContentView(mViewProxy.getView());
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotViewProxy.kt
index 0064521..381404a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotViewProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotViewProxy.kt
@@ -28,18 +28,18 @@
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.WindowInsets
-import android.window.OnBackInvokedDispatcher
+import android.window.OnBackInvokedCallback
import com.android.internal.logging.UiEventLogger
import com.android.systemui.flags.FeatureFlags
/** Abstraction of the surface between ScreenshotController and ScreenshotView */
interface ScreenshotViewProxy {
val view: ViewGroup
- val internalInsetsListener: ViewTreeObserver.OnComputeInternalInsetsListener
val screenshotPreview: View
var defaultDisplay: Int
var defaultTimeoutMillis: Long
+ var onBackInvokedCallback: OnBackInvokedCallback
var onKeyListener: OnKeyListener?
var flags: FeatureFlags?
var packageName: String
@@ -78,8 +78,6 @@
fun stopInputListening()
fun requestFocus()
fun announceForAccessibility(string: String)
- fun addOnAttachStateChangeListener(listener: View.OnAttachStateChangeListener)
- fun findOnBackInvokedDispatcher(): OnBackInvokedDispatcher?
fun getViewTreeObserver(): ViewTreeObserver
fun post(runnable: Runnable)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 2fd438b..a1644b2 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1288,10 +1288,9 @@
mView.getContext().getDisplay());
mKeyguardStatusViewController = statusViewComponent.getKeyguardStatusViewController();
mKeyguardStatusViewController.init();
- }
- mKeyguardStatusViewController.setSplitShadeEnabled(mSplitShadeEnabled);
- mKeyguardStatusViewController.getView().addOnLayoutChangeListener(
+ mKeyguardStatusViewController.setSplitShadeEnabled(mSplitShadeEnabled);
+ mKeyguardStatusViewController.getView().addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
int oldHeight = oldBottom - oldTop;
if (v.getHeight() != oldHeight) {
@@ -1299,7 +1298,8 @@
}
});
- updateClockAppearance();
+ updateClockAppearance();
+ }
}
@Override
@@ -1326,7 +1326,9 @@
private void onSplitShadeEnabledChanged() {
mShadeLog.logSplitShadeChanged(mSplitShadeEnabled);
- mKeyguardStatusViewController.setSplitShadeEnabled(mSplitShadeEnabled);
+ if (!migrateClocksToBlueprint()) {
+ mKeyguardStatusViewController.setSplitShadeEnabled(mSplitShadeEnabled);
+ }
// Reset any left over overscroll state. It is a rare corner case but can happen.
mQsController.setOverScrollAmount(0);
mScrimController.setNotificationsOverScrollAmount(0);
@@ -1441,11 +1443,13 @@
mStatusBarStateListener.onDozeAmountChanged(mStatusBarStateController.getDozeAmount(),
mStatusBarStateController.getInterpolatedDozeAmount());
- mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
- mBarState,
- false,
- false,
- mBarState);
+ if (!migrateClocksToBlueprint()) {
+ mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
+ mBarState,
+ false,
+ false,
+ mBarState);
+ }
if (mKeyguardQsUserSwitchController != null) {
mKeyguardQsUserSwitchController.setKeyguardQsUserSwitchVisibility(
mBarState,
@@ -1665,13 +1669,11 @@
mKeyguardStatusViewController.setLockscreenClockY(
mClockPositionAlgorithm.getExpandedPreferredClockY());
}
- if (keyguardBottomAreaRefactor()) {
- mKeyguardInteractor.setClockPosition(
- mClockPositionResult.clockX, mClockPositionResult.clockY);
- } else {
+ if (!(migrateClocksToBlueprint() || keyguardBottomAreaRefactor())) {
mKeyguardBottomAreaInteractor.setClockPosition(
mClockPositionResult.clockX, mClockPositionResult.clockY);
}
+
boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
boolean animateClock = (animate || mAnimateNextPositionUpdate) && shouldAnimateClockChange;
@@ -1749,13 +1751,11 @@
}
private void updateKeyguardStatusViewAlignment(boolean animate) {
- boolean shouldBeCentered = shouldKeyguardStatusViewBeCentered();
- ConstraintLayout layout;
if (migrateClocksToBlueprint()) {
- layout = mKeyguardViewConfigurator.getKeyguardRootView();
- } else {
- layout = mNotificationContainerParent;
+ return;
}
+ boolean shouldBeCentered = shouldKeyguardStatusViewBeCentered();
+ ConstraintLayout layout = mNotificationContainerParent;
mKeyguardStatusViewController.updateAlignment(
layout, mSplitShadeEnabled, shouldBeCentered, animate);
mKeyguardUnfoldTransition.ifPresent(t -> t.setStatusViewCentered(shouldBeCentered));
@@ -3316,6 +3316,9 @@
/** Updates the views to the initial state for the fold to AOD animation. */
@Override
public void prepareFoldToAodAnimation() {
+ if (migrateClocksToBlueprint()) {
+ return;
+ }
// Force show AOD UI even if we are not locked
showAodUi();
@@ -3337,6 +3340,9 @@
@Override
public void startFoldToAodAnimation(Runnable startAction, Runnable endAction,
Runnable cancelAction) {
+ if (migrateClocksToBlueprint()) {
+ return;
+ }
final ViewPropertyAnimator viewAnimator = mView.animate();
viewAnimator.cancel();
viewAnimator
@@ -3372,6 +3378,9 @@
/** Cancels fold to AOD transition and resets view state. */
@Override
public void cancelFoldToAodAnimation() {
+ if (migrateClocksToBlueprint()) {
+ return;
+ }
cancelAnimation();
resetAlpha();
resetTranslation();
@@ -4446,11 +4455,13 @@
}
}
- mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
- statusBarState,
- keyguardFadingAway,
- goingToFullShade,
- mBarState);
+ if (!migrateClocksToBlueprint()) {
+ mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
+ statusBarState,
+ keyguardFadingAway,
+ goingToFullShade,
+ mBarState);
+ }
if (!keyguardBottomAreaRefactor()) {
setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 1ec86ae..c904621 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -147,8 +147,9 @@
private static final int MSG_SHOW_ACTION_TO_UNLOCK = 1;
private static final int MSG_RESET_ERROR_MESSAGE_ON_SCREEN_ON = 2;
private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300;
+ public static final long DEFAULT_MESSAGE_TIME = 3500;
public static final long DEFAULT_HIDE_DELAY_MS =
- 3500 + KeyguardIndicationTextView.Y_IN_DURATION;
+ DEFAULT_MESSAGE_TIME + KeyguardIndicationTextView.Y_IN_DURATION;
private final Context mContext;
private final BroadcastDispatcher mBroadcastDispatcher;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index 14593cb..e141b7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row;
+import static android.app.Notification.EXTRA_BUILDER_APPLICATION_INFO;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
@@ -353,18 +354,15 @@
}
private void bindPackage() {
- ApplicationInfo info;
- try {
- info = mPm.getApplicationInfo(
- mPackageName,
- PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_DISABLED_COMPONENTS
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.MATCH_DIRECT_BOOT_AWARE);
- if (info != null) {
+ // filled in if missing during notification inflation, which must have happened if
+ // we have a notification to long press on
+ ApplicationInfo info =
+ mSbn.getNotification().extras.getParcelable(EXTRA_BUILDER_APPLICATION_INFO,
+ ApplicationInfo.class);
+ if (info != null) {
+ try {
mAppName = String.valueOf(mPm.getApplicationLabel(info));
- }
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (Exception ignored) {}
}
((TextView) findViewById(R.id.pkg_name)).setText(mAppName);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index d8ebd42..2012099 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row;
+import static android.app.Notification.EXTRA_BUILDER_APPLICATION_INFO;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
@@ -66,7 +67,6 @@
import java.lang.annotation.Retention;
import java.util.List;
-import java.util.Set;
/**
* The guts of a notification revealed when performing a long press.
@@ -297,19 +297,18 @@
private void bindHeader() {
// Package name
mPkgIcon = null;
- ApplicationInfo info;
- try {
- info = mPm.getApplicationInfo(
- mPackageName,
- PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_DISABLED_COMPONENTS
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.MATCH_DIRECT_BOOT_AWARE);
- if (info != null) {
+ // filled in if missing during notification inflation, which must have happened if
+ // we have a notification to long press on
+ ApplicationInfo info =
+ mSbn.getNotification().extras.getParcelable(EXTRA_BUILDER_APPLICATION_INFO,
+ ApplicationInfo.class);
+ if (info != null) {
+ try {
mAppName = String.valueOf(mPm.getApplicationLabel(info));
mPkgIcon = mPm.getApplicationIcon(info);
- }
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (Exception ignored) {}
+ }
+ if (mPkgIcon == null) {
// app is gone, just show package name and generic icon
mPkgIcon = mPm.getDefaultActivityIcon();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 78fc147..3a9cdd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -474,7 +474,10 @@
*/
fun translationY(params: BurnInParameters): Flow<Float> {
return combine(
- aodBurnInViewModel.translationY(params).onStart { emit(0f) },
+ aodBurnInViewModel
+ .movement(params)
+ .map { it.translationY.toFloat() }
+ .onStart { emit(0f) },
isOnLockscreenWithoutShade,
merge(
keyguardInteractor.keyguardTranslationY,
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/ClientTrackingWakeLock.kt b/packages/SystemUI/src/com/android/systemui/util/wakelock/ClientTrackingWakeLock.kt
index db300eb..2157fafa 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/ClientTrackingWakeLock.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/ClientTrackingWakeLock.kt
@@ -18,6 +18,7 @@
import android.os.PowerManager
import android.util.Log
+import com.android.systemui.util.wakelock.WakeLock.Builder.NO_TIMEOUT
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicInteger
@@ -36,7 +37,11 @@
override fun acquire(why: String) {
val count = activeClients.computeIfAbsent(why) { _ -> AtomicInteger(0) }.incrementAndGet()
logger?.logAcquire(pmWakeLock, why, count)
- pmWakeLock.acquire(maxTimeout)
+ if (maxTimeout == NO_TIMEOUT) {
+ pmWakeLock.acquire()
+ } else {
+ pmWakeLock.acquire(maxTimeout)
+ }
}
override fun release(why: String) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
index 707751a..f763ee4 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
@@ -130,7 +130,11 @@
if (logger != null) {
logger.logAcquire(inner, why, count);
}
- inner.acquire(maxTimeout);
+ if (maxTimeout == Builder.NO_TIMEOUT) {
+ inner.acquire();
+ } else {
+ inner.acquire(maxTimeout);
+ }
}
/** @see PowerManager.WakeLock#release() */
@@ -169,6 +173,7 @@
* An injectable Builder that wraps {@link #createPartial(Context, String, long)}.
*/
class Builder {
+ public static final long NO_TIMEOUT = -1;
private final Context mContext;
private final WakeLockLogger mLogger;
private String mTag;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/SpatializerModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dagger/SpatializerModule.kt
index 593b90a..4ba7cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dagger/SpatializerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/SpatializerModule.kt
@@ -21,12 +21,10 @@
import com.android.settingslib.media.data.repository.SpatializerRepository
import com.android.settingslib.media.data.repository.SpatializerRepositoryImpl
import com.android.settingslib.media.domain.interactor.SpatializerInteractor
-import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import dagger.Module
import dagger.Provides
import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CoroutineScope
/** Spatializer module. */
@Module
@@ -42,9 +40,8 @@
@Provides
fun provdieSpatializerRepository(
spatializer: Spatializer,
- @Application scope: CoroutineScope,
@Background backgroundContext: CoroutineContext,
- ): SpatializerRepository = SpatializerRepositoryImpl(spatializer, scope, backgroundContext)
+ ): SpatializerRepository = SpatializerRepositoryImpl(spatializer, backgroundContext)
@Provides
fun provideSpatializerInetractor(repository: SpatializerRepository): SpatializerInteractor =
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ToggleButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ToggleButtonViewModel.kt
index 8ab563a..6c47aec 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ToggleButtonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/button/ui/viewmodel/ToggleButtonViewModel.kt
@@ -23,3 +23,6 @@
val icon: Icon,
val label: CharSequence,
)
+
+fun ToggleButtonViewModel.toButtonViewModel(): ButtonViewModel =
+ ButtonViewModel(icon = icon, label = label)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/shared/model/VolumePanelComponents.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/shared/model/VolumePanelComponents.kt
index 9d801fc..9ef07fa 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/shared/model/VolumePanelComponents.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/shared/model/VolumePanelComponents.kt
@@ -24,5 +24,6 @@
const val BOTTOM_BAR: VolumePanelComponentKey = "bottom_bar"
const val VOLUME_SLIDERS: VolumePanelComponentKey = "volume_sliders"
const val CAPTIONING: VolumePanelComponentKey = "captioning"
+ const val SPATIAL_AUDIO: VolumePanelComponentKey = "spatial_audio"
const val ANC: VolumePanelComponentKey = "anc"
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt
index 4358611..6032bfe 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt
@@ -71,10 +71,10 @@
combine(
currentAudioDeviceAttributes,
changes.onStart { emit(Unit) },
- spatializerInteractor.isHeadTrackingAvailable,
- ) { attributes, _, isHeadTrackingAvailable ->
+ ) { attributes, _,
+ ->
attributes ?: return@combine SpatialAudioAvailabilityModel.Unavailable
- if (isHeadTrackingAvailable) {
+ if (spatializerInteractor.isHeadTrackingAvailable(attributes)) {
return@combine SpatialAudioAvailabilityModel.HeadTracking
}
if (spatializerInteractor.isSpatialAudioAvailable(attributes)) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/model/SpatialAudioEnabledModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/model/SpatialAudioEnabledModel.kt
index 4e65f60..9735e5c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/model/SpatialAudioEnabledModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/model/SpatialAudioEnabledModel.kt
@@ -19,6 +19,16 @@
/** Models spatial audio and head tracking enabled/disabled state. */
interface SpatialAudioEnabledModel {
+ companion object {
+ /** All possible SpatialAudioEnabledModel implementations. */
+ val values =
+ listOf(
+ Disabled,
+ SpatialAudioEnabled,
+ HeadTrackingEnabled,
+ )
+ }
+
/** Spatial audio is disabled. */
data object Disabled : SpatialAudioEnabledModel
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt
new file mode 100644
index 0000000..9f9275b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioButtonViewModel.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 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.volume.panel.component.spatial.ui.viewmodel
+
+import com.android.systemui.common.shared.model.Color
+import com.android.systemui.volume.panel.component.button.ui.viewmodel.ToggleButtonViewModel
+import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioEnabledModel
+
+data class SpatialAudioButtonViewModel(
+ val model: SpatialAudioEnabledModel,
+ val button: ToggleButtonViewModel,
+ val iconColor: Color,
+ val labelColor: Color,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt
new file mode 100644
index 0000000..30715d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/ui/viewmodel/SpatialAudioViewModel.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2024 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.volume.panel.component.spatial.ui.viewmodel
+
+import android.content.Context
+import com.android.systemui.common.shared.model.Color
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.res.R
+import com.android.systemui.volume.panel.component.button.ui.viewmodel.ButtonViewModel
+import com.android.systemui.volume.panel.component.button.ui.viewmodel.ToggleButtonViewModel
+import com.android.systemui.volume.panel.component.button.ui.viewmodel.toButtonViewModel
+import com.android.systemui.volume.panel.component.spatial.domain.SpatialAudioAvailabilityCriteria
+import com.android.systemui.volume.panel.component.spatial.domain.interactor.SpatialAudioComponentInteractor
+import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioAvailabilityModel
+import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioEnabledModel
+import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
+
+@VolumePanelScope
+class SpatialAudioViewModel
+@Inject
+constructor(
+ @Application private val context: Context,
+ @VolumePanelScope private val scope: CoroutineScope,
+ availabilityCriteria: SpatialAudioAvailabilityCriteria,
+ private val interactor: SpatialAudioComponentInteractor,
+) {
+
+ val spatialAudioButton: StateFlow<ButtonViewModel?> =
+ interactor.isEnabled
+ .map { it.toViewModel(true).toButtonViewModel() }
+ .stateIn(scope, SharingStarted.Eagerly, null)
+
+ val isAvailable: StateFlow<Boolean> =
+ availabilityCriteria.isAvailable().stateIn(scope, SharingStarted.Eagerly, true)
+
+ val spatialAudioButtonByEnabled: StateFlow<List<SpatialAudioButtonViewModel>> =
+ combine(interactor.isEnabled, interactor.isAvailable) { currentIsEnabled, isAvailable ->
+ SpatialAudioEnabledModel.values
+ .filter {
+ if (it is SpatialAudioEnabledModel.HeadTrackingEnabled) {
+ // Spatial audio control can be visible when there is spatial audio
+ // setting available but not the head tracking.
+ isAvailable is SpatialAudioAvailabilityModel.HeadTracking
+ } else {
+ true
+ }
+ }
+ .map { isEnabled ->
+ val isChecked = isEnabled == currentIsEnabled
+ val buttonViewModel: ToggleButtonViewModel =
+ isEnabled.toViewModel(isChecked)
+ SpatialAudioButtonViewModel(
+ button = buttonViewModel,
+ model = isEnabled,
+ iconColor =
+ Color.Attribute(
+ if (isChecked)
+ com.android.internal.R.attr.materialColorOnPrimaryContainer
+ else com.android.internal.R.attr.materialColorOnSurfaceVariant
+ ),
+ labelColor =
+ Color.Attribute(
+ if (isChecked)
+ com.android.internal.R.attr.materialColorOnSurface
+ else com.android.internal.R.attr.materialColorOutline
+ ),
+ )
+ }
+ }
+ .stateIn(scope, SharingStarted.Eagerly, emptyList())
+
+ fun setEnabled(model: SpatialAudioEnabledModel) {
+ scope.launch { interactor.setEnabled(model) }
+ }
+
+ private fun SpatialAudioEnabledModel.toViewModel(isChecked: Boolean): ToggleButtonViewModel {
+ if (this is SpatialAudioEnabledModel.HeadTrackingEnabled) {
+ return ToggleButtonViewModel(
+ isChecked = isChecked,
+ icon = Icon.Resource(R.drawable.ic_head_tracking, contentDescription = null),
+ label = context.getString(R.string.volume_panel_spatial_audio_tracking)
+ )
+ }
+
+ if (this is SpatialAudioEnabledModel.SpatialAudioEnabled) {
+ return ToggleButtonViewModel(
+ isChecked = isChecked,
+ icon = Icon.Resource(R.drawable.ic_spatial_audio, contentDescription = null),
+ label = context.getString(R.string.volume_panel_spatial_audio_fixed)
+ )
+ }
+
+ if (this is SpatialAudioEnabledModel.Disabled) {
+ return ToggleButtonViewModel(
+ isChecked = isChecked,
+ icon = Icon.Resource(R.drawable.ic_spatial_audio_off, contentDescription = null),
+ label = context.getString(R.string.volume_panel_spatial_audio_off)
+ )
+ }
+
+ error("Unsupported model: $this")
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt
index f31ee86..d868c33 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/dagger/VolumePanelComponent.kt
@@ -20,6 +20,7 @@
import com.android.systemui.volume.panel.component.bottombar.BottomBarModule
import com.android.systemui.volume.panel.component.captioning.CaptioningModule
import com.android.systemui.volume.panel.component.mediaoutput.MediaOutputModule
+import com.android.systemui.volume.panel.component.spatialaudio.SpatialAudioModule
import com.android.systemui.volume.panel.component.volume.VolumeSlidersModule
import com.android.systemui.volume.panel.dagger.factory.VolumePanelComponentFactory
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
@@ -49,6 +50,7 @@
// Components modules
BottomBarModule::class,
AncModule::class,
+ SpatialAudioModule::class,
VolumeSlidersModule::class,
CaptioningModule::class,
MediaOutputModule::class,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/domain/DomainModule.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/domain/DomainModule.kt
index 57ea997..999f4c1 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/domain/DomainModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/domain/DomainModule.kt
@@ -51,6 +51,7 @@
fun provideEnabledComponents(): Collection<VolumePanelComponentKey> {
return setOf(
VolumePanelComponents.ANC,
+ VolumePanelComponents.SPATIAL_AUDIO,
VolumePanelComponents.CAPTIONING,
VolumePanelComponents.VOLUME_SLIDERS,
VolumePanelComponents.MEDIA_OUTPUT,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/UiModule.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/UiModule.kt
index ec4da06..8ba06e1 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/ui/UiModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/ui/UiModule.kt
@@ -49,6 +49,7 @@
fun provideFooterComponents(): Collection<VolumePanelComponentKey> {
return listOf(
VolumePanelComponents.ANC,
+ VolumePanelComponents.SPATIAL_AUDIO,
VolumePanelComponents.CAPTIONING,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
index 13fb42c..90587d7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
@@ -16,8 +16,6 @@
package com.android.keyguard;
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
-
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -32,7 +30,6 @@
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.power.data.repository.FakePowerRepository;
import com.android.systemui.power.domain.interactor.PowerInteractorFactory;
import com.android.systemui.res.R;
@@ -62,7 +59,6 @@
@Mock protected KeyguardStatusViewController mControllerMock;
@Mock protected InteractionJankMonitor mInteractionJankMonitor;
@Mock protected ViewTreeObserver mViewTreeObserver;
- @Mock protected KeyguardTransitionInteractor mKeyguardTransitionInteractor;
@Mock protected DumpManager mDumpManager;
protected FakeKeyguardRepository mFakeKeyguardRepository;
protected FakePowerRepository mFakePowerRepository;
@@ -93,7 +89,6 @@
mKeyguardLogger,
mInteractionJankMonitor,
deps.getKeyguardInteractor(),
- mKeyguardTransitionInteractor,
mDumpManager,
PowerInteractorFactory.create(
mFakePowerRepository
@@ -110,7 +105,6 @@
when(mKeyguardStatusView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
when(mKeyguardClockSwitchController.getView()).thenReturn(mKeyguardClockSwitch);
- when(mKeyguardTransitionInteractor.getGoneToAodTransition()).thenReturn(emptyFlow());
when(mKeyguardStatusView.findViewById(R.id.keyguard_status_area))
.thenReturn(mKeyguardStatusAreaView);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java
index 1ce6525..eced465 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java
@@ -22,11 +22,15 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
+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.app.UiModeManager;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.graphics.drawable.GradientDrawable;
import android.platform.test.annotations.EnableFlags;
@@ -54,6 +58,8 @@
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.util.ArrayList;
+
/** Tests for {@link MenuView}. */
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -73,6 +79,8 @@
private AccessibilityManager mAccessibilityManager;
private SysuiTestableContext mSpyContext;
+ @Mock
+ private PackageManager mMockPackageManager;
@Before
public void setUp() throws Exception {
@@ -82,6 +90,8 @@
mSpyContext = spy(mContext);
doNothing().when(mSpyContext).startActivity(any());
+
+ when(mSpyContext.getPackageManager()).thenReturn(mMockPackageManager);
final SecureSettings secureSettings = TestUtils.mockSecureSettings();
final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager,
secureSettings);
@@ -181,10 +191,19 @@
@Test
@EnableFlags(Flags.FLAG_FLOATING_MENU_DRAG_TO_EDIT)
public void gotoEditScreen_sendsIntent() {
+ mockActivityQuery(true);
mMenuView.gotoEditScreen();
verify(mSpyContext).startActivity(any());
}
+ @Test
+ @EnableFlags(Flags.FLAG_FLOATING_MENU_DRAG_TO_EDIT)
+ public void gotoEditScreen_noResolve_doesNotStart() {
+ mockActivityQuery(false);
+ mMenuView.gotoEditScreen();
+ verify(mSpyContext, never()).startActivity(any());
+ }
+
private InstantInsetLayerDrawable getMenuViewInsetLayer() {
return (InstantInsetLayerDrawable) mMenuView.getBackground();
}
@@ -207,4 +226,14 @@
mUiModeManager.setNightMode(mNightMode);
Prefs.putString(mContext, Prefs.Key.ACCESSIBILITY_FLOATING_MENU_POSITION, mLastPosition);
}
+
+ private void mockActivityQuery(boolean successfulQuery) {
+ // Query just needs to return a non-empty set to be successful.
+ ArrayList<ResolveInfo> resolveInfos = new ArrayList<>();
+ if (successfulQuery) {
+ resolveInfos.add(new ResolveInfo());
+ }
+ when(mMockPackageManager.queryIntentActivities(
+ any(), any(PackageManager.ResolveInfoFlags.class))).thenReturn(resolveInfos);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorTest.kt
index df52265..0bd541c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorTest.kt
@@ -20,16 +20,19 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.util.BurnInHelperWrapper
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.BurnInModel
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -43,41 +46,35 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class BurnInInteractorTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+ val configurationRepository = kosmos.fakeConfigurationRepository
+ val fakeKeyguardRepository = kosmos.fakeKeyguardRepository
+
private val burnInOffset = 7
private var burnInProgress = 0f
@Mock private lateinit var burnInHelperWrapper: BurnInHelperWrapper
- private lateinit var configurationRepository: FakeConfigurationRepository
- private lateinit var keyguardInteractor: KeyguardInteractor
- private lateinit var fakeKeyguardRepository: FakeKeyguardRepository
- private lateinit var testScope: TestScope
private lateinit var underTest: BurnInInteractor
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- configurationRepository = FakeConfigurationRepository()
context
.getOrCreateTestableResources()
.addOverride(R.dimen.burn_in_prevention_offset_y, burnInOffset)
-
- KeyguardInteractorFactory.create().let {
- keyguardInteractor = it.keyguardInteractor
- fakeKeyguardRepository = it.repository
- }
whenever(burnInHelperWrapper.burnInOffset(anyInt(), anyBoolean())).thenReturn(burnInOffset)
setBurnInProgress(.65f)
- testScope = TestScope()
underTest =
BurnInInteractor(
context,
burnInHelperWrapper,
- testScope.backgroundScope,
- configurationRepository,
- keyguardInteractor,
+ kosmos.applicationCoroutineScope,
+ kosmos.configurationInteractor,
+ kosmos.keyguardInteractor,
)
}
@@ -122,7 +119,13 @@
testScope.runTest {
whenever(burnInHelperWrapper.burnInScale()).thenReturn(0.5f)
- val burnInModel by collectLastValue(underTest.keyguardBurnIn)
+ val burnInModel by
+ collectLastValue(
+ underTest.burnIn(
+ xDimenResourceId = R.dimen.burn_in_prevention_offset_x,
+ yDimenResourceId = R.dimen.burn_in_prevention_offset_y
+ )
+ )
// After time tick, returns the configured values
fakeKeyguardRepository.dozeTimeTick(10)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
index 87eee1a..0a29821 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
@@ -22,23 +22,25 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.util.BurnInHelperWrapper
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.kosmos.testScope
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
import com.android.systemui.power.domain.interactor.PowerInteractorFactory
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.phone.SystemUIDialogManager
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -53,18 +55,19 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class UdfpsKeyguardInteractorTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+ val configRepository = kosmos.fakeConfigurationRepository
+ val keyguardRepository = kosmos.fakeKeyguardRepository
+
private val burnInProgress = 1f
private val burnInYOffset = 20
private val burnInXOffset = 10
- private lateinit var testScope: TestScope
- private lateinit var configRepository: FakeConfigurationRepository
private lateinit var bouncerRepository: KeyguardBouncerRepository
- private lateinit var keyguardRepository: FakeKeyguardRepository
private lateinit var fakeCommandQueue: FakeCommandQueue
private lateinit var burnInInteractor: BurnInInteractor
private lateinit var shadeRepository: FakeShadeRepository
- private lateinit var keyguardInteractor: KeyguardInteractor
private lateinit var powerInteractor: PowerInteractor
@Mock private lateinit var burnInHelper: BurnInHelperWrapper
@@ -75,12 +78,6 @@
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- testScope = TestScope()
- configRepository = FakeConfigurationRepository()
- KeyguardInteractorFactory.create().let {
- keyguardInteractor = it.keyguardInteractor
- keyguardRepository = it.repository
- }
bouncerRepository = FakeKeyguardBouncerRepository()
shadeRepository = FakeShadeRepository()
fakeCommandQueue = FakeCommandQueue()
@@ -89,8 +86,8 @@
context,
burnInHelper,
testScope.backgroundScope,
- configRepository,
- keyguardInteractor
+ kosmos.configurationInteractor,
+ kosmos.keyguardInteractor
)
powerInteractor = PowerInteractorFactory.create().powerInteractor
@@ -98,7 +95,7 @@
UdfpsKeyguardInteractor(
configRepository,
burnInInteractor,
- keyguardInteractor,
+ kosmos.keyguardInteractor,
shadeRepository,
dialogManager,
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
deleted file mode 100644
index 864acfb..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2023 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.keyguard.ui.viewmodel
-
-import androidx.test.filters.SmallTest
-import com.android.systemui.Flags as AConfigFlags
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.doze.util.BurnInHelperWrapper
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
-import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(JUnit4::class)
-class KeyguardIndicationAreaViewModelTest : SysuiTestCase() {
-
- @Mock private lateinit var burnInHelperWrapper: BurnInHelperWrapper
- @Mock private lateinit var shortcutsCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel
-
- private lateinit var underTest: KeyguardIndicationAreaViewModel
- private lateinit var repository: FakeKeyguardRepository
-
- private val startButtonFlow =
- MutableStateFlow<KeyguardQuickAffordanceViewModel>(
- KeyguardQuickAffordanceViewModel(
- slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId()
- )
- )
- private val endButtonFlow =
- MutableStateFlow<KeyguardQuickAffordanceViewModel>(
- KeyguardQuickAffordanceViewModel(
- slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId()
- )
- )
- private val alphaFlow = MutableStateFlow<Float>(1f)
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
-
- mSetFlagsRule.disableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
-
- whenever(burnInHelperWrapper.burnInOffset(anyInt(), any()))
- .thenReturn(RETURNED_BURN_IN_OFFSET)
-
- val withDeps = KeyguardInteractorFactory.create()
- val keyguardInteractor = withDeps.keyguardInteractor
- repository = withDeps.repository
-
- val bottomAreaViewModel: KeyguardBottomAreaViewModel = mock()
- whenever(bottomAreaViewModel.startButton).thenReturn(startButtonFlow)
- whenever(bottomAreaViewModel.endButton).thenReturn(endButtonFlow)
- whenever(bottomAreaViewModel.alpha).thenReturn(alphaFlow)
- underTest =
- KeyguardIndicationAreaViewModel(
- keyguardInteractor = keyguardInteractor,
- bottomAreaInteractor = KeyguardBottomAreaInteractor(repository = repository),
- keyguardBottomAreaViewModel = bottomAreaViewModel,
- burnInHelperWrapper = burnInHelperWrapper,
- shortcutsCombinedViewModel = shortcutsCombinedViewModel,
- configurationInteractor = ConfigurationInteractor(FakeConfigurationRepository()),
- )
- }
-
- @Test
- fun alpha() = runTest {
- val value = collectLastValue(underTest.alpha)
-
- assertThat(value()).isEqualTo(1f)
- alphaFlow.value = 0.1f
- assertThat(value()).isEqualTo(0.1f)
- alphaFlow.value = 0.5f
- assertThat(value()).isEqualTo(0.5f)
- alphaFlow.value = 0.2f
- assertThat(value()).isEqualTo(0.2f)
- alphaFlow.value = 0f
- assertThat(value()).isEqualTo(0f)
- }
-
- @Test
- fun isIndicationAreaPadded() = runTest {
- repository.setKeyguardShowing(true)
- val value = collectLastValue(underTest.isIndicationAreaPadded)
-
- assertThat(value()).isFalse()
- startButtonFlow.value = startButtonFlow.value.copy(isVisible = true)
- assertThat(value()).isTrue()
- endButtonFlow.value = endButtonFlow.value.copy(isVisible = true)
- assertThat(value()).isTrue()
- startButtonFlow.value = startButtonFlow.value.copy(isVisible = false)
- assertThat(value()).isTrue()
- endButtonFlow.value = endButtonFlow.value.copy(isVisible = false)
- assertThat(value()).isFalse()
- }
-
- @Test
- fun indicationAreaTranslationX() = runTest {
- val value = collectLastValue(underTest.indicationAreaTranslationX)
-
- assertThat(value()).isEqualTo(0f)
- repository.setClockPosition(100, 100)
- assertThat(value()).isEqualTo(100f)
- repository.setClockPosition(200, 100)
- assertThat(value()).isEqualTo(200f)
- repository.setClockPosition(200, 200)
- assertThat(value()).isEqualTo(200f)
- repository.setClockPosition(300, 100)
- assertThat(value()).isEqualTo(300f)
- }
-
- @Test
- fun indicationAreaTranslationY() = runTest {
- val value = collectLastValue(underTest.indicationAreaTranslationY(DEFAULT_BURN_IN_OFFSET))
-
- // Negative 0 - apparently there's a difference in floating point arithmetic - FML
- assertThat(value()).isEqualTo(-0f)
- val expected1 = setDozeAmountAndCalculateExpectedTranslationY(0.1f)
- assertThat(value()).isEqualTo(expected1)
- val expected2 = setDozeAmountAndCalculateExpectedTranslationY(0.2f)
- assertThat(value()).isEqualTo(expected2)
- val expected3 = setDozeAmountAndCalculateExpectedTranslationY(0.5f)
- assertThat(value()).isEqualTo(expected3)
- val expected4 = setDozeAmountAndCalculateExpectedTranslationY(1f)
- assertThat(value()).isEqualTo(expected4)
- }
-
- private fun setDozeAmountAndCalculateExpectedTranslationY(dozeAmount: Float): Float {
- repository.setDozeAmount(dozeAmount)
- return dozeAmount * (RETURNED_BURN_IN_OFFSET - DEFAULT_BURN_IN_OFFSET)
- }
-
- companion object {
- private const val DEFAULT_BURN_IN_OFFSET = 5
- private const val RETURNED_BURN_IN_OFFSET = 3
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index ca403e0..695d3b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -19,7 +19,6 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -48,7 +47,6 @@
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.settingslib.media.LocalMediaManager;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.broadcast.BroadcastSender;
@@ -129,12 +127,6 @@
mNearbyMediaDevicesManager, mAudioManager, mPowerExemptionManager,
mKeyguardManager, mFlags, mUserTracker);
- // Using a fake package will cause routing operations to fail, so we intercept
- // scanning-related operations.
- mMediaOutputController.mLocalMediaManager = mock(LocalMediaManager.class);
- doNothing().when(mMediaOutputController.mLocalMediaManager).startScan();
- doNothing().when(mMediaOutputController.mLocalMediaManager).stopScan();
-
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender,
mMediaOutputController);
mMediaOutputBaseDialogImpl.onCreate(new Bundle());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java
index 6068c23..f4d7a5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.screenshot;
+import static com.android.systemui.screenshot.ImageExporter.createSystemFileDisplayName;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -182,6 +184,30 @@
}
@Test
+ public void testImageExport_customizedFileName()
+ throws ExecutionException, InterruptedException {
+ // This test only asserts the file name for the case when user specifies a file name,
+ // instead of using the auto-generated name by ImageExporter::createFileName. Other
+ // metadata are not affected by the specified file name.
+ final String customizedFileName = "customized_file_name";
+ ContentResolver contentResolver = mContext.getContentResolver();
+ ImageExporter exporter = new ImageExporter(contentResolver, mFeatureFlags);
+
+ UUID requestId = UUID.fromString("3c11da99-9284-4863-b1d5-6f3684976814");
+ Bitmap original = createCheckerBitmap(10, 10, 10);
+
+ ListenableFuture<ImageExporter.Result> direct =
+ exporter.export(DIRECT_EXECUTOR, requestId, original, CAPTURE_TIME,
+ Process.myUserHandle(), customizedFileName);
+ assertTrue("future should be done", direct.isDone());
+ assertFalse("future should not be canceled", direct.isCancelled());
+ ImageExporter.Result result = direct.get();
+ assertEquals("Filename should contain the correct filename",
+ createSystemFileDisplayName(customizedFileName, CompressFormat.PNG),
+ result.fileName);
+ }
+
+ @Test
public void testMediaStoreMetadata() {
String name = ImageExporter.createFilename(CAPTURE_TIME, CompressFormat.PNG,
Display.DEFAULT_DISPLAY);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index acbf997..cdff4d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -461,7 +461,6 @@
mKeyguardLogger,
mInteractionJankMonitor,
mKeyguardInteractor,
- mKeyguardTransitionInteractor,
mDumpManager,
mPowerInteractor));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index 1763d9b..3c1f559 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row;
+import static android.app.Notification.EXTRA_BUILDER_APPLICATION_INFO;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
@@ -183,8 +184,6 @@
.thenReturn(packageInfo);
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.uid = TEST_UID; // non-zero
- when(mMockPackageManager.getApplicationInfo(eq(TEST_PACKAGE_NAME), anyInt())).thenReturn(
- applicationInfo);
final PackageInfo systemPackageInfo = new PackageInfo();
systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME;
when(mMockPackageManager.getPackageInfo(eq(TEST_SYSTEM_PACKAGE_NAME), anyInt()))
@@ -207,6 +206,7 @@
.addMessage(new Notification.MessagingStyle.Message(
"hello!", 1000, new Person.Builder().setName("other").build())))
.build();
+ notification.extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, applicationInfo);
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
notification, UserHandle.CURRENT, null, 0);
mEntry = new NotificationEntryBuilder().setSbn(mSbn).setShortcutInfo(mShortcutInfo).build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index b59385c..f31b1c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row;
+import static android.app.Notification.EXTRA_BUILDER_APPLICATION_INFO;
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
@@ -143,8 +144,6 @@
.thenReturn(packageInfo);
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.uid = TEST_UID; // non-zero
- when(mMockPackageManager.getApplicationInfo(eq(TEST_PACKAGE_NAME), anyInt())).thenReturn(
- applicationInfo);
final PackageInfo systemPackageInfo = new PackageInfo();
systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME;
when(mMockPackageManager.getPackageInfo(eq(TEST_SYSTEM_PACKAGE_NAME), anyInt()))
@@ -162,8 +161,10 @@
mDefaultNotificationChannel = new NotificationChannel(
NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
IMPORTANCE_LOW);
+ Notification notification = new Notification();
+ notification.extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, applicationInfo);
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
- new Notification(), UserHandle.getUserHandleForUid(TEST_UID), null, 0);
+ notification, UserHandle.getUserHandleForUid(TEST_UID), null, 0);
mEntry = new NotificationEntryBuilder().setSbn(mSbn).build();
when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(false);
when(mAssistantFeedbackController.getInlineDescriptionResource(any()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index fbefb0e..c0d3d27 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -90,6 +90,7 @@
import android.view.ViewTreeObserver;
import android.view.WindowManager;
+import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
@@ -196,6 +197,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
@@ -2251,6 +2253,30 @@
verify(mBubbleController).onSensitiveNotificationProtectionStateChanged(false);
}
+ @Test
+ public void setBubbleBarLocation_listenerNotified() {
+ mBubbleProperties.mIsBubbleBarEnabled = true;
+ mPositioner.setIsLargeScreen(true);
+
+ FakeBubbleStateListener bubbleStateListener = new FakeBubbleStateListener();
+ mBubbleController.registerBubbleStateListener(bubbleStateListener);
+ mBubbleController.setBubbleBarLocation(BubbleBarLocation.LEFT);
+ assertThat(bubbleStateListener.mLastUpdate).isNotNull();
+ assertThat(bubbleStateListener.mLastUpdate.bubbleBarLocation).isEqualTo(
+ BubbleBarLocation.LEFT);
+ }
+
+ @Test
+ public void setBubbleBarLocation_barDisabled_shouldBeIgnored() {
+ mBubbleProperties.mIsBubbleBarEnabled = false;
+ mPositioner.setIsLargeScreen(true);
+
+ FakeBubbleStateListener bubbleStateListener = new FakeBubbleStateListener();
+ mBubbleController.registerBubbleStateListener(bubbleStateListener);
+ mBubbleController.setBubbleBarLocation(BubbleBarLocation.LEFT);
+ assertThat(bubbleStateListener.mStateChangeCalls).isEqualTo(0);
+ }
+
/** Creates a bubble using the userId and package. */
private Bubble createBubble(int userId, String pkg) {
final UserHandle userHandle = new UserHandle(userId);
@@ -2436,8 +2462,15 @@
}
private static class FakeBubbleStateListener implements Bubbles.BubbleStateListener {
+
+ int mStateChangeCalls = 0;
+ @Nullable
+ BubbleBarUpdate mLastUpdate;
+
@Override
public void onBubbleStateChange(BubbleBarUpdate update) {
+ mStateChangeCalls++;
+ mLastUpdate = update;
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 793e2d7..1e305d6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.data.repository
import android.graphics.Point
-import com.android.systemui.common.shared.model.Position
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
@@ -58,9 +57,6 @@
private val _bottomAreaAlpha = MutableStateFlow(1f)
override val bottomAreaAlpha: StateFlow<Float> = _bottomAreaAlpha
- private val _clockPosition = MutableStateFlow(Position(0, 0))
- override val clockPosition: StateFlow<Position> = _clockPosition
-
private val _isKeyguardShowing = MutableStateFlow(false)
override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
@@ -149,10 +145,6 @@
_bottomAreaAlpha.value = alpha
}
- override fun setClockPosition(x: Int, y: Int) {
- _clockPosition.value = Position(x, y)
- }
-
fun setKeyguardShowing(isShowing: Boolean) {
_isKeyguardShowing.value = isShowing
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorKosmos.kt
index a9d89a3..40131c7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/BurnInInteractorKosmos.kt
@@ -19,7 +19,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.content.applicationContext
-import com.android.systemui.common.ui.data.repository.configurationRepository
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.doze.util.burnInHelperWrapper
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
@@ -31,7 +31,7 @@
context = applicationContext,
burnInHelperWrapper = burnInHelperWrapper,
scope = applicationCoroutineScope,
- configurationRepository = configurationRepository,
+ configurationInteractor = configurationInteractor,
keyguardInteractor = keyguardInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModelKosmos.kt
new file mode 100644
index 0000000..b7d9676
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerMessageAreaViewModelKosmos.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 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.keyguard.ui.viewmodel
+
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
+import com.android.systemui.deviceentry.domain.interactor.biometricMessageInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.time.systemClock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@ExperimentalCoroutinesApi
+val Kosmos.alternateBouncerMessageAreaViewModel by
+ Kosmos.Fixture {
+ AlternateBouncerMessageAreaViewModel(
+ biometricMessageInteractor = biometricMessageInteractor,
+ alternateBouncerInteractor = alternateBouncerInteractor,
+ systemClock = systemClock,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
index 75e3ac2..a863edf 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
@@ -23,6 +23,7 @@
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
import com.android.systemui.statusbar.phone.dozeParameters
@@ -31,6 +32,7 @@
val Kosmos.keyguardRootViewModel by Fixture {
KeyguardRootViewModel(
+ scope = applicationCoroutineScope,
deviceEntryInteractor = deviceEntryInteractor,
dozeParameters = dozeParameters,
keyguardInteractor = keyguardInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/data/repository/FakeSpatializerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/data/repository/FakeSpatializerRepository.kt
index 0183b97..63e2d4b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/data/repository/FakeSpatializerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/data/repository/FakeSpatializerRepository.kt
@@ -18,23 +18,27 @@
import android.media.AudioDeviceAttributes
import com.android.settingslib.media.data.repository.SpatializerRepository
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
class FakeSpatializerRepository : SpatializerRepository {
var defaultSpatialAudioAvailable: Boolean = false
+ var defaultHeadTrackingAvailable: Boolean = false
private val spatialAudioAvailabilityByDevice: MutableMap<AudioDeviceAttributes, Boolean> =
mutableMapOf()
+ private val headTrackingAvailabilityByDevice: MutableMap<AudioDeviceAttributes, Boolean> =
+ mutableMapOf()
private val spatialAudioCompatibleDevices: MutableList<AudioDeviceAttributes> = mutableListOf()
- private val mutableHeadTrackingAvailable = MutableStateFlow(false)
private val headTrackingEnabledByDevice = mutableMapOf<AudioDeviceAttributes, Boolean>()
- override val isHeadTrackingAvailable: StateFlow<Boolean> =
- mutableHeadTrackingAvailable.asStateFlow()
+ override suspend fun isHeadTrackingAvailableForDevice(
+ audioDeviceAttributes: AudioDeviceAttributes
+ ): Boolean =
+ headTrackingAvailabilityByDevice.getOrDefault(
+ audioDeviceAttributes,
+ defaultHeadTrackingAvailable
+ )
override suspend fun isSpatialAudioAvailableForDevice(
audioDeviceAttributes: AudioDeviceAttributes
@@ -77,7 +81,10 @@
spatialAudioAvailabilityByDevice[audioDeviceAttributes] = isAvailable
}
- fun setIsHeadTrackingAvailable(isAvailable: Boolean) {
- mutableHeadTrackingAvailable.value = isAvailable
+ fun setIsHeadTrackingAvailable(
+ audioDeviceAttributes: AudioDeviceAttributes,
+ isAvailable: Boolean,
+ ) {
+ headTrackingAvailabilityByDevice[audioDeviceAttributes] = isAvailable
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 4fc65bf..be2ad21 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -1601,6 +1601,9 @@
+ " pointers down.");
return;
}
+ if (Flags.resetHoverEventTimerOnActionUp() && mEvents.size() == 0) {
+ return;
+ }
// Send an accessibility event to announce the touch exploration start.
mDispatcher.sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_START);
if (isSendMotionEventsEnabled()) {
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index 6e98e68..3e68920 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -24,7 +24,6 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
@@ -32,7 +31,6 @@
import android.os.ParcelFileDescriptor;
import android.util.Slog;
-import com.android.server.LocalServices;
import com.android.server.backup.utils.BackupEligibilityRules;
import java.io.BufferedInputStream;
@@ -49,16 +47,14 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Objects;
import java.util.Set;
/**
- * We back up the signatures of each package so that during a system restore,
- * we can verify that the app whose data we think we have matches the app
- * actually resident on the device.
+ * We back up the signatures of each package so that during a system restore, we can verify that the
+ * app whose data we think we have matches the app actually resident on the device.
*
- * Since the Package Manager isn't a proper "application" we just provide a
- * direct IBackupAgent implementation and hand-construct it at need.
+ * <p>Since the Package Manager isn't a proper "application" we just provide a direct IBackupAgent
+ * implementation and hand-construct it at need.
*/
public class PackageManagerBackupAgent extends BackupAgent {
private static final String TAG = "PMBA";
@@ -134,8 +130,8 @@
init(packageMgr, packages, userId);
}
- public PackageManagerBackupAgent(PackageManager packageMgr, int userId,
- BackupEligibilityRules backupEligibilityRules) {
+ public PackageManagerBackupAgent(
+ PackageManager packageMgr, int userId, BackupEligibilityRules backupEligibilityRules) {
init(packageMgr, null, userId);
evaluateStorablePackages(backupEligibilityRules);
@@ -159,12 +155,12 @@
}
/** Gets all packages installed on user {@code userId} eligible for backup. */
- public static List<PackageInfo> getStorableApplications(PackageManager pm, int userId,
- BackupEligibilityRules backupEligibilityRules) {
+ public static List<PackageInfo> getStorableApplications(
+ PackageManager pm, int userId, BackupEligibilityRules backupEligibilityRules) {
List<PackageInfo> pkgs =
pm.getInstalledPackagesAsUser(PackageManager.GET_SIGNING_CERTIFICATES, userId);
int N = pkgs.size();
- for (int a = N-1; a >= 0; a--) {
+ for (int a = N - 1; a >= 0; a--) {
PackageInfo pkg = pkgs.get(a);
if (!backupEligibilityRules.appIsEligibleForBackup(pkg.applicationInfo)) {
pkgs.remove(a);
@@ -204,12 +200,14 @@
return mRestoredSignatures.keySet();
}
- // The backed up data is the signature block for each app, keyed by the package name.
- public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
- ParcelFileDescriptor newState) {
+ @Override
+ public void onBackup(
+ ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) {
if (DEBUG) Slog.v(TAG, "onBackup()");
- ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(); // we'll reuse these
+ // The backed up data is the signature block for each app, keyed by the package name.
+
+ ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(); // we'll reuse these
DataOutputStream outputBufferStream = new DataOutputStream(outputBuffer);
parseStateFile(oldState);
@@ -218,8 +216,13 @@
// "already backed up" map built by parseStateFile().
if (mStoredIncrementalVersion == null
|| !mStoredIncrementalVersion.equals(Build.VERSION.INCREMENTAL)) {
- Slog.i(TAG, "Previous metadata " + mStoredIncrementalVersion + " mismatch vs "
- + Build.VERSION.INCREMENTAL + " - rewriting");
+ Slog.i(
+ TAG,
+ "Previous metadata "
+ + mStoredIncrementalVersion
+ + " mismatch vs "
+ + Build.VERSION.INCREMENTAL
+ + " - rewriting");
mExisting.clear();
}
@@ -271,8 +274,9 @@
} else {
PackageInfo info = null;
try {
- info = mPackageManager.getPackageInfoAsUser(packName,
- PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
+ info =
+ mPackageManager.getPackageInfoAsUser(
+ packName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
} catch (NameNotFoundException e) {
// Weird; we just found it, and now are told it doesn't exist.
// Treat it as having been removed from the device.
@@ -294,8 +298,11 @@
SigningInfo signingInfo = info.signingInfo;
if (signingInfo == null) {
- Slog.w(TAG, "Not backing up package " + packName
- + " since it appears to have no signatures.");
+ Slog.w(
+ TAG,
+ "Not backing up package "
+ + packName
+ + " since it appears to have no signatures.");
continue;
}
@@ -317,15 +324,20 @@
}
// retrieve the newest sigs to back up
Signature[] infoSignatures = signingInfo.getApkContentsSigners();
- writeSignatureHashArray(outputBufferStream,
- BackupUtils.hashSignatureArray(infoSignatures));
+ writeSignatureHashArray(
+ outputBufferStream, BackupUtils.hashSignatureArray(infoSignatures));
if (DEBUG) {
- Slog.v(TAG, "+ writing metadata for " + packName
- + " version=" + info.getLongVersionCode()
- + " entityLen=" + outputBuffer.size());
+ Slog.v(
+ TAG,
+ "+ writing metadata for "
+ + packName
+ + " version="
+ + info.getLongVersionCode()
+ + " entityLen="
+ + outputBuffer.size());
}
-
+
// Now we can write the backup entity for this package
writeEntity(data, packName, outputBuffer.toByteArray());
}
@@ -363,13 +375,15 @@
data.writeEntityData(bytes, bytes.length);
}
- // "Restore" here is a misnomer. What we're really doing is reading back the
- // set of app signatures associated with each backed-up app in this restore
- // image. We'll use those later to determine what we can legitimately restore.
+ @Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
if (DEBUG) Slog.v(TAG, "onRestore()");
+ // "Restore" here is a misnomer. What we're really doing is reading back the
+ // set of app signatures associated with each backed-up app in this restore
+ // image. We'll use those later to determine what we can legitimately restore.
+
// we expect the ANCESTRAL_RECORD_KEY ("@ancestral_record@") to always come first in the
// restore set - based on that value we use different mechanisms to consume the data;
// if the ANCESTRAL_RECORD_KEY is missing in the restore set, it means that the data is
@@ -380,8 +394,10 @@
RestoreDataConsumer consumer = getRestoreDataConsumer(ancestralRecordVersion);
if (consumer == null) {
- Slog.w(TAG, "Ancestral restore set version is unknown"
- + " to this Android version; not restoring");
+ Slog.w(
+ TAG,
+ "Ancestral restore set version is unknown"
+ + " to this Android version; not restoring");
return;
} else {
consumer.consumeRestoreData(data);
@@ -443,9 +459,9 @@
Slog.w(TAG, "Read empty signature block");
return null;
}
-
+
if (DEBUG) Slog.v(TAG, " ... unflatten read " + num);
-
+
// Sensical?
if (num > 20) {
Slog.e(TAG, "Suspiciously large sig count in restore data; aborting");
@@ -506,8 +522,11 @@
if (pkg.equals(STATE_FILE_HEADER)) {
int stateVersion = in.readInt();
if (stateVersion > STATE_FILE_VERSION) {
- Slog.w(TAG, "Unsupported state file version " + stateVersion
- + ", redoing from start");
+ Slog.w(
+ TAG,
+ "Unsupported state file version "
+ + stateVersion
+ + ", redoing from start");
return;
}
pkg = in.readUTF();
@@ -640,10 +659,17 @@
mStoredIncrementalVersion = inputBufferStream.readUTF();
mHasMetadata = true;
if (DEBUG) {
- Slog.i(TAG, "Restore set version " + storedSystemVersion
- + " is compatible with OS version " + Build.VERSION.SDK_INT
- + " (" + mStoredIncrementalVersion + " vs "
- + Build.VERSION.INCREMENTAL + ")");
+ Slog.i(
+ TAG,
+ "Restore set version "
+ + storedSystemVersion
+ + " is compatible with OS version "
+ + Build.VERSION.SDK_INT
+ + " ("
+ + mStoredIncrementalVersion
+ + " vs "
+ + Build.VERSION.INCREMENTAL
+ + ")");
}
} else if (key.equals(DEFAULT_HOME_KEY)) {
String cn = inputBufferStream.readUTF();
@@ -652,10 +678,16 @@
mRestoredHomeInstaller = inputBufferStream.readUTF();
mRestoredHomeSigHashes = readSignatureHashArray(inputBufferStream);
if (DEBUG) {
- Slog.i(TAG, " read preferred home app " + mRestoredHome
- + " version=" + mRestoredHomeVersion
- + " installer=" + mRestoredHomeInstaller
- + " sig=" + mRestoredHomeSigHashes);
+ Slog.i(
+ TAG,
+ " read preferred home app "
+ + mRestoredHome
+ + " version="
+ + mRestoredHomeVersion
+ + " installer="
+ + mRestoredHomeInstaller
+ + " sig="
+ + mRestoredHomeSigHashes);
}
} else {
// it's a file metadata record
@@ -668,14 +700,24 @@
}
ArrayList<byte[]> sigs = readSignatureHashArray(inputBufferStream);
if (DEBUG) {
- Slog.i(TAG, " read metadata for " + key
- + " dataSize=" + dataSize
- + " versionCode=" + versionCode + " sigs=" + sigs);
+ Slog.i(
+ TAG,
+ " read metadata for "
+ + key
+ + " dataSize="
+ + dataSize
+ + " versionCode="
+ + versionCode
+ + " sigs="
+ + sigs);
}
if (sigs == null || sigs.size() == 0) {
- Slog.w(TAG, "Not restoring package " + key
- + " since it appears to have no signatures.");
+ Slog.w(
+ TAG,
+ "Not restoring package "
+ + key
+ + " since it appears to have no signatures.");
continue;
}
@@ -687,8 +729,12 @@
boolean readNextHeader = data.readNextHeader();
if (!readNextHeader) {
- if (DEBUG) Slog.v(TAG, "LegacyRestoreDataConsumer:"
- + " we're done reading all the headers");
+ if (DEBUG) {
+ Slog.v(
+ TAG,
+ "LegacyRestoreDataConsumer:"
+ + " we're done reading all the headers");
+ }
break;
}
}
@@ -725,10 +771,17 @@
mStoredIncrementalVersion = inputBufferStream.readUTF();
mHasMetadata = true;
if (DEBUG) {
- Slog.i(TAG, "Restore set version " + storedSystemVersion
- + " is compatible with OS version " + Build.VERSION.SDK_INT
- + " (" + mStoredIncrementalVersion + " vs "
- + Build.VERSION.INCREMENTAL + ")");
+ Slog.i(
+ TAG,
+ "Restore set version "
+ + storedSystemVersion
+ + " is compatible with OS version "
+ + Build.VERSION.SDK_INT
+ + " ("
+ + mStoredIncrementalVersion
+ + " vs "
+ + Build.VERSION.INCREMENTAL
+ + ")");
}
} else if (key.equals(DEFAULT_HOME_KEY)) {
// Default home app data is no longer backed up by this agent. This code is
@@ -739,10 +792,16 @@
mRestoredHomeInstaller = inputBufferStream.readUTF();
mRestoredHomeSigHashes = readSignatureHashArray(inputBufferStream);
if (DEBUG) {
- Slog.i(TAG, " read preferred home app " + mRestoredHome
- + " version=" + mRestoredHomeVersion
- + " installer=" + mRestoredHomeInstaller
- + " sig=" + mRestoredHomeSigHashes);
+ Slog.i(
+ TAG,
+ " read preferred home app "
+ + mRestoredHome
+ + " version="
+ + mRestoredHomeVersion
+ + " installer="
+ + mRestoredHomeInstaller
+ + " sig="
+ + mRestoredHomeSigHashes);
}
} else {
// it's a file metadata record
@@ -755,14 +814,24 @@
}
ArrayList<byte[]> sigs = readSignatureHashArray(inputBufferStream);
if (DEBUG) {
- Slog.i(TAG, " read metadata for " + key
- + " dataSize=" + dataSize
- + " versionCode=" + versionCode + " sigs=" + sigs);
+ Slog.i(
+ TAG,
+ " read metadata for "
+ + key
+ + " dataSize="
+ + dataSize
+ + " versionCode="
+ + versionCode
+ + " sigs="
+ + sigs);
}
if (sigs == null || sigs.size() == 0) {
- Slog.w(TAG, "Not restoring package " + key
- + " since it appears to have no signatures.");
+ Slog.w(
+ TAG,
+ "Not restoring package "
+ + key
+ + " since it appears to have no signatures.");
continue;
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index e4a1048..3846e98 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -244,13 +244,14 @@
context, mAssociationStore, mObservableUuidStore, mDevicePresenceMonitor,
mPowerManagerInternal);
+ mTransportManager = new CompanionTransportManager(context, mAssociationStore);
+
mAssociationRevokeProcessor = new AssociationRevokeProcessor(this, mAssociationStore,
mPackageManagerInternal, mDevicePresenceMonitor, mCompanionAppController,
- mSystemDataTransferRequestStore);
+ mSystemDataTransferRequestStore, mTransportManager);
loadAssociationsFromDisk();
- mTransportManager = new CompanionTransportManager(context, mAssociationStore);
mSystemDataTransferProcessor = new SystemDataTransferProcessor(this,
mPackageManagerInternal, mAssociationStore,
mSystemDataTransferRequestStore, mTransportManager);
diff --git a/services/companion/java/com/android/server/companion/association/AssociationRevokeProcessor.java b/services/companion/java/com/android/server/companion/association/AssociationRevokeProcessor.java
index 490be0d..d1efbbc 100644
--- a/services/companion/java/com/android/server/companion/association/AssociationRevokeProcessor.java
+++ b/services/companion/java/com/android/server/companion/association/AssociationRevokeProcessor.java
@@ -42,6 +42,7 @@
import com.android.server.companion.CompanionDeviceManagerService;
import com.android.server.companion.datatransfer.SystemDataTransferRequestStore;
import com.android.server.companion.presence.CompanionDevicePresenceMonitor;
+import com.android.server.companion.transport.CompanionTransportManager;
import java.util.HashMap;
import java.util.Map;
@@ -62,6 +63,7 @@
private final @NonNull CompanionDevicePresenceMonitor mDevicePresenceMonitor;
private final @NonNull SystemDataTransferRequestStore mSystemDataTransferRequestStore;
private final @NonNull CompanionApplicationController mCompanionAppController;
+ private final @NonNull CompanionTransportManager mTransportManager;
private final OnPackageVisibilityChangeListener mOnPackageVisibilityChangeListener;
private final ActivityManager mActivityManager;
@@ -97,7 +99,8 @@
@NonNull PackageManagerInternal packageManager,
@NonNull CompanionDevicePresenceMonitor devicePresenceMonitor,
@NonNull CompanionApplicationController applicationController,
- @NonNull SystemDataTransferRequestStore systemDataTransferRequestStore) {
+ @NonNull SystemDataTransferRequestStore systemDataTransferRequestStore,
+ @NonNull CompanionTransportManager companionTransportManager) {
mService = service;
mContext = service.getContext();
mActivityManager = mContext.getSystemService(ActivityManager.class);
@@ -108,6 +111,7 @@
mDevicePresenceMonitor = devicePresenceMonitor;
mCompanionAppController = applicationController;
mSystemDataTransferRequestStore = systemDataTransferRequestStore;
+ mTransportManager = companionTransportManager;
}
/**
@@ -120,6 +124,9 @@
final String packageName = association.getPackageName();
final String deviceProfile = association.getDeviceProfile();
+ // Detach transport if exists
+ mTransportManager.detachSystemDataTransport(packageName, userId, associationId);
+
if (!maybeRemoveRoleHolderForAssociation(association)) {
// Need to remove the app from list of the role holders, but will have to do it later
// (the app is in foreground at the moment).
diff --git a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
index 6dd14ac..793fb7f 100644
--- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
@@ -153,12 +153,12 @@
public void detachSystemDataTransport(String packageName, int userId, int associationId) {
synchronized (mTransports) {
- final Transport transport = mTransports.get(associationId);
- if (transport != null) {
- mTransports.delete(associationId);
- transport.stop();
+ final Transport transport = mTransports.removeReturnOld(associationId);
+ if (transport == null) {
+ return;
}
+ transport.stop();
notifyOnTransportsChanged();
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 45f657d..4ebabdc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1164,7 +1164,8 @@
synchronized (mInternal) {
synchronized (mInternal.mProcLock) {
app.mOptRecord.setFreezeSticky(isSticky);
- mInternal.mOomAdjuster.mCachedAppOptimizer.freezeAppAsyncInternalLSP(app, 0, true);
+ mInternal.mOomAdjuster.mCachedAppOptimizer.freezeAppAsyncInternalLSP(
+ app, 0 /* delayMillis */, true /* force */, false /* immediate */);
}
}
return 0;
diff --git a/services/core/java/com/android/server/am/BroadcastConstants.java b/services/core/java/com/android/server/am/BroadcastConstants.java
index 2fff79b..887915d 100644
--- a/services/core/java/com/android/server/am/BroadcastConstants.java
+++ b/services/core/java/com/android/server/am/BroadcastConstants.java
@@ -296,11 +296,21 @@
* For {@link BroadcastQueueModernImpl}: How frequently we should check for the pending
* cold start validity.
*/
- public long PENDING_COLD_START_CHECK_INTERVAL_MILLIS = 30 * 1000;
+ public long PENDING_COLD_START_CHECK_INTERVAL_MILLIS =
+ DEFAULT_PENDING_COLD_START_CHECK_INTERVAL_MILLIS;
private static final String KEY_PENDING_COLD_START_CHECK_INTERVAL_MILLIS =
"pending_cold_start_check_interval_millis";
private static final long DEFAULT_PENDING_COLD_START_CHECK_INTERVAL_MILLIS = 30_000;
+ /**
+ * For {@link BroadcastQueueModernImpl}: Maximum number of outgoing broadcasts from a
+ * freezable process that will be allowed before killing the process.
+ */
+ public long MAX_FROZEN_OUTGOING_BROADCASTS = DEFAULT_MAX_FROZEN_OUTGOING_BROADCASTS;
+ private static final String KEY_MAX_FROZEN_OUTGOING_BROADCASTS =
+ "max_frozen_outgoing_broadcasts";
+ private static final int DEFAULT_MAX_FROZEN_OUTGOING_BROADCASTS = 32;
+
// Settings override tracking for this instance
private String mSettingsKey;
private SettingsObserver mSettingsObserver;
@@ -453,6 +463,9 @@
PENDING_COLD_START_CHECK_INTERVAL_MILLIS = getDeviceConfigLong(
KEY_PENDING_COLD_START_CHECK_INTERVAL_MILLIS,
DEFAULT_PENDING_COLD_START_CHECK_INTERVAL_MILLIS);
+ MAX_FROZEN_OUTGOING_BROADCASTS = getDeviceConfigInt(
+ KEY_MAX_FROZEN_OUTGOING_BROADCASTS,
+ DEFAULT_MAX_FROZEN_OUTGOING_BROADCASTS);
}
// TODO: migrate BroadcastRecord to accept a BroadcastConstants
@@ -513,6 +526,8 @@
CORE_DEFER_UNTIL_ACTIVE).println();
pw.print(KEY_PENDING_COLD_START_CHECK_INTERVAL_MILLIS,
PENDING_COLD_START_CHECK_INTERVAL_MILLIS).println();
+ pw.print(KEY_MAX_FROZEN_OUTGOING_BROADCASTS,
+ MAX_FROZEN_OUTGOING_BROADCASTS).println();
pw.decreaseIndent();
pw.println();
}
diff --git a/services/core/java/com/android/server/am/BroadcastHistory.java b/services/core/java/com/android/server/am/BroadcastHistory.java
index 34658ca..d6e3d43 100644
--- a/services/core/java/com/android/server/am/BroadcastHistory.java
+++ b/services/core/java/com/android/server/am/BroadcastHistory.java
@@ -50,6 +50,11 @@
}
/**
+ * List of broadcasts in frozen processes that are yet to be enqueued.
+ */
+ private final ArrayList<BroadcastRecord> mFrozenBroadcasts = new ArrayList<>();
+
+ /**
* List of broadcasts which are being delivered or yet to be delivered.
*/
private final ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<>();
@@ -77,7 +82,12 @@
final long[] mSummaryHistoryDispatchTime;
final long[] mSummaryHistoryFinishTime;
+ void onBroadcastFrozenLocked(@NonNull BroadcastRecord r) {
+ mFrozenBroadcasts.add(r);
+ }
+
void onBroadcastEnqueuedLocked(@NonNull BroadcastRecord r) {
+ mFrozenBroadcasts.remove(r);
mPendingBroadcasts.add(r);
}
@@ -101,7 +111,7 @@
mSummaryHistoryNext = ringAdvance(mSummaryHistoryNext, 1, MAX_BROADCAST_SUMMARY_HISTORY);
}
- private final int ringAdvance(int x, final int increment, final int ringSize) {
+ private int ringAdvance(int x, final int increment, final int ringSize) {
x += increment;
if (x < 0) return (ringSize - 1);
else if (x >= ringSize) return 0;
@@ -114,6 +124,10 @@
final BroadcastRecord r = mPendingBroadcasts.get(i);
r.dumpDebug(proto, BroadcastQueueProto.PENDING_BROADCASTS);
}
+ for (int i = 0; i < mFrozenBroadcasts.size(); ++i) {
+ final BroadcastRecord r = mFrozenBroadcasts.get(i);
+ r.dumpDebug(proto, BroadcastQueueProto.FROZEN_BROADCASTS);
+ }
int lastIndex = mHistoryNext;
int ringIndex = lastIndex;
@@ -151,16 +165,8 @@
public boolean dumpLocked(@NonNull PrintWriter pw, @Nullable String dumpPackage,
@NonNull String queueName, @NonNull SimpleDateFormat sdf,
boolean dumpAll, boolean needSep) {
- pw.println(" Pending broadcasts:");
- if (mPendingBroadcasts.isEmpty()) {
- pw.println(" <empty>");
- } else {
- for (int idx = mPendingBroadcasts.size() - 1; idx >= 0; --idx) {
- final BroadcastRecord r = mPendingBroadcasts.get(idx);
- pw.print(" Broadcast #"); pw.print(idx); pw.println(":");
- r.dump(pw, " ", sdf);
- }
- }
+ dumpBroadcastList(pw, sdf, mFrozenBroadcasts, "Frozen");
+ dumpBroadcastList(pw, sdf, mPendingBroadcasts, "Pending");
int i;
boolean printed = false;
@@ -268,4 +274,18 @@
}
return needSep;
}
+
+ private void dumpBroadcastList(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf,
+ @NonNull ArrayList<BroadcastRecord> broadcasts, @NonNull String flavor) {
+ pw.print(" "); pw.print(flavor); pw.println(" broadcasts:");
+ if (broadcasts.isEmpty()) {
+ pw.println(" <empty>");
+ } else {
+ for (int idx = broadcasts.size() - 1; idx >= 0; --idx) {
+ final BroadcastRecord r = broadcasts.get(idx);
+ pw.print(flavor); pw.print(" broadcast #"); pw.print(idx); pw.println(":");
+ r.dump(pw, " ", sdf);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 4a37913..298eb79 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -44,6 +44,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayDeque;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;
@@ -233,6 +234,11 @@
*/
private long mForcedDelayedDurationMs;
+ /**
+ * List of outgoing broadcasts from a freezable process.
+ */
+ private final ArrayList<BroadcastRecord> mOutgoingBroadcasts = new ArrayList<>();
+
public BroadcastProcessQueue(@NonNull BroadcastConstants constants,
@NonNull String processName, int uid) {
this.constants = Objects.requireNonNull(constants);
@@ -250,6 +256,21 @@
}
}
+ public void enqueueOutgoingBroadcast(@NonNull BroadcastRecord record) {
+ mOutgoingBroadcasts.add(record);
+ }
+
+ public int getOutgoingBroadcastCount() {
+ return mOutgoingBroadcasts.size();
+ }
+
+ public void enqueueOutgoingBroadcasts(@NonNull BroadcastRecordConsumer consumer) {
+ for (int i = 0; i < mOutgoingBroadcasts.size(); ++i) {
+ consumer.accept(mOutgoingBroadcasts.get(i));
+ }
+ mOutgoingBroadcasts.clear();
+ }
+
/**
* Enqueue the given broadcast to be dispatched to this process at some
* future point in time. The target receiver is indicated by the given index
@@ -386,8 +407,8 @@
}
/**
- * Functional interface that tests a {@link BroadcastRecord} that has been
- * previously enqueued in {@link BroadcastProcessQueue}.
+ * Functional interface that tests a {@link BroadcastRecord} and an index in the
+ * {@link BroadcastRecord} that has been previously enqueued in {@link BroadcastProcessQueue}.
*/
@FunctionalInterface
public interface BroadcastPredicate {
@@ -395,8 +416,8 @@
}
/**
- * Functional interface that consumes a {@link BroadcastRecord} that has
- * been previously enqueued in {@link BroadcastProcessQueue}.
+ * Functional interface that consumes a {@link BroadcastRecord} and an index in the
+ * {@link BroadcastRecord} that has been previously enqueued in {@link BroadcastProcessQueue}.
*/
@FunctionalInterface
public interface BroadcastConsumer {
@@ -404,6 +425,15 @@
}
/**
+ * Functional interface that consumes a {@link BroadcastRecord} that has
+ * been previously enqueued in {@link BroadcastProcessQueue}.
+ */
+ @FunctionalInterface
+ public interface BroadcastRecordConsumer {
+ void accept(@NonNull BroadcastRecord r);
+ }
+
+ /**
* Invoke given consumer for any broadcasts matching given predicate. If
* requested, matching broadcasts will also be removed from this queue.
* <p>
@@ -774,6 +804,10 @@
return mActiveIndex;
}
+ public boolean isOutgoingEmpty() {
+ return mOutgoingBroadcasts.isEmpty();
+ }
+
public boolean isEmpty() {
return mPending.isEmpty() && mPendingUrgent.isEmpty() && mPendingOffload.isEmpty();
}
@@ -1443,7 +1477,7 @@
@NeverCompile
public void dumpLocked(@UptimeMillisLong long now, @NonNull IndentingPrintWriter pw) {
- if ((mActive == null) && isEmpty()) return;
+ if ((mActive == null) && isEmpty() && isOutgoingEmpty()) return;
pw.print(toShortString());
pw.print(" ");
@@ -1454,6 +1488,12 @@
dumpProcessState(pw);
dumpBroadcastCounts(pw);
+ if (!mOutgoingBroadcasts.isEmpty()) {
+ for (int i = 0; i < mOutgoingBroadcasts.size(); ++i) {
+ dumpOutgoingRecord(now, pw, mOutgoingBroadcasts.get(i));
+ }
+ }
+
if (mActive != null) {
dumpRecord("ACTIVE", now, pw, mActive, mActiveIndex);
}
@@ -1525,6 +1565,15 @@
}
@NeverCompile
+ private void dumpOutgoingRecord(@UptimeMillisLong long now,
+ @NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record) {
+ pw.print("OUTGOING ");
+ TimeUtils.formatDuration(record.enqueueTime, now, pw);
+ pw.print(' ');
+ pw.println(record.toShortString());
+ }
+
+ @NeverCompile
private void dumpRecord(@Nullable String flavor, @UptimeMillisLong long now,
@NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record, int recordIndex) {
TimeUtils.formatDuration(record.enqueueTime, now, pw);
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 4422608..569f9ec 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -92,6 +92,7 @@
import com.android.server.LocalServices;
import com.android.server.am.BroadcastProcessQueue.BroadcastConsumer;
import com.android.server.am.BroadcastProcessQueue.BroadcastPredicate;
+import com.android.server.am.BroadcastProcessQueue.BroadcastRecordConsumer;
import com.android.server.am.BroadcastRecord.DeliveryState;
import com.android.server.pm.UserJourneyLogger;
import com.android.server.pm.UserManagerInternal;
@@ -284,6 +285,9 @@
// when the flag is fused on.
private static final int MSG_DELIVERY_TIMEOUT_SOFT = 8;
+ // TODO: Use the trunk stable flag.
+ private static final boolean DEFER_FROZEN_OUTGOING_BCASTS = false;
+
private void enqueueUpdateRunningList() {
mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST);
mLocalHandler.sendEmptyMessage(MSG_UPDATE_RUNNING_LIST);
@@ -332,9 +336,7 @@
return true;
}
case MSG_PROCESS_FREEZABLE_CHANGED: {
- synchronized (mService) {
- refreshProcessQueueLocked((ProcessRecord) msg.obj);
- }
+ handleProcessFreezableChanged((ProcessRecord) msg.obj);
return true;
}
case MSG_UID_STATE_CHANGED: {
@@ -435,7 +437,8 @@
}
// If app isn't running, and there's nothing in the queue, clean up
- if (queue.isEmpty() && !queue.isActive() && !queue.isProcessWarm()) {
+ if (queue.isEmpty() && queue.isOutgoingEmpty() && !queue.isActive()
+ && !queue.isProcessWarm()) {
removeProcessQueue(queue.processName, queue.uid);
}
}
@@ -759,6 +762,21 @@
@Override
public void enqueueBroadcastLocked(@NonNull BroadcastRecord r) {
+ // TODO: Apply delivery group policies and FLAG_REPLACE_PENDING to collapse the
+ // outgoing broadcasts.
+ // TODO: Add traces/logs for the enqueueing outgoing broadcasts logic.
+ if (DEFER_FROZEN_OUTGOING_BCASTS && isProcessFreezable(r.callerApp)) {
+ final BroadcastProcessQueue queue = getOrCreateProcessQueue(
+ r.callerApp.processName, r.callerApp.uid);
+ if (queue.getOutgoingBroadcastCount() >= mConstants.MAX_FROZEN_OUTGOING_BROADCASTS) {
+ // TODO: Kill the process if the outgoing broadcasts count is
+ // beyond a certain limit.
+ }
+ queue.enqueueOutgoingBroadcast(r);
+ mHistory.onBroadcastFrozenLocked(r);
+ mService.mOomAdjuster.mCachedAppOptimizer.freezeAppAsyncImmediateLSP(r.callerApp);
+ return;
+ }
if (DEBUG_BROADCAST) logv("Enqueuing " + r + " for " + r.receivers.size() + " receivers");
final int cookie = traceBegin("enqueueBroadcast");
@@ -1634,6 +1652,8 @@
"mBroadcastConsumerDeferClear");
};
+ final BroadcastRecordConsumer mBroadcastRecordConsumerEnqueue = this::enqueueBroadcastLocked;
+
/**
* Verify that all known {@link #mProcessQueues} are in the state tested by
* the given {@link Predicate}.
@@ -1930,8 +1950,9 @@
}
}
+ @VisibleForTesting
@GuardedBy("mService")
- private boolean isProcessFreezable(@Nullable ProcessRecord app) {
+ boolean isProcessFreezable(@Nullable ProcessRecord app) {
if (app == null) {
return false;
}
@@ -1956,16 +1977,25 @@
enqueueUpdateRunningList();
}
+ private void handleProcessFreezableChanged(@NonNull ProcessRecord app) {
+ synchronized (mService) {
+ final BroadcastProcessQueue queue = getProcessQueue(app.processName, app.uid);
+ if (queue == null || queue.app == null || queue.app.getPid() != app.getPid()) {
+ return;
+ }
+ if (!isProcessFreezable(app)) {
+ queue.enqueueOutgoingBroadcasts(mBroadcastRecordConsumerEnqueue);
+ }
+ refreshProcessQueueLocked(queue);
+ }
+ }
+
/**
* Refresh the process queue corresponding to {@code app} with the latest process state
* so that runnableAt can be updated.
*/
@GuardedBy("mService")
- private void refreshProcessQueueLocked(@NonNull ProcessRecord app) {
- final BroadcastProcessQueue queue = getProcessQueue(app.processName, app.uid);
- if (queue == null || queue.app == null || queue.app.getPid() != app.getPid()) {
- return;
- }
+ private void refreshProcessQueueLocked(@NonNull BroadcastProcessQueue queue) {
setQueueProcess(queue, queue.app);
enqueueUpdateRunningList();
}
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 150f406..0cf5575 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -1415,7 +1415,7 @@
@GuardedBy({"mAm", "mProcLock"})
private void freezeAppAsyncLSP(ProcessRecord app, @UptimeMillisLong long delayMillis) {
- freezeAppAsyncInternalLSP(app, delayMillis, false);
+ freezeAppAsyncInternalLSP(app, delayMillis, false, false);
}
@GuardedBy({"mAm", "mProcLock"})
@@ -1423,11 +1423,25 @@
freezeAppAsyncLSP(app, updateEarliestFreezableTime(app, 0));
}
+ // TODO: Update freezeAppAsyncAtEarliestLSP to actually freeze the app at the earliest
+ // and remove this method.
+ @GuardedBy({"mAm", "mProcLock"})
+ void freezeAppAsyncImmediateLSP(ProcessRecord app) {
+ freezeAppAsyncInternalLSP(app, 0, false, true);
+ }
+
+ // TODO: Update this method to be private and have the existing clients call different methods.
+ // This "internal" method should not be directly triggered by clients outside this class.
@GuardedBy({"mAm", "mProcLock"})
void freezeAppAsyncInternalLSP(ProcessRecord app, @UptimeMillisLong long delayMillis,
- boolean force) {
+ boolean force, boolean immediate) {
final ProcessCachedOptimizerRecord opt = app.mOptRecord;
if (opt.isPendingFreeze()) {
+ if (immediate) {
+ mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);
+ mFreezeHandler.sendMessage(mFreezeHandler.obtainMessage(
+ SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app));
+ }
// Skip redundant DO_FREEZE message
return;
}
@@ -2210,6 +2224,9 @@
case SET_FROZEN_PROCESS_MSG: {
ProcessRecord proc = (ProcessRecord) msg.obj;
synchronized (mAm) {
+ if (!proc.mOptRecord.isPendingFreeze()) {
+ return;
+ }
freezeProcess(proc);
}
if (proc.mOptRecord.isFrozen()) {
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index b2a738f..3d95fee 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -403,15 +403,14 @@
brightnessEvent.setRecommendedBrightness(mScreenAutoBrightness);
brightnessEvent.setFlags(brightnessEvent.getFlags()
| (!mAmbientLuxValid ? BrightnessEvent.FLAG_INVALID_LUX : 0)
- | (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE
- ? BrightnessEvent.FLAG_DOZE_SCALE : 0));
+ | (shouldApplyDozeScaleFactor() ? BrightnessEvent.FLAG_DOZE_SCALE : 0));
brightnessEvent.setAutoBrightnessMode(getMode());
}
if (!mAmbientLuxValid) {
return PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
- if (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE) {
+ if (shouldApplyDozeScaleFactor()) {
return mScreenAutoBrightness * mDozeScaleFactor;
}
return mScreenAutoBrightness;
@@ -434,7 +433,7 @@
float brightness = mCurrentBrightnessMapper.getBrightness(mLastObservedLux,
mForegroundAppPackageName, mForegroundAppCategory);
- if (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE) {
+ if (shouldApplyDozeScaleFactor()) {
brightness *= mDozeScaleFactor;
}
@@ -443,8 +442,7 @@
brightnessEvent.setRecommendedBrightness(brightness);
brightnessEvent.setFlags(brightnessEvent.getFlags()
| (mLastObservedLux == INVALID_LUX ? BrightnessEvent.FLAG_INVALID_LUX : 0)
- | (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE
- ? BrightnessEvent.FLAG_DOZE_SCALE : 0));
+ | (shouldApplyDozeScaleFactor() ? BrightnessEvent.FLAG_DOZE_SCALE : 0));
brightnessEvent.setAutoBrightnessMode(getMode());
}
return brightness;
@@ -1263,6 +1261,12 @@
}
}
+ private boolean shouldApplyDozeScaleFactor() {
+ // Don't apply the doze scale factor if we have a designated brightness curve for doze
+ return mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE
+ && getMode() != AUTO_BRIGHTNESS_MODE_DOZE;
+ }
+
private class ShortTermModel {
// When the short term model is invalidated, we don't necessarily reset it (i.e. clear the
// user's adjustment) immediately, but wait for a drastic enough change in the ambient
diff --git a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
index 91e560e..b1defe9 100644
--- a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
+++ b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
@@ -113,4 +113,14 @@
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
+
+ @Override
+ public float getBrightness() {
+ return mDisplayPowerController.getScreenBrightnessSetting();
+ }
+
+ @Override
+ public float getDozeBrightness() {
+ return mDisplayPowerController.getDozeBrightnessForOffload();
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 7f014f6..77a43d0 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -487,6 +487,9 @@
private DisplayOffloadSession mDisplayOffloadSession;
+ // Used to scale the brightness in doze mode
+ private float mDozeScaleFactor;
+
/**
* Creates the display power controller.
*/
@@ -547,6 +550,9 @@
loadBrightnessRampRates();
mSkipScreenOnBrightnessRamp = resources.getBoolean(
R.bool.config_skipScreenOnBrightnessRamp);
+ mDozeScaleFactor = context.getResources().getFraction(
+ R.fraction.config_screenAutoBrightnessDozeScaleFactor,
+ 1, 1);
Runnable modeChangeCallback = () -> {
sendUpdatePowerState();
@@ -1042,10 +1048,6 @@
}
if (defaultModeBrightnessMapper != null) {
- final float dozeScaleFactor = context.getResources().getFraction(
- R.fraction.config_screenAutoBrightnessDozeScaleFactor,
- 1, 1);
-
// Ambient Lux - Active Mode Brightness Thresholds
float[] ambientBrighteningThresholds =
mDisplayDeviceConfig.getAmbientBrighteningPercentages();
@@ -1156,7 +1158,7 @@
mAutomaticBrightnessController = mInjector.getAutomaticBrightnessController(
this, handler.getLooper(), mSensorManager, mLightSensor,
brightnessMappers, lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN,
- PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate,
+ PowerManager.BRIGHTNESS_MAX, mDozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
brighteningLightDebounceIdle, darkeningLightDebounceIdle,
autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
@@ -1473,17 +1475,22 @@
mAutomaticBrightnessStrategy.setAutoBrightnessApplied(false);
}
- // If there's an offload session and auto-brightness is on, we need to set the initial doze
- // brightness using the doze auto-brightness curve before the offload session starts
- // controlling the brightness.
- if (Float.isNaN(brightnessState) && mFlags.areAutoBrightnessModesEnabled()
- && mFlags.isDisplayOffloadEnabled()
- && mPowerRequest.policy == POLICY_DOZE
- && mDisplayOffloadSession != null
- && mAutomaticBrightnessController != null
- && mAutomaticBrightnessStrategy.shouldUseAutoBrightness()) {
- rawBrightnessState = mAutomaticBrightnessController
- .getAutomaticScreenBrightnessBasedOnLastObservedLux(mTempBrightnessEvent);
+ // If there's an offload session, we need to set the initial doze brightness before
+ // the offload session starts controlling the brightness.
+ if (Float.isNaN(brightnessState) && mFlags.isDisplayOffloadEnabled()
+ && mPowerRequest.policy == POLICY_DOZE && mDisplayOffloadSession != null) {
+ if (mAutomaticBrightnessController != null
+ && mAutomaticBrightnessStrategy.shouldUseAutoBrightness()) {
+ // Use the auto-brightness curve and the last observed lux
+ rawBrightnessState = mAutomaticBrightnessController
+ .getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ mTempBrightnessEvent);
+ } else {
+ rawBrightnessState = getDozeBrightnessForOffload();
+ mTempBrightnessEvent.setFlags(mTempBrightnessEvent.getFlags()
+ | BrightnessEvent.FLAG_DOZE_SCALE);
+ }
+
if (BrightnessUtils.isValidBrightnessValue(rawBrightnessState)) {
brightnessState = clampScreenBrightness(rawBrightnessState);
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_INITIAL);
@@ -2444,6 +2451,11 @@
}
@Override
+ public float getDozeBrightnessForOffload() {
+ return mDisplayBrightnessController.getCurrentBrightness() * mDozeScaleFactor;
+ }
+
+ @Override
public void setBrightness(float brightness) {
mDisplayBrightnessController.setBrightness(clampScreenBrightness(brightness));
}
@@ -2596,6 +2608,7 @@
}
pw.println(" mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
pw.println(" mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
+ pw.println(" mDozeScaleFactor=" + mDozeScaleFactor);
mHandler.runWithScissors(() -> dumpLocal(pw), 1000);
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
index ecf1635..408d610 100644
--- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
+++ b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
@@ -161,6 +161,11 @@
float getScreenBrightnessSetting();
/**
+ * Gets the brightness value used when the device is in doze
+ */
+ float getDozeBrightnessForOffload();
+
+ /**
* Sets up the temporary brightness for the associated display
*/
void setTemporaryBrightness(float brightness);
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
index 71cc872..03fb147 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
@@ -71,8 +71,14 @@
@Nullable
private final OffloadBrightnessStrategy mOffloadBrightnessStrategy;
+ // A collective representation of all the strategies that the selector is aware of. This is
+ // non null, but the strategies this is tracking can be null
+ @NonNull
private final DisplayBrightnessStrategy[] mDisplayBrightnessStrategies;
+ @NonNull
+ private final DisplayManagerFlags mDisplayManagerFlags;
+
// We take note of the old brightness strategy so that we can know when the strategy changes.
private String mOldBrightnessStrategyName;
@@ -86,6 +92,7 @@
if (injector == null) {
injector = new Injector();
}
+ mDisplayManagerFlags = flags;
mDisplayId = displayId;
mDozeBrightnessStrategy = injector.getDozeBrightnessStrategy();
mScreenOffBrightnessStrategy = injector.getScreenOffBrightnessStrategy();
@@ -139,6 +146,10 @@
displayBrightnessStrategy = mOffloadBrightnessStrategy;
}
+ if (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) {
+ postProcess(constructStrategySelectionNotifyRequest(displayBrightnessStrategy));
+ }
+
if (!mOldBrightnessStrategyName.equals(displayBrightnessStrategy.getName())) {
Slog.i(TAG,
"Changing the DisplayBrightnessStrategy from " + mOldBrightnessStrategyName
@@ -186,13 +197,27 @@
" mAllowAutoBrightnessWhileDozingConfig= "
+ mAllowAutoBrightnessWhileDozingConfig);
IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " ");
- for (DisplayBrightnessStrategy displayBrightnessStrategy: mDisplayBrightnessStrategies) {
+ for (DisplayBrightnessStrategy displayBrightnessStrategy : mDisplayBrightnessStrategies) {
if (displayBrightnessStrategy != null) {
displayBrightnessStrategy.dump(ipw);
}
}
}
+ private StrategySelectionNotifyRequest constructStrategySelectionNotifyRequest(
+ DisplayBrightnessStrategy selectedDisplayBrightnessStrategy) {
+ return new StrategySelectionNotifyRequest(selectedDisplayBrightnessStrategy);
+ }
+
+ private void postProcess(StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ for (DisplayBrightnessStrategy displayBrightnessStrategy : mDisplayBrightnessStrategies) {
+ if (displayBrightnessStrategy != null) {
+ displayBrightnessStrategy.strategySelectionPostProcessor(
+ strategySelectionNotifyRequest);
+ }
+ }
+ }
+
/**
* Validates if the conditions are met to qualify for the DozeBrightnessStrategy.
*/
diff --git a/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java b/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
new file mode 100644
index 0000000..d8bd2e4
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 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.display.brightness;
+
+import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
+
+import java.util.Objects;
+
+/**
+ * A wrapper class to encapsulate the request to notify the strategies about the selection of a
+ * DisplayBrightnessStrategy
+ */
+public final class StrategySelectionNotifyRequest {
+ // The strategy that was selected with the current request
+ private final DisplayBrightnessStrategy mSelectedDisplayBrightnessStrategy;
+
+ public StrategySelectionNotifyRequest(DisplayBrightnessStrategy displayBrightnessStrategy) {
+ mSelectedDisplayBrightnessStrategy = displayBrightnessStrategy;
+ }
+
+ public DisplayBrightnessStrategy getSelectedDisplayBrightnessStrategy() {
+ return mSelectedDisplayBrightnessStrategy;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof StrategySelectionNotifyRequest)) {
+ return false;
+ }
+ StrategySelectionNotifyRequest other = (StrategySelectionNotifyRequest) obj;
+ return other.getSelectedDisplayBrightnessStrategy()
+ == getSelectedDisplayBrightnessStrategy();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSelectedDisplayBrightnessStrategy);
+ }
+}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
index 9ee1d73..11edde9 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
@@ -22,6 +22,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -53,4 +54,10 @@
@Override
public void dump(PrintWriter writer) {}
+
+ @Override
+ public void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ // DO NOTHING
+ }
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
index 1f28eb4..7b49957 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
@@ -20,6 +20,7 @@
import android.hardware.display.DisplayManagerInternal;
import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -48,4 +49,10 @@
* @param writer
*/
void dump(PrintWriter writer);
+
+ /**
+ * Notifies this strategy about the selection of a DisplayBrightnessStrategy
+ */
+ void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest);
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
index 2be7443..5afdc42 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
@@ -21,6 +21,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -46,4 +47,10 @@
@Override
public void dump(PrintWriter writer) {}
+
+ @Override
+ public void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ // DO NOTHING
+ }
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
index 54f9afc..0650c1c 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
@@ -22,6 +22,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -82,4 +83,10 @@
writer.println(" mBrightnessToFollow:" + mBrightnessToFollow);
writer.println(" mBrightnessToFollowSlowChange:" + mBrightnessToFollowSlowChange);
}
+
+ @Override
+ public void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ // DO NOTHING
+ }
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
index 49c3e03..bf37ee0 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
@@ -22,6 +22,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -44,4 +45,10 @@
@Override
public void dump(PrintWriter writer) {}
+
+ @Override
+ public void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ // DO NOTHING
+ }
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java
index 4ffb16b..d2bb1e2 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java
@@ -21,6 +21,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -72,4 +73,10 @@
writer.println("OffloadBrightnessStrategy:");
writer.println(" mOffloadScreenBrightness:" + mOffloadScreenBrightness);
}
+
+ @Override
+ public void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ // DO NOTHING
+ }
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
index 7b651d8..653170c 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
@@ -21,6 +21,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -45,4 +46,10 @@
@Override
public void dump(PrintWriter writer) {}
+
+ @Override
+ public void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ // DO NOTHING
+ }
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
index 201ef41..f0cce23 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
@@ -22,6 +22,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -46,4 +47,10 @@
@Override
public void dump(PrintWriter writer) {}
+
+ @Override
+ public void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ // DO NOTHING
+ }
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
index bbd0c00..91e1d09 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
@@ -22,6 +22,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -73,4 +74,10 @@
writer.println("TemporaryBrightnessStrategy:");
writer.println(" mTemporaryScreenBrightness:" + mTemporaryScreenBrightness);
}
+
+ @Override
+ public void strategySelectionPostProcessor(
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
+ // DO NOTHING
+ }
}
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index 516d4b1..3c98ee4 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -126,6 +126,13 @@
Flags::sensorBasedBrightnessThrottling
);
+
+ private final FlagState mRefactorDisplayPowerController = new FlagState(
+ Flags.FLAG_REFACTOR_DISPLAY_POWER_CONTROLLER,
+ Flags::refactorDisplayPowerController
+ );
+
+
/**
* @return {@code true} if 'port' is allowed in display layout configuration file.
*/
@@ -256,6 +263,10 @@
return mSensorBasedBrightnessThrottling.isEnabled();
}
+ public boolean isRefactorDisplayPowerControllerEnabled() {
+ return mRefactorDisplayPowerController.isEnabled();
+ }
+
/**
* dumps all flagstates
* @param pw printWriter
@@ -280,6 +291,7 @@
pw.println(" " + mFastHdrTransitions);
pw.println(" " + mRefreshRateVotingTelemetry);
pw.println(" " + mSensorBasedBrightnessThrottling);
+ pw.println(" " + mRefactorDisplayPowerController);
}
private static class FlagState {
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index 63ab3a9..3404527 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -192,3 +192,11 @@
bug: "294900859"
is_fixed_read_only: true
}
+
+flag {
+ name: "refactor_display_power_controller"
+ namespace: "display_manager"
+ description: "Feature flag for refactoring the DisplayPowerController and associated components"
+ bug: "294444204"
+ is_fixed_read_only: true
+}
diff --git a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java
new file mode 100644
index 0000000..c7b60da
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeMapRepository.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 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.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.pm.UserInfo;
+import android.os.Handler;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+
+/**
+ * Provides accesses to per-user additional {@link android.view.inputmethod.InputMethodSubtype}
+ * persistent storages.
+ */
+final class AdditionalSubtypeMapRepository {
+ @GuardedBy("ImfLock.class")
+ @NonNull
+ private static final SparseArray<AdditionalSubtypeMap> sPerUserMap = new SparseArray<>();
+
+ /**
+ * Not intended to be instantiated.
+ */
+ private AdditionalSubtypeMapRepository() {
+ }
+
+ @NonNull
+ @GuardedBy("ImfLock.class")
+ static AdditionalSubtypeMap get(@UserIdInt int userId) {
+ final AdditionalSubtypeMap map = sPerUserMap.get(userId);
+ if (map != null) {
+ return map;
+ }
+ final AdditionalSubtypeMap newMap = AdditionalSubtypeUtils.load(userId);
+ sPerUserMap.put(userId, newMap);
+ return newMap;
+ }
+
+ @GuardedBy("ImfLock.class")
+ static void putAndSave(@UserIdInt int userId, @NonNull AdditionalSubtypeMap map,
+ @NonNull InputMethodMap inputMethodMap) {
+ final AdditionalSubtypeMap previous = sPerUserMap.get(userId);
+ if (previous == map) {
+ return;
+ }
+ sPerUserMap.put(userId, map);
+ // TODO: Offload this to a background thread.
+ // TODO: Skip if the previous data is exactly the same as new one.
+ AdditionalSubtypeUtils.save(map, inputMethodMap, userId);
+ }
+
+ static void initialize(@NonNull Handler handler) {
+ final UserManagerInternal userManagerInternal =
+ LocalServices.getService(UserManagerInternal.class);
+ handler.post(() -> {
+ userManagerInternal.addUserLifecycleListener(
+ new UserManagerInternal.UserLifecycleListener() {
+ @Override
+ public void onUserCreated(UserInfo user, @Nullable Object token) {
+ final int userId = user.id;
+ handler.post(() -> {
+ synchronized (ImfLock.class) {
+ if (!sPerUserMap.contains(userId)) {
+ sPerUserMap.put(userId,
+ AdditionalSubtypeUtils.load(userId));
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onUserRemoved(UserInfo user) {
+ final int userId = user.id;
+ handler.post(() -> {
+ synchronized (ImfLock.class) {
+ sPerUserMap.remove(userId);
+ }
+ });
+ }
+ });
+ synchronized (ImfLock.class) {
+ for (int userId : userManagerInternal.getUserIds()) {
+ sPerUserMap.put(userId, AdditionalSubtypeUtils.load(userId));
+ }
+ }
+ });
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 2205986..d13b28f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -192,7 +192,9 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
import java.security.InvalidParameterException;
import java.time.Instant;
import java.time.ZoneId;
@@ -230,6 +232,16 @@
int FAILURE = -1;
}
+ /**
+ * Indicates that the annotated field is not yet ready for concurrent multi-user support.
+ *
+ * <p>See b/305849394 for details.</p>
+ */
+ @Retention(SOURCE)
+ @Target({ElementType.FIELD})
+ private @interface MultiUserUnawareField {
+ }
+
private static final int MSG_SHOW_IM_SUBTYPE_PICKER = 1;
private static final int MSG_HIDE_ALL_INPUT_METHODS = 1035;
@@ -279,7 +291,9 @@
final Resources mRes;
private final Handler mHandler;
@NonNull
+ @MultiUserUnawareField
private InputMethodSettings mSettings;
+ @MultiUserUnawareField
final SettingsObserver mSettingsObserver;
final WindowManagerInternal mWindowManagerInternal;
private final ActivityManagerInternal mActivityManagerInternal;
@@ -288,15 +302,16 @@
final ImePlatformCompatUtils mImePlatformCompatUtils;
final InputMethodDeviceConfigs mInputMethodDeviceConfigs;
- @GuardedBy("ImfLock.class")
- @NonNull
- private AdditionalSubtypeMap mAdditionalSubtypeMap = AdditionalSubtypeMap.EMPTY_MAP;
private final UserManagerInternal mUserManagerInternal;
+ @MultiUserUnawareField
private final InputMethodMenuController mMenuController;
+ @MultiUserUnawareField
@NonNull private final InputMethodBindingController mBindingController;
+ @MultiUserUnawareField
@NonNull private final AutofillSuggestionsController mAutofillController;
@GuardedBy("ImfLock.class")
+ @MultiUserUnawareField
@NonNull private final ImeVisibilityStateComputer mVisibilityStateComputer;
@GuardedBy("ImfLock.class")
@@ -315,13 +330,16 @@
// Mapping from deviceId to the device-specific imeId for that device.
@GuardedBy("ImfLock.class")
+ @MultiUserUnawareField
private final SparseArray<String> mVirtualDeviceMethodMap = new SparseArray<>();
// TODO: Instantiate mSwitchingController for each user.
@NonNull
+ @MultiUserUnawareField
private InputMethodSubtypeSwitchingController mSwitchingController;
// TODO: Instantiate mHardwareKeyboardShortcutController for each user.
@NonNull
+ @MultiUserUnawareField
private HardwareKeyboardShortcutController mHardwareKeyboardShortcutController;
/**
@@ -339,23 +357,29 @@
}
@GuardedBy("ImfLock.class")
+ @MultiUserUnawareField
private int mDisplayIdToShowIme = INVALID_DISPLAY;
@GuardedBy("ImfLock.class")
+ @MultiUserUnawareField
private int mDeviceIdToShowIme = DEVICE_ID_DEFAULT;
@Nullable private StatusBarManagerInternal mStatusBarManagerInternal;
private boolean mShowOngoingImeSwitcherForPhones;
@GuardedBy("ImfLock.class")
+ @MultiUserUnawareField
private final HandwritingModeController mHwController;
@GuardedBy("ImfLock.class")
+ @MultiUserUnawareField
private IntArray mStylusIds;
@GuardedBy("ImfLock.class")
@Nullable
+ @MultiUserUnawareField
private OverlayableSystemBooleanResourceWrapper mImeDrawsImeNavBarRes;
@GuardedBy("ImfLock.class")
@Nullable
+ @MultiUserUnawareField
Future<?> mImeDrawsImeNavBarResLazyInitFuture;
static class SessionState {
@@ -420,6 +444,7 @@
/**
* Holds the current IME binding state info.
*/
+ @MultiUserUnawareField
ImeBindingState mImeBindingState;
/**
@@ -486,27 +511,32 @@
* upon reports from the input method. If the window state is already changed before the report
* is handled, this field just keeps the last value.
*/
+ @MultiUserUnawareField
IBinder mLastImeTargetWindow;
/**
* The {@link IRemoteInputConnection} last provided by the current client.
*/
+ @MultiUserUnawareField
IRemoteInputConnection mCurInputConnection;
/**
* The {@link ImeOnBackInvokedDispatcher} last provided by the current client to
* receive {@link android.window.OnBackInvokedCallback}s forwarded from IME.
*/
+ @MultiUserUnawareField
ImeOnBackInvokedDispatcher mCurImeDispatcher;
/**
* The {@link IRemoteAccessibilityInputConnection} last provided by the current client.
*/
+ @MultiUserUnawareField
@Nullable IRemoteAccessibilityInputConnection mCurRemoteAccessibilityInputConnection;
/**
* The {@link EditorInfo} last provided by the current client.
*/
+ @MultiUserUnawareField
@Nullable
EditorInfo mCurEditorInfo;
@@ -527,11 +557,13 @@
/**
* The current subtype of the current input method.
*/
+ @MultiUserUnawareField
private InputMethodSubtype mCurrentSubtype;
/**
* {@code true} if the IME has not been mostly hidden via {@link android.view.InsetsController}
*/
+ @MultiUserUnawareField
private boolean mCurPerceptible;
/**
@@ -548,11 +580,13 @@
* otherwise {@code null}.
*/
@Nullable
+ @MultiUserUnawareField
private ImeTracker.Token mCurStatsToken;
/**
* {@code true} if the current input method is in fullscreen mode.
*/
+ @MultiUserUnawareField
boolean mInFullscreenMode;
/**
@@ -588,6 +622,7 @@
}
@GuardedBy("ImfLock.class")
+ @MultiUserUnawareField
private int mCurTokenDisplayId = INVALID_DISPLAY;
/**
@@ -595,6 +630,7 @@
*/
@GuardedBy("ImfLock.class")
@Nullable
+ @MultiUserUnawareField
private IBinder mCurHostInputToken;
/**
@@ -633,25 +669,31 @@
/**
* Have we called mCurMethod.bindInput()?
*/
+ @MultiUserUnawareField
boolean mBoundToMethod;
/**
* Have we called bindInput() for accessibility services?
*/
+ @MultiUserUnawareField
boolean mBoundToAccessibility;
/**
* Currently enabled session.
*/
@GuardedBy("ImfLock.class")
+ @MultiUserUnawareField
SessionState mEnabledSession;
+ @MultiUserUnawareField
SparseArray<AccessibilitySessionState> mEnabledAccessibilitySessions = new SparseArray<>();
/**
* True if the device is currently interactive with user. The value is true initially.
*/
+ @MultiUserUnawareField
boolean mIsInteractive = true;
+ @MultiUserUnawareField
int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
/**
@@ -675,6 +717,7 @@
* <em>Do not update this value outside of {@link #setImeWindowStatus(IBinder, int, int)} and
* {@link InputMethodBindingController#unbindCurrentMethod()}.</em>
*/
+ @MultiUserUnawareField
int mImeWindowVis;
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
@@ -1310,13 +1353,12 @@
final int userId = getChangingUserId();
synchronized (ImfLock.class) {
final boolean isCurrentUser = (userId == mSettings.getUserId());
- final AdditionalSubtypeMap additionalSubtypeMap;
+ final AdditionalSubtypeMap additionalSubtypeMap =
+ AdditionalSubtypeMapRepository.get(userId);
final InputMethodSettings settings;
if (isCurrentUser) {
- additionalSubtypeMap = mAdditionalSubtypeMap;
settings = mSettings;
} else {
- additionalSubtypeMap = AdditionalSubtypeUtils.load(userId);
settings = queryInputMethodServicesInternal(mContext, userId,
additionalSubtypeMap, DirectBootAwareness.AUTO);
}
@@ -1331,11 +1373,8 @@
final AdditionalSubtypeMap newMap =
additionalSubtypeMap.cloneWithRemoveOrSelf(changedImes);
if (newMap != additionalSubtypeMap) {
- if (isCurrentUser) {
- mAdditionalSubtypeMap = newMap;
- }
- AdditionalSubtypeUtils.save(
- newMap, settings.getMethodMap(), settings.getUserId());
+ AdditionalSubtypeMapRepository.putAndSave(userId, newMap,
+ settings.getMethodMap());
}
if (!changedImes.isEmpty()) {
mChangedPackages.add(packageName);
@@ -1382,13 +1421,12 @@
synchronized (ImfLock.class) {
final int userId = getChangingUserId();
final boolean isCurrentUser = (userId == mSettings.getUserId());
- AdditionalSubtypeMap additionalSubtypeMap;
+ AdditionalSubtypeMap additionalSubtypeMap =
+ AdditionalSubtypeMapRepository.get(userId);
final InputMethodSettings settings;
if (isCurrentUser) {
- additionalSubtypeMap = mAdditionalSubtypeMap;
settings = mSettings;
} else {
- additionalSubtypeMap = AdditionalSubtypeUtils.load(userId);
settings = queryInputMethodServicesInternal(mContext, userId,
additionalSubtypeMap, DirectBootAwareness.AUTO);
}
@@ -1419,11 +1457,8 @@
+ imi.getComponent());
additionalSubtypeMap =
additionalSubtypeMap.cloneWithRemoveOrSelf(imi.getId());
- AdditionalSubtypeUtils.save(additionalSubtypeMap,
- settings.getMethodMap(), userId);
- if (isCurrentUser) {
- mAdditionalSubtypeMap = additionalSubtypeMap;
- }
+ AdditionalSubtypeMapRepository.putAndSave(userId,
+ additionalSubtypeMap, settings.getMethodMap());
}
}
@@ -1515,6 +1550,7 @@
*/
@Nullable
@GuardedBy("ImfLock.class")
+ @MultiUserUnawareField
private UserSwitchHandlerTask mUserSwitchHandlerTask;
/**
@@ -1658,12 +1694,13 @@
mShowOngoingImeSwitcherForPhones = false;
+ AdditionalSubtypeMapRepository.initialize(mHandler);
+
final int userId = mActivityManagerInternal.getCurrentUserId();
// mSettings should be created before buildInputMethodListLocked
mSettings = InputMethodSettings.createEmptyMap(userId);
- mAdditionalSubtypeMap = AdditionalSubtypeUtils.load(userId);
mSwitchingController =
InputMethodSubtypeSwitchingController.createInstanceLocked(context,
mSettings.getMethodMap(), userId);
@@ -1808,8 +1845,6 @@
mSettingsObserver.registerContentObserverLocked(newUserId);
mSettings = InputMethodSettings.createEmptyMap(newUserId);
- // Additional subtypes should be reset when the user is changed
- mAdditionalSubtypeMap = AdditionalSubtypeUtils.load(newUserId);
final String defaultImiId = mSettings.getSelectedInputMethod();
if (DEBUG) {
@@ -1897,7 +1932,7 @@
}
}, "Lazily initialize IMMS#mImeDrawsImeNavBarRes");
- mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
+ mMyPackageMonitor.register(mContext, UserHandle.ALL, mHandler);
mSettingsObserver.registerContentObserverLocked(currentUserId);
final IntentFilter broadcastFilterForAllUsers = new IntentFilter();
@@ -2017,7 +2052,7 @@
}
//TODO(b/197848765): This can be optimized by caching multi-user methodMaps/methodList.
//TODO(b/210039666): use cache.
- final InputMethodSettings settings = queryMethodMapForUser(userId);
+ final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
final InputMethodInfo imi = settings.getMethodMap().get(
settings.getSelectedInputMethod());
return imi != null && imi.supportsStylusHandwriting()
@@ -2045,7 +2080,8 @@
&& directBootAwareness == DirectBootAwareness.AUTO) {
settings = mSettings;
} else {
- final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId);
+ final AdditionalSubtypeMap additionalSubtypeMap =
+ AdditionalSubtypeMapRepository.get(userId);
settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
directBootAwareness);
}
@@ -2066,7 +2102,7 @@
methodList = mSettings.getEnabledInputMethodList();
settings = mSettings;
} else {
- settings = queryMethodMapForUser(userId);
+ settings = queryMethodMapForUserLocked(userId);
methodList = settings.getEnabledInputMethodList();
}
// filter caller's access to input methods
@@ -2141,7 +2177,7 @@
return mSettings.getEnabledInputMethodSubtypeList(
imi, allowsImplicitlyEnabledSubtypes);
}
- final InputMethodSettings settings = queryMethodMapForUser(userId);
+ final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
final InputMethodInfo imi = settings.getMethodMap().get(imiId);
if (imi == null) {
return Collections.emptyList();
@@ -4307,7 +4343,7 @@
return mSettings.getLastInputMethodSubtype();
}
- final InputMethodSettings settings = queryMethodMapForUser(userId);
+ final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
return settings.getLastInputMethodSubtype();
}
}
@@ -4338,33 +4374,25 @@
return;
}
- if (mSettings.getUserId() == userId) {
- final var newAdditionalSubtypeMap = mSettings.getNewAdditionalSubtypeMap(
- imiId, toBeAdded, mAdditionalSubtypeMap, mPackageManagerInternal,
- callingUid);
- if (mAdditionalSubtypeMap == newAdditionalSubtypeMap) {
- return;
- }
- AdditionalSubtypeUtils.save(newAdditionalSubtypeMap, mSettings.getMethodMap(),
- mSettings.getUserId());
- mAdditionalSubtypeMap = newAdditionalSubtypeMap;
- final long ident = Binder.clearCallingIdentity();
- try {
- buildInputMethodListLocked(false /* resetDefaultEnabledIme */);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- return;
- }
-
- final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId);
- final InputMethodSettings settings = queryInputMethodServicesInternal(mContext, userId,
- additionalSubtypeMap, DirectBootAwareness.AUTO);
+ final var additionalSubtypeMap = AdditionalSubtypeMapRepository.get(userId);
+ final boolean isCurrentUser = (mSettings.getUserId() == userId);
+ final InputMethodSettings settings = isCurrentUser
+ ? mSettings
+ : queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
+ DirectBootAwareness.AUTO);
final var newAdditionalSubtypeMap = settings.getNewAdditionalSubtypeMap(
imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid);
if (additionalSubtypeMap != newAdditionalSubtypeMap) {
- AdditionalSubtypeUtils.save(newAdditionalSubtypeMap, settings.getMethodMap(),
- settings.getUserId());
+ AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap,
+ settings.getMethodMap());
+ if (isCurrentUser) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ buildInputMethodListLocked(false /* resetDefaultEnabledIme */);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
}
}
}
@@ -4391,7 +4419,7 @@
synchronized (ImfLock.class) {
final boolean currentUser = (mSettings.getUserId() == userId);
final InputMethodSettings settings = currentUser
- ? mSettings : queryMethodMapForUser(userId);
+ ? mSettings : queryMethodMapForUserLocked(userId);
if (!settings.setEnabledInputMethodSubtypes(imeId, subtypeHashCodes)) {
return;
}
@@ -5293,7 +5321,8 @@
mMyPackageMonitor.clearKnownImePackageNamesLocked();
mSettings = queryInputMethodServicesInternal(mContext, mSettings.getUserId(),
- mAdditionalSubtypeMap, DirectBootAwareness.AUTO);
+ AdditionalSubtypeMapRepository.get(mSettings.getUserId()),
+ DirectBootAwareness.AUTO);
// Construct the set of possible IME packages for onPackageChanged() to avoid false
// negatives when the package state remains to be the same but only the component state is
@@ -5565,7 +5594,7 @@
return getCurrentInputMethodSubtypeLocked();
}
- final InputMethodSettings settings = queryMethodMapForUser(userId);
+ final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
return settings.getCurrentInputMethodSubtypeForNonCurrentUsers();
}
}
@@ -5632,15 +5661,18 @@
if (userId == mSettings.getUserId()) {
settings = mSettings;
} else {
- final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId);
+ final AdditionalSubtypeMap additionalSubtypeMap =
+ AdditionalSubtypeMapRepository.get(userId);
settings = queryInputMethodServicesInternal(mContext, userId,
additionalSubtypeMap, DirectBootAwareness.AUTO);
}
return settings.getMethodMap().get(settings.getSelectedInputMethod());
}
- private InputMethodSettings queryMethodMapForUser(@UserIdInt int userId) {
- final AdditionalSubtypeMap additionalSubtypeMap = AdditionalSubtypeUtils.load(userId);
+ @GuardedBy("ImfLock.class")
+ private InputMethodSettings queryMethodMapForUserLocked(@UserIdInt int userId) {
+ final AdditionalSubtypeMap additionalSubtypeMap =
+ AdditionalSubtypeMapRepository.get(userId);
return queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
DirectBootAwareness.AUTO);
}
@@ -5656,7 +5688,7 @@
setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID);
return true;
}
- final InputMethodSettings settings = queryMethodMapForUser(userId);
+ final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
if (!settings.getMethodMap().containsKey(imeId)
|| !settings.getEnabledInputMethodList().contains(
settings.getMethodMap().get(imeId))) {
@@ -5796,7 +5828,7 @@
setInputMethodEnabledLocked(imeId, enabled);
return true;
}
- final InputMethodSettings settings = queryMethodMapForUser(userId);
+ final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
if (!settings.getMethodMap().containsKey(imeId)) {
return false; // IME is not found.
}
@@ -6550,7 +6582,7 @@
previouslyEnabled = setInputMethodEnabledLocked(imeId, enabled);
}
} else {
- final InputMethodSettings settings = queryMethodMapForUser(userId);
+ final InputMethodSettings settings = queryMethodMapForUserLocked(userId);
if (enabled) {
if (!settings.getMethodMap().containsKey(imeId)) {
failedToEnableUnknownIme = true;
@@ -6685,7 +6717,7 @@
nextEnabledImes = mSettings.getEnabledInputMethodList();
} else {
final AdditionalSubtypeMap additionalSubtypeMap =
- AdditionalSubtypeUtils.load(userId);
+ AdditionalSubtypeMapRepository.get(userId);
final InputMethodSettings settings = queryInputMethodServicesInternal(
mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO);
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 3abf3a5..ecfc768 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -50,13 +50,17 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApexStagedEvent;
import android.content.pm.Flags;
+import android.content.pm.IPackageManagerNative;
+import android.content.pm.IStagedApexObserver;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.dex.ArtManager;
import android.os.Binder;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
@@ -1054,6 +1058,10 @@
artManager.scheduleBackgroundDexoptJob();
}
}, new IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+
+ if (Flags.useArtServiceV2()) {
+ StagedApexObserver.registerForStagedApexUpdates(artManager);
+ }
}
/**
@@ -1168,4 +1176,32 @@
&& dexoptOptions.isCompilationEnabled()
&& !isApex;
}
+
+ private static class StagedApexObserver extends IStagedApexObserver.Stub {
+ private final @NonNull ArtManagerLocal mArtManager;
+
+ static void registerForStagedApexUpdates(@NonNull ArtManagerLocal artManager) {
+ IPackageManagerNative packageNative = IPackageManagerNative.Stub.asInterface(
+ ServiceManager.getService("package_native"));
+ if (packageNative == null) {
+ Log.e(TAG, "No IPackageManagerNative");
+ return;
+ }
+
+ try {
+ packageNative.registerStagedApexObserver(new StagedApexObserver(artManager));
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to register staged apex observer", e);
+ }
+ }
+
+ private StagedApexObserver(@NonNull ArtManagerLocal artManager) {
+ mArtManager = artManager;
+ }
+
+ @Override
+ public void onApexStaged(@NonNull ApexStagedEvent event) {
+ mArtManager.onApexStaged(event.stagedApexModuleNames);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fe8030b..7c51707 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -38,7 +38,6 @@
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
-import static android.util.FeatureFlagUtils.SETTINGS_TREAT_PAUSE_AS_QUARANTINE;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME;
@@ -168,7 +167,6 @@
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.ExceptionUtils;
-import android.util.FeatureFlagUtils;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -3208,15 +3206,8 @@
}
if (quarantined) {
- final boolean hasQuarantineAppsPerm = mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.QUARANTINE_APPS) == PERMISSION_GRANTED;
- // TODO: b/305256093 - In order to facilitate testing, temporarily allowing apps
- // with SUSPEND_APPS permission to quarantine apps. Remove this once the testing
- // is done and this is no longer needed.
- if (!hasQuarantineAppsPerm) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS,
- callingMethod);
- }
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.QUARANTINE_APPS,
+ callingMethod);
} else {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS,
callingMethod);
@@ -6287,16 +6278,8 @@
SuspendDialogInfo dialogInfo, int flags, String suspendingPackage,
int suspendingUserId, int targetUserId) {
final int callingUid = Binder.getCallingUid();
- boolean quarantined = false;
- if (Flags.quarantinedEnabled()) {
- if ((flags & PackageManager.FLAG_SUSPEND_QUARANTINED) != 0) {
- quarantined = true;
- } else if (FeatureFlagUtils.isEnabled(mContext,
- SETTINGS_TREAT_PAUSE_AS_QUARANTINE)) {
- final String wellbeingPkg = mContext.getString(R.string.config_systemWellbeing);
- quarantined = suspendingPackage.equals(wellbeingPkg);
- }
- }
+ final boolean quarantined = ((flags & PackageManager.FLAG_SUSPEND_QUARANTINED) != 0)
+ && Flags.quarantinedEnabled();
final Computer snapshot = snapshotComputer();
final UserPackage suspender = UserPackage.of(targetUserId, suspendingPackage);
enforceCanSetPackagesSuspendedAsUser(snapshot, quarantined, suspender, callingUid,
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index 79adcb4..34c90f1 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -349,6 +349,7 @@
}
}
+ userState.mAdServiceMap.clear();
userState.mAdServiceMap = adServiceMap;
}
@@ -988,7 +989,7 @@
return;
}
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
- TvAdServiceState adState = userState.mAdMap.get(serviceId);
+ TvAdServiceState adState = userState.mAdServiceMap.get(serviceId);
if (adState == null) {
Slogf.w(TAG, "Failed to find state for serviceId=" + serviceId);
sendAdSessionTokenToClientLocked(client, serviceId, null, null, seq);
@@ -3031,6 +3032,7 @@
ITvAdService service, IBinder sessionToken, int userId) {
UserState userState = getOrCreateUserStateLocked(userId);
AdSessionState sessionState = userState.mAdSessionStateMap.get(sessionToken);
+
if (DEBUG) {
Slogf.d(TAG, "createAdSessionInternalLocked(iAppServiceId="
+ sessionState.mAdServiceId + ")");
@@ -3300,8 +3302,6 @@
private static final class UserState {
private final int mUserId;
- // A mapping from the TV AD service ID to its TvAdServiceState.
- private Map<String, TvAdServiceState> mAdMap = new HashMap<>();
// A mapping from the name of a TV Interactive App service to its state.
private final Map<ComponentName, AdServiceState> mAdServiceStateMap = new HashMap<>();
// A mapping from the token of a TV Interactive App session to its state.
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index b490f57..6fc9d9a 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -208,6 +208,7 @@
* potentially expensive or resource-linked objects, such as {@link IBinder}.
*/
static final class DebugInfo {
+ final Status mStatus;
final long mCreateTime;
final CallerInfo mCallerInfo;
@Nullable
@@ -220,7 +221,6 @@
private final CombinedVibration mOriginalEffect;
private final int mScaleLevel;
private final float mAdaptiveScale;
- private final Status mStatus;
DebugInfo(Status status, VibrationStats stats, @Nullable CombinedVibration playedEffect,
@Nullable CombinedVibration originalEffect, int scaleLevel,
@@ -253,6 +253,10 @@
+ ", callerInfo: " + mCallerInfo;
}
+ void logMetrics(VibratorFrameworkStatsLogger statsLogger) {
+ statsLogger.logVibrationAdaptiveHapticScale(mCallerInfo.uid, mAdaptiveScale);
+ }
+
/**
* Write this info in a compact way into given {@link PrintWriter}.
*
diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
index f510b4e..f3e226e 100644
--- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
+++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
@@ -40,8 +40,10 @@
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Creates and manages a queue of steps for performing a VibrationEffect, as well as coordinating
@@ -70,6 +72,7 @@
private final DeviceAdapter mDeviceAdapter;
private final VibrationScaler mVibrationScaler;
+ private final VibratorFrameworkStatsLogger mStatsLogger;
// Not guarded by lock because it's mostly used to read immutable fields by this conductor.
// This is only modified here at the prepareToStart method which always runs at the vibration
@@ -103,14 +106,15 @@
private int mSuccessfulVibratorOnSteps;
VibrationStepConductor(HalVibration vib, VibrationSettings vibrationSettings,
- DeviceAdapter deviceAdapter,
- VibrationScaler vibrationScaler,
+ DeviceAdapter deviceAdapter, VibrationScaler vibrationScaler,
+ VibratorFrameworkStatsLogger statsLogger,
CompletableFuture<Void> requestVibrationParamsFuture,
VibrationThread.VibratorManagerHooks vibratorManagerHooks) {
this.mVibration = vib;
this.vibrationSettings = vibrationSettings;
this.mDeviceAdapter = deviceAdapter;
mVibrationScaler = vibrationScaler;
+ mStatsLogger = statsLogger;
mRequestVibrationParamsFuture = requestVibrationParamsFuture;
this.vibratorManagerHooks = vibratorManagerHooks;
this.mSignalVibratorsComplete =
@@ -461,9 +465,19 @@
}
try {
- mRequestVibrationParamsFuture.orTimeout(
+ mRequestVibrationParamsFuture.get(
vibrationSettings.getRequestVibrationParamsTimeoutMs(),
- TimeUnit.MILLISECONDS).get();
+ TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ if (DEBUG) {
+ Slog.d(TAG, "Request for vibration params timed out", e);
+ }
+ mStatsLogger.logVibrationParamRequestTimeout(mVibration.callerInfo.uid);
+ } catch (CancellationException e) {
+ if (DEBUG) {
+ Slog.d(TAG, "Request for vibration params cancelled, maybe superseded or"
+ + " vibrator controller unregistered. Skipping params...", e);
+ }
} catch (Throwable e) {
Slog.w(TAG, "Failed to retrieve vibration params.", e);
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorControlService.java b/services/core/java/com/android/server/vibrator/VibratorControlService.java
index ec3d99b..10317c9 100644
--- a/services/core/java/com/android/server/vibrator/VibratorControlService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorControlService.java
@@ -72,19 +72,21 @@
private final VibrationParamsRecords mVibrationParamsRecords;
private final VibratorControllerHolder mVibratorControllerHolder;
private final VibrationScaler mVibrationScaler;
+ private final VibratorFrameworkStatsLogger mStatsLogger;
private final Object mLock;
private final int[] mRequestVibrationParamsForUsages;
@GuardedBy("mLock")
- private CompletableFuture<Void> mRequestVibrationParamsFuture = null;
- @GuardedBy("mLock")
- private IBinder mRequestVibrationParamsToken;
+ @Nullable
+ private VibrationParamRequest mVibrationParamRequest = null;
VibratorControlService(Context context,
VibratorControllerHolder vibratorControllerHolder, VibrationScaler vibrationScaler,
- VibrationSettings vibrationSettings, Object lock) {
+ VibrationSettings vibrationSettings, VibratorFrameworkStatsLogger statsLogger,
+ Object lock) {
mVibratorControllerHolder = vibratorControllerHolder;
mVibrationScaler = vibrationScaler;
+ mStatsLogger = statsLogger;
mLock = lock;
mRequestVibrationParamsForUsages = vibrationSettings.getRequestVibrationParamsForUsages();
@@ -180,20 +182,25 @@
Objects.requireNonNull(requestToken);
synchronized (mLock) {
- if (mRequestVibrationParamsToken == null) {
+ if (mVibrationParamRequest == null) {
Slog.wtf(TAG,
"New vibration params received but no token was cached in the service. "
+ "New vibration params ignored.");
+ mStatsLogger.logVibrationParamResponseIgnored();
return;
}
- if (!Objects.equals(requestToken, mRequestVibrationParamsToken)) {
+ if (!Objects.equals(requestToken, mVibrationParamRequest.token)) {
Slog.w(TAG,
"New vibration params received but the provided token does not match the "
+ "cached one. New vibration params ignored.");
+ mStatsLogger.logVibrationParamResponseIgnored();
return;
}
+ long latencyMs = SystemClock.uptimeMillis() - mVibrationParamRequest.uptimeMs;
+ mStatsLogger.logVibrationParamRequestLatency(mVibrationParamRequest.uid, latencyMs);
+
updateAdaptiveHapticsScales(result);
endOngoingRequestVibrationParamsLocked(/* wasCancelled= */ false);
recordUpdateVibrationParams(result, /* fromRequest= */ true);
@@ -222,7 +229,7 @@
*/
@Nullable
public CompletableFuture<Void> triggerVibrationParamsRequest(
- @VibrationAttributes.Usage int usage, int timeoutInMillis) {
+ int uid, @VibrationAttributes.Usage int usage, int timeoutInMillis) {
synchronized (mLock) {
IVibratorController vibratorController =
mVibratorControllerHolder.getVibratorController();
@@ -241,16 +248,16 @@
try {
endOngoingRequestVibrationParamsLocked(/* wasCancelled= */ true);
- mRequestVibrationParamsFuture = new CompletableFuture<>();
- mRequestVibrationParamsToken = new Binder();
+ mVibrationParamRequest = new VibrationParamRequest(uid);
vibratorController.requestVibrationParams(vibrationType, timeoutInMillis,
- mRequestVibrationParamsToken);
+ mVibrationParamRequest.token);
+ return mVibrationParamRequest.future;
} catch (RemoteException e) {
Slog.e(TAG, "Failed to request vibration params.", e);
endOngoingRequestVibrationParamsLocked(/* wasCancelled= */ true);
}
- return mRequestVibrationParamsFuture;
+ return null;
}
}
@@ -276,13 +283,13 @@
}
/**
- * Returns the {@link #mRequestVibrationParamsToken} which is used to validate
+ * Returns the binder token which is used to validate
* {@link #onRequestVibrationParamsComplete(IBinder, VibrationParam[])} calls.
*/
@VisibleForTesting
public IBinder getRequestVibrationParamsToken() {
synchronized (mLock) {
- return mRequestVibrationParamsToken;
+ return mVibrationParamRequest == null ? null : mVibrationParamRequest.token;
}
}
@@ -293,7 +300,7 @@
synchronized (mLock) {
isVibratorControllerRegistered =
mVibratorControllerHolder.getVibratorController() != null;
- hasPendingVibrationParamsRequest = mRequestVibrationParamsFuture != null;
+ hasPendingVibrationParamsRequest = mVibrationParamRequest != null;
}
pw.println("VibratorControlService:");
@@ -329,18 +336,10 @@
*/
@GuardedBy("mLock")
private void endOngoingRequestVibrationParamsLocked(boolean wasCancelled) {
- mRequestVibrationParamsToken = null;
- if (mRequestVibrationParamsFuture == null) {
- return;
+ if (mVibrationParamRequest != null) {
+ mVibrationParamRequest.endRequest(wasCancelled);
}
-
- if (wasCancelled) {
- mRequestVibrationParamsFuture.cancel(/* mayInterruptIfRunning= */ true);
- } else {
- mRequestVibrationParamsFuture.complete(null);
- }
-
- mRequestVibrationParamsFuture = null;
+ mVibrationParamRequest = null;
}
private static int mapToAdaptiveVibrationType(@VibrationAttributes.Usage int usage) {
@@ -423,6 +422,7 @@
* @param scale The scaling factor that should be applied to the vibrations.
*/
private void updateAdaptiveHapticsScales(int types, float scale) {
+ mStatsLogger.logVibrationParamScale(scale);
for (int usage : mapFromAdaptiveVibrationTypeToVibrationUsages(types)) {
updateOrRemoveAdaptiveHapticsScale(usage, scale);
}
@@ -504,6 +504,27 @@
}
}
+ /** Represents a request for {@link VibrationParam}. */
+ private static final class VibrationParamRequest {
+ public final CompletableFuture<Void> future = new CompletableFuture<>();
+ public final IBinder token = new Binder();
+ public final int uid;
+ public final long uptimeMs;
+
+ VibrationParamRequest(int uid) {
+ this.uid = uid;
+ uptimeMs = SystemClock.uptimeMillis();
+ }
+
+ public void endRequest(boolean wasCancelled) {
+ if (wasCancelled) {
+ future.cancel(/* mayInterruptIfRunning= */ true);
+ } else {
+ future.complete(null);
+ }
+ }
+ }
+
/**
* Record for a single {@link Vibration.DebugInfo}, that can be grouped by usage and aggregated
* by UID, {@link VibrationAttributes} and {@link VibrationEffect}.
diff --git a/services/core/java/com/android/server/vibrator/VibratorFrameworkStatsLogger.java b/services/core/java/com/android/server/vibrator/VibratorFrameworkStatsLogger.java
index 7e601b6..e9c3894 100644
--- a/services/core/java/com/android/server/vibrator/VibratorFrameworkStatsLogger.java
+++ b/services/core/java/com/android/server/vibrator/VibratorFrameworkStatsLogger.java
@@ -25,6 +25,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.modules.expresslog.Counter;
+import com.android.modules.expresslog.Histogram;
import java.util.ArrayDeque;
import java.util.Queue;
@@ -40,6 +41,23 @@
// Warning about dropping entries after this amount of atoms were dropped by the throttle.
private static final int VIBRATION_REPORTED_WARNING_QUEUE_SIZE = 200;
+ // Latency between 0ms and 99ms, with 100 representing overflow latencies >= 100ms.
+ // Underflow not expected.
+ private static final Histogram sVibrationParamRequestLatencyHistogram = new Histogram(
+ "vibrator.value_vibration_param_request_latency",
+ new Histogram.UniformOptions(20, 0, 100));
+
+ // Scales in [0, 2), with 2 representing overflow scales >= 2.
+ // Underflow expected to represent how many times scales were cleared (set to -1).
+ private static final Histogram sVibrationParamScaleHistogram = new Histogram(
+ "vibrator.value_vibration_param_scale", new Histogram.UniformOptions(20, 0, 2));
+
+ // Scales in [0, 2), with 2 representing overflow scales >= 2.
+ // Underflow not expected.
+ private static final Histogram sAdaptiveHapticScaleHistogram = new Histogram(
+ "vibrator.value_vibration_adaptive_haptic_scale",
+ new Histogram.UniformOptions(20, 0, 2));
+
private final Object mLock = new Object();
private final Handler mHandler;
private final long mVibrationReportedLogIntervalMillis;
@@ -140,6 +158,33 @@
}
}
+ /** Logs adaptive haptic scale value applied to a vibration, only if it's not 1.0. */
+ public void logVibrationAdaptiveHapticScale(int uid, float scale) {
+ if (Float.compare(scale, 1f) != 0) {
+ sAdaptiveHapticScaleHistogram.logSampleWithUid(uid, scale);
+ }
+ }
+
+ /** Logs a vibration param scale value received by the vibrator control service. */
+ public void logVibrationParamScale(float scale) {
+ sVibrationParamScaleHistogram.logSample(scale);
+ }
+
+ /** Logs the latency of a successful vibration params request completed before a vibration. */
+ public void logVibrationParamRequestLatency(int uid, long latencyMs) {
+ sVibrationParamRequestLatencyHistogram.logSampleWithUid(uid, (float) latencyMs);
+ }
+
+ /** Logs a vibration params request timed out before a vibration. */
+ public void logVibrationParamRequestTimeout(int uid) {
+ Counter.logIncrementWithUid("vibrator.value_vibration_param_request_timeout", uid);
+ }
+
+ /** Logs when a response received for a vibration params request is ignored by the service. */
+ public void logVibrationParamResponseIgnored() {
+ Counter.logIncrement("vibrator.value_vibration_param_response_ignored");
+ }
+
/** Logs only if the haptics feedback effect is one of the KEYBOARD_ constants. */
public static void logPerformHapticsFeedbackIfKeyboard(int uid, int hapticsFeedbackEffect) {
boolean isKeyboard;
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index c1bf039..af494a3 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -212,12 +212,13 @@
mContext = context;
mInjector = injector;
mHandler = injector.createHandler(Looper.myLooper());
+ mFrameworkStatsLogger = injector.getFrameworkStatsLogger(mHandler);
mVibrationSettings = new VibrationSettings(mContext, mHandler);
mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings);
mVibratorControlService = new VibratorControlService(mContext,
injector.createVibratorControllerHolder(), mVibrationScaler, mVibrationSettings,
- mLock);
+ mFrameworkStatsLogger, mLock);
mInputDeviceDelegate = new InputDeviceDelegate(mContext, mHandler);
VibrationCompleteListener listener = new VibrationCompleteListener(this);
@@ -235,7 +236,6 @@
recentDumpSizeLimit, dumpSizeLimit, dumpAggregationTimeLimit);
mBatteryStatsService = injector.getBatteryStatsService();
- mFrameworkStatsLogger = injector.getFrameworkStatsLogger(mHandler);
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -853,9 +853,7 @@
private void endVibrationLocked(HalVibration vib, Vibration.EndInfo vibrationEndInfo,
boolean shouldWriteStats) {
vib.end(vibrationEndInfo);
- logVibrationStatus(vib.callerInfo.uid, vib.callerInfo.attrs,
- vibrationEndInfo.status);
- mVibratorManagerRecords.record(vib);
+ logAndRecordVibration(vib.getDebugInfo());
if (shouldWriteStats) {
mFrameworkStatsLogger.writeVibrationReportedAsync(
vib.getStatsInfo(/* completionUptimeMillis= */ SystemClock.uptimeMillis()));
@@ -866,9 +864,7 @@
private void endVibrationAndWriteStatsLocked(ExternalVibrationHolder vib,
Vibration.EndInfo vibrationEndInfo) {
vib.end(vibrationEndInfo);
- logVibrationStatus(vib.externalVibration.getUid(),
- vib.externalVibration.getVibrationAttributes(), vibrationEndInfo.status);
- mVibratorManagerRecords.record(vib);
+ logAndRecordVibration(vib.getDebugInfo());
mFrameworkStatsLogger.writeVibrationReportedAsync(
vib.getStatsInfo(/* completionUptimeMillis= */ SystemClock.uptimeMillis()));
}
@@ -882,12 +878,12 @@
vib.callerInfo.attrs.getUsage())) {
requestVibrationParamsFuture =
mVibratorControlService.triggerVibrationParamsRequest(
- vib.callerInfo.attrs.getUsage(),
+ vib.callerInfo.uid, vib.callerInfo.attrs.getUsage(),
mVibrationSettings.getRequestVibrationParamsTimeoutMs());
}
return new VibrationStepConductor(vib, mVibrationSettings, mDeviceAdapter, mVibrationScaler,
- requestVibrationParamsFuture, mVibrationThreadCallbacks);
+ mFrameworkStatsLogger, requestVibrationParamsFuture, mVibrationThreadCallbacks);
}
private Vibration.EndInfo startVibrationOnInputDevicesLocked(HalVibration vib) {
@@ -903,6 +899,12 @@
return new Vibration.EndInfo(Vibration.Status.FORWARDED_TO_INPUT_DEVICES);
}
+ private void logAndRecordVibration(Vibration.DebugInfo info) {
+ info.logMetrics(mFrameworkStatsLogger);
+ logVibrationStatus(info.mCallerInfo.uid, info.mCallerInfo.attrs, info.mStatus);
+ mVibratorManagerRecords.record(info);
+ }
+
private void logVibrationStatus(int uid, VibrationAttributes attrs,
Vibration.Status status) {
switch (status) {
@@ -1752,15 +1754,7 @@
new VibrationRecords(recentVibrationSizeLimit, /* aggregationTimeLimit= */ 0);
}
- synchronized void record(HalVibration vib) {
- record(vib.getDebugInfo());
- }
-
- synchronized void record(ExternalVibrationHolder vib) {
- record(vib.getDebugInfo());
- }
-
- private synchronized void record(Vibration.DebugInfo info) {
+ synchronized void record(Vibration.DebugInfo info) {
GroupedAggregatedLogRecords.AggregatedLogRecord<VibrationRecord> droppedRecord =
mRecentVibrations.add(new VibrationRecord(info));
if (droppedRecord != null) {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 7f3df95..57b9c63 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -25,6 +25,7 @@
import static android.view.InsetsFrameProvider.SOURCE_FRAME;
import static android.view.ViewRootImpl.CLIENT_IMMERSIVE_CONFIRMATION;
import static android.view.ViewRootImpl.CLIENT_TRANSIENT;
+import static android.view.WindowInsetsController.APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -984,6 +985,9 @@
}
break;
}
+ if ((attrs.insetsFlags.appearance & APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS) != 0) {
+ attrs.insetsFlags.appearance |= APPEARANCE_LIGHT_NAVIGATION_BARS;
+ }
if (LayoutParams.isSystemAlertWindowType(attrs.type)) {
float maxOpacity = mService.mMaximumObscuringOpacityForTouch;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 73aa307..d87e21c 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1933,8 +1933,8 @@
td.setEnsureStatusBarContrastWhenTransparent(
atd.getEnsureStatusBarContrastWhenTransparent());
}
- if (td.getStatusBarAppearance() == 0) {
- td.setStatusBarAppearance(atd.getStatusBarAppearance());
+ if (td.getSystemBarsAppearance() == 0) {
+ td.setSystemBarsAppearance(atd.getSystemBarsAppearance());
}
if (td.getNavigationBarColor() == 0) {
td.setNavigationBarColor(atd.getNavigationBarColor());
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index f4d95af..b9c5b36 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -201,6 +201,7 @@
when(mMockUserManagerInternal.isUserRunning(anyInt())).thenReturn(true);
when(mMockUserManagerInternal.getProfileIds(anyInt(), anyBoolean()))
.thenReturn(new int[] {0});
+ when(mMockUserManagerInternal.getUserIds()).thenReturn(new int[] {0});
when(mMockActivityManagerInternal.isSystemReady()).thenReturn(true);
when(mMockPackageManagerInternal.getPackageUid(anyString(), anyLong(), anyInt()))
.thenReturn(Binder.getCallingUid());
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index 4f27bc2..ea7bb8b 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -94,7 +94,7 @@
"libutils",
"netd_aidl_interface-V5-cpp",
],
-
+ compile_multilib: "both",
dxflags: ["--multi-dex"],
java_resources: [
diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index 9c9aeea..705dac5 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -19,6 +19,7 @@
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
+import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE;
import static org.junit.Assert.assertArrayEquals;
@@ -72,7 +73,7 @@
private static final int DARKENING_LIGHT_DEBOUNCE_CONFIG = 4000;
private static final int BRIGHTENING_LIGHT_DEBOUNCE_CONFIG_IDLE = 1000;
private static final int DARKENING_LIGHT_DEBOUNCE_CONFIG_IDLE = 2000;
- private static final float DOZE_SCALE_FACTOR = 0.0f;
+ private static final float DOZE_SCALE_FACTOR = 0.54f;
private static final boolean RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG = false;
private static final int LIGHT_SENSOR_WARMUP_TIME = 0;
private static final int AMBIENT_LIGHT_HORIZON_SHORT = 1000;
@@ -87,6 +88,7 @@
@Mock SensorManager mSensorManager;
@Mock BrightnessMappingStrategy mBrightnessMappingStrategy;
@Mock BrightnessMappingStrategy mIdleBrightnessMappingStrategy;
+ @Mock BrightnessMappingStrategy mDozeBrightnessMappingStrategy;
@Mock HysteresisLevels mAmbientBrightnessThresholds;
@Mock HysteresisLevels mScreenBrightnessThresholds;
@Mock HysteresisLevels mAmbientBrightnessThresholdsIdle;
@@ -124,12 +126,15 @@
when(mBrightnessMappingStrategy.getMode()).thenReturn(AUTO_BRIGHTNESS_MODE_DEFAULT);
when(mIdleBrightnessMappingStrategy.getMode()).thenReturn(AUTO_BRIGHTNESS_MODE_IDLE);
+ when(mDozeBrightnessMappingStrategy.getMode()).thenReturn(AUTO_BRIGHTNESS_MODE_DOZE);
SparseArray<BrightnessMappingStrategy> brightnessMappingStrategyMap = new SparseArray<>();
brightnessMappingStrategyMap.append(AUTO_BRIGHTNESS_MODE_DEFAULT,
mBrightnessMappingStrategy);
brightnessMappingStrategyMap.append(AUTO_BRIGHTNESS_MODE_IDLE,
mIdleBrightnessMappingStrategy);
+ brightnessMappingStrategyMap.append(AUTO_BRIGHTNESS_MODE_DOZE,
+ mDozeBrightnessMappingStrategy);
mController = new AutomaticBrightnessController(
new AutomaticBrightnessController.Injector() {
@Override
@@ -1032,10 +1037,9 @@
float normalizedBrightness = 0.3f;
when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux);
when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux);
- when(mBrightnessMappingStrategy.getBrightness(eq(lux), eq(null), anyInt()))
- .thenReturn(normalizedBrightness);
+ when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null),
+ /* category= */ anyInt())).thenReturn(normalizedBrightness);
when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT);
- when(mBrightnessThrottler.isThrottled()).thenReturn(true);
// Send a new sensor value, disable the sensor and verify
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux));
@@ -1047,4 +1051,79 @@
mController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
/* brightnessEvent= */ null), EPSILON);
}
+
+ @Test
+ public void testAutoBrightnessInDoze_ShouldScaleIfNotUsingDozeCurve() throws Exception {
+ ArgumentCaptor<SensorEventListener> listenerCaptor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+ verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
+ eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
+ SensorEventListener listener = listenerCaptor.getValue();
+
+ // Set up system to return 0.3f as a brightness value
+ float lux = 100.0f;
+ // Brightness as float (from 0.0f to 1.0f)
+ float normalizedBrightness = 0.3f;
+ when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux);
+ when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux);
+ when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null),
+ /* category= */ anyInt())).thenReturn(normalizedBrightness);
+ when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT);
+
+ // Set policy to DOZE
+ mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null,
+ /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0,
+ /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE,
+ /* shouldResetShortTermModel= */ true);
+
+ // Send a new sensor value
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux));
+
+ // The brightness should be scaled by the doze factor
+ assertEquals(normalizedBrightness * DOZE_SCALE_FACTOR,
+ mController.getAutomaticScreenBrightness(
+ /* brightnessEvent= */ null), EPSILON);
+ assertEquals(normalizedBrightness * DOZE_SCALE_FACTOR,
+ mController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ /* brightnessEvent= */ null), EPSILON);
+ }
+
+ @Test
+ public void testAutoBrightnessInDoze_ShouldNotScaleIfUsingDozeCurve() throws Exception {
+ ArgumentCaptor<SensorEventListener> listenerCaptor =
+ ArgumentCaptor.forClass(SensorEventListener.class);
+ verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
+ eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
+ SensorEventListener listener = listenerCaptor.getValue();
+
+ // Set up system to return 0.3f as a brightness value
+ float lux = 100.0f;
+ // Brightness as float (from 0.0f to 1.0f)
+ float normalizedBrightness = 0.3f;
+ when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux)).thenReturn(lux);
+ when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux);
+ when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null),
+ /* category= */ anyInt())).thenReturn(normalizedBrightness);
+ when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT);
+
+ // Switch mode to DOZE
+ mController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE);
+
+ // Set policy to DOZE
+ mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null,
+ /* brightness= */ 0, /* userChangedBrightness= */ false, /* adjustment= */ 0,
+ /* userChanged= */ false, DisplayPowerRequest.POLICY_DOZE,
+ /* shouldResetShortTermModel= */ true);
+
+ // Send a new sensor value
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux));
+
+ // The brightness should not be scaled by the doze factor
+ assertEquals(normalizedBrightness,
+ mController.getAutomaticScreenBrightness(
+ /* brightnessEvent= */ null), EPSILON);
+ assertEquals(normalizedBrightness,
+ mController.getAutomaticScreenBrightnessBasedOnLastObservedLux(
+ /* brightnessEvent= */ null), EPSILON);
+ }
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index 14d8a9c..76b7780 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -114,6 +114,8 @@
private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1;
private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789";
private static final float PROX_SENSOR_MAX_RANGE = 5;
+ private static final float DOZE_SCALE_FACTOR = 0.34f;
+
private static final float BRIGHTNESS_RAMP_RATE_MINIMUM = 0.0f;
private static final float BRIGHTNESS_RAMP_RATE_FAST_DECREASE = 0.3f;
private static final float BRIGHTNESS_RAMP_RATE_FAST_INCREASE = 0.4f;
@@ -193,6 +195,9 @@
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.bool.config_displayColorFadeDisabled, false);
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
+ DOZE_SCALE_FACTOR);
doAnswer((Answer<Void>) invocationOnMock -> null).when(() ->
SystemProperties.set(anyString(), any()));
@@ -1705,7 +1710,7 @@
}
@Test
- public void testInitialDozeBrightness() {
+ public void testInitialDozeBrightness_AutoBrightnessEnabled() {
when(mDisplayManagerFlagsMock.areAutoBrightnessModesEnabled()).thenReturn(true);
when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true);
mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession);
@@ -1734,6 +1739,39 @@
}
@Test
+ public void testInitialDozeBrightness_AutoBrightnessDisabled() {
+ when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true);
+ mHolder.dpc.setDisplayOffloadSession(mDisplayOffloadSession);
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+ float brightness = 0.277f;
+ when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
+ when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+ when(mHolder.hbmController.getCurrentBrightnessMax())
+ .thenReturn(PowerManager.BRIGHTNESS_MAX);
+ when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_DOZE);
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_DOZE;
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState, initialize
+
+ ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+ ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+ verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+ BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
+ listener.onBrightnessChanged(brightness);
+ advanceTime(1); // Send messages, run updatePowerState
+
+ verify(mHolder.animator).animateTo(eq(brightness * DOZE_SCALE_FACTOR),
+ /* linearSecondTarget= */ anyFloat(), /* rate= */ anyFloat(),
+ /* ignoreAnimationLimits= */ anyBoolean());
+ assertEquals(brightness * DOZE_SCALE_FACTOR, mHolder.dpc.getDozeBrightnessForOffload(),
+ /* delta= */ 0);
+ }
+
+ @Test
public void testInitialDozeBrightness_AbcIsNull() {
when(mDisplayManagerFlagsMock.areAutoBrightnessModesEnabled()).thenReturn(true);
when(mDisplayManagerFlagsMock.isDisplayOffloadEnabled()).thenReturn(true);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
index 0e89d83..a3728c8 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
@@ -18,8 +18,10 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
@@ -268,4 +270,33 @@
mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest,
Display.STATE_ON));
}
+
+ @Test
+ public void selectStrategyCallsPostProcessorForAllStrategies() {
+ when(mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()).thenReturn(true);
+ mDisplayBrightnessStrategySelector = new DisplayBrightnessStrategySelector(mContext,
+ mInjector, DISPLAY_ID, mDisplayManagerFlags);
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest = mock(
+ DisplayManagerInternal.DisplayPowerRequest.class);
+ when(mFollowerBrightnessStrategy.getBrightnessToFollow()).thenReturn(0.3f);
+
+ mDisplayBrightnessStrategySelector.selectStrategy(displayPowerRequest, Display.STATE_ON);
+
+ StrategySelectionNotifyRequest strategySelectionNotifyRequest =
+ new StrategySelectionNotifyRequest(mFollowerBrightnessStrategy);
+ verify(mInvalidBrightnessStrategy).strategySelectionPostProcessor(
+ eq(strategySelectionNotifyRequest));
+ verify(mScreenOffBrightnessModeStrategy).strategySelectionPostProcessor(
+ eq(strategySelectionNotifyRequest));
+ verify(mDozeBrightnessModeStrategy).strategySelectionPostProcessor(
+ eq(strategySelectionNotifyRequest));
+ verify(mFollowerBrightnessStrategy).strategySelectionPostProcessor(
+ eq(strategySelectionNotifyRequest));
+ verify(mBoostBrightnessStrategy).strategySelectionPostProcessor(
+ eq(strategySelectionNotifyRequest));
+ verify(mOverrideBrightnessStrategy).strategySelectionPostProcessor(
+ eq(strategySelectionNotifyRequest));
+ verify(mTemporaryBrightnessStrategy).strategySelectionPostProcessor(
+ eq(strategySelectionNotifyRequest));
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
index 9d3caa5..bd20ae2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
@@ -283,4 +283,9 @@
receiverList.add(res);
return res;
}
+
+ void setProcessFreezable(ProcessRecord app, boolean pendingFreeze, boolean frozen) {
+ app.mOptRecord.setPendingFreeze(pendingFreeze);
+ app.mOptRecord.setFrozen(frozen);
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index bcf297f..079bc37 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -99,7 +99,7 @@
private static final int TEST_UID = android.os.Process.FIRST_APPLICATION_UID;
private static final int TEST_UID2 = android.os.Process.FIRST_APPLICATION_UID + 1;
- @Mock ProcessRecord mProcess;
+ ProcessRecord mProcess;
@Mock BroadcastProcessQueue mQueue1;
@Mock BroadcastProcessQueue mQueue2;
@@ -126,6 +126,9 @@
doReturn(2L).when(mQueue2).getRunnableAt();
doReturn(3L).when(mQueue3).getRunnableAt();
doReturn(4L).when(mQueue4).getRunnableAt();
+
+ final ApplicationInfo ai = makeApplicationInfo(PACKAGE_ORANGE);
+ mProcess = spy(new ProcessRecord(mAms, ai, ai.processName, ai.uid));
}
@After
@@ -1746,6 +1749,31 @@
}, false /* andRemove */);
}
+ @Test
+ public void testIsProcessFreezable() throws Exception {
+ final ProcessRecord greenProcess = makeProcessRecord(makeApplicationInfo(PACKAGE_GREEN));
+
+ setProcessFreezable(greenProcess, true /* pendingFreeze */, true /* frozen */);
+ mImpl.onProcessFreezableChangedLocked(greenProcess);
+ waitForIdle();
+ assertTrue(mImpl.isProcessFreezable(greenProcess));
+
+ setProcessFreezable(greenProcess, true /* pendingFreeze */, false /* frozen */);
+ mImpl.onProcessFreezableChangedLocked(greenProcess);
+ waitForIdle();
+ assertTrue(mImpl.isProcessFreezable(greenProcess));
+
+ setProcessFreezable(greenProcess, false /* pendingFreeze */, true /* frozen */);
+ mImpl.onProcessFreezableChangedLocked(greenProcess);
+ waitForIdle();
+ assertTrue(mImpl.isProcessFreezable(greenProcess));
+
+ setProcessFreezable(greenProcess, false /* pendingFreeze */, false /* frozen */);
+ mImpl.onProcessFreezableChangedLocked(greenProcess);
+ waitForIdle();
+ assertFalse(mImpl.isProcessFreezable(greenProcess));
+ }
+
// TODO: Reuse BroadcastQueueTest.makeActiveProcessRecord()
private ProcessRecord makeProcessRecord(ApplicationInfo info) {
final ProcessRecord r = spy(new ProcessRecord(mAms, info, info.processName, info.uid));
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index 56e5bd6..66ab807 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -86,6 +86,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import org.mockito.InOrder;
@@ -446,11 +447,6 @@
BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
}
- private void setProcessFreezable(ProcessRecord app, boolean pendingFreeze, boolean frozen) {
- app.mOptRecord.setPendingFreeze(pendingFreeze);
- app.mOptRecord.setFrozen(frozen);
- }
-
private void assertHealth() {
// If this fails, it'll throw a clear reason message
((BroadcastQueueModernImpl) mQueue).assertHealthLocked();
@@ -2339,6 +2335,38 @@
.isGreaterThan(getReceiverScheduledTime(prioritizedRecord, receiverBlue));
}
+ @Ignore
+ @Test
+ public void testDeferOutgoingBroadcasts() throws Exception {
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+ setProcessFreezable(callerApp, true /* pendingFreeze */, false /* frozen */);
+ mQueue.onProcessFreezableChangedLocked(callerApp);
+ waitForIdle();
+
+ final ProcessRecord receiverGreenApp = makeActiveProcessRecord(PACKAGE_GREEN);
+ final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
+ final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK);
+ enqueueBroadcast(makeBroadcastRecord(timeTick, callerApp, List.of(
+ makeRegisteredReceiver(receiverGreenApp),
+ makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE),
+ makeManifestReceiver(PACKAGE_YELLOW, CLASS_YELLOW))));
+
+ waitForIdle();
+ verifyScheduleRegisteredReceiver(never(), receiverGreenApp, timeTick);
+ verifyScheduleReceiver(never(), receiverBlueApp, timeTick);
+ assertNull(mAms.getProcessRecordLocked(PACKAGE_YELLOW, getUidForPackage(PACKAGE_GREEN)));
+
+ setProcessFreezable(callerApp, false /* pendingFreeze */, false /* frozen */);
+ mQueue.onProcessFreezableChangedLocked(callerApp);
+ waitForIdle();
+
+ verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, timeTick);
+ verifyScheduleReceiver(times(1), receiverBlueApp, timeTick);
+ final ProcessRecord receiverYellowApp = mAms.getProcessRecordLocked(PACKAGE_YELLOW,
+ getUidForPackage(PACKAGE_YELLOW));
+ verifyScheduleReceiver(times(1), receiverYellowApp, timeTick);
+ }
+
private long getReceiverScheduledTime(@NonNull BroadcastRecord r, @NonNull Object receiver) {
for (int i = 0; i < r.receivers.size(); ++i) {
if (isReceiverEquals(receiver, r.receivers.get(i))) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java
index 709a804..97b7af8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java
@@ -186,7 +186,7 @@
any());
doReturn(true).when(mAms.mOomAdjuster.mCachedAppOptimizer).useFreezer();
doNothing().when(mAms.mOomAdjuster.mCachedAppOptimizer).freezeAppAsyncInternalLSP(
- any(), anyLong(), anyBoolean());
+ any(), anyLong(), anyBoolean(), anyBoolean());
doReturn(false).when(mAms.mAppProfiler).updateLowMemStateLSP(anyInt(), anyInt(),
anyInt(), anyLong());
@@ -503,7 +503,7 @@
if (clientApp.isFreezable()) {
verify(mAms.mOomAdjuster.mCachedAppOptimizer,
times(Flags.serviceBindingOomAdjPolicy() ? 1 : 0))
- .freezeAppAsyncInternalLSP(eq(clientApp), eq(0L), anyBoolean());
+ .freezeAppAsyncInternalLSP(eq(clientApp), eq(0L), anyBoolean(), anyBoolean());
clearInvocations(mAms.mOomAdjuster.mCachedAppOptimizer);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING b/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING
index 6ac56bf..4ac4484 100644
--- a/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "postsubmit": [
+ "presubmit": [
{
"name": "RollbackPackageHealthObserverTests",
"options": [
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
index 6e478d8..55fc03e 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -110,6 +110,7 @@
@Mock private VibratorController.OnVibrationCompleteListener mControllerCallbacks;
@Mock private IBinder mVibrationToken;
@Mock private VibrationConfig mVibrationConfigMock;
+ @Mock private VibratorFrameworkStatsLogger mStatsLoggerMock;
private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
private VibrationSettings mVibrationSettings;
@@ -255,6 +256,7 @@
USAGE_RINGTONE);
waitForCompletion();
+ verify(mStatsLoggerMock, never()).logVibrationParamRequestTimeout(UID);
assertEquals(Arrays.asList(expectedOneShot(15)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId));
List<Float> amplitudes = mVibratorProviders.get(VIBRATOR_ID).getAmplitudes();
@@ -274,6 +276,7 @@
long vibrationId = startThreadAndDispatcher(effect, neverCompletingFuture, USAGE_RINGTONE);
waitForCompletion();
+ verify(mStatsLoggerMock).logVibrationParamRequestTimeout(UID);
assertEquals(Arrays.asList(expectedOneShot(15)),
mVibratorProviders.get(VIBRATOR_ID).getEffectSegments(vibrationId));
assertEquals(expectedAmplitudes(1, 1, 1),
@@ -1679,7 +1682,7 @@
mControllers = createVibratorControllers();
DeviceAdapter deviceAdapter = new DeviceAdapter(mVibrationSettings, mControllers);
mVibrationConductor = new VibrationStepConductor(vib, mVibrationSettings, deviceAdapter,
- mVibrationScaler, requestVibrationParamsFuture, mManagerHooks);
+ mVibrationScaler, mStatsLoggerMock, requestVibrationParamsFuture, mManagerHooks);
assertTrue(mThread.runVibrationOnVibrationThread(mVibrationConductor));
return mVibrationConductor.getVibration().id;
}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java
index 3799abc..3f5217c 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java
@@ -27,6 +27,10 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -38,6 +42,7 @@
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Process;
import android.os.test.TestLooper;
import android.util.SparseArray;
@@ -59,13 +64,14 @@
public class VibratorControlServiceTest {
+ private static final int UID = Process.ROOT_UID;
+
@Rule
public MockitoRule rule = MockitoJUnit.rule();
- @Mock
- private VibrationScaler mMockVibrationScaler;
- @Mock
- private PackageManagerInternal mPackageManagerInternalMock;
+ @Mock private VibrationScaler mMockVibrationScaler;
+ @Mock private PackageManagerInternal mPackageManagerInternalMock;
+ @Mock private VibratorFrameworkStatsLogger mStatsLoggerMock;
private TestLooper mTestLooper;
private FakeVibratorController mFakeVibratorController;
@@ -88,7 +94,7 @@
mFakeVibratorController = new FakeVibratorController(mTestLooper.getLooper());
mVibratorControlService = new VibratorControlService(
InstrumentationRegistry.getContext(), new VibratorControllerHolder(),
- mMockVibrationScaler, mVibrationSettings, mLock);
+ mMockVibrationScaler, mVibrationSettings, mStatsLoggerMock, mLock);
}
@Test
@@ -123,7 +129,7 @@
mVibratorControlService.registerVibratorController(mFakeVibratorController);
int timeoutInMillis = 10;
CompletableFuture<Void> future =
- mVibratorControlService.triggerVibrationParamsRequest(USAGE_RINGTONE,
+ mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE,
timeoutInMillis);
IBinder token = mVibratorControlService.getRequestVibrationParamsToken();
@@ -134,6 +140,11 @@
mVibratorControlService.onRequestVibrationParamsComplete(token,
VibrationParamGenerator.generateVibrationParams(vibrationScales));
+ verify(mStatsLoggerMock).logVibrationParamRequestLatency(eq(UID), anyLong());
+ verify(mStatsLoggerMock).logVibrationParamScale(0.7f);
+ verify(mStatsLoggerMock).logVibrationParamScale(0.4f);
+ verifyNoMoreInteractions(mStatsLoggerMock);
+
verify(mMockVibrationScaler).updateAdaptiveHapticsScale(USAGE_ALARM, 0.7f);
verify(mMockVibrationScaler).updateAdaptiveHapticsScale(USAGE_NOTIFICATION, 0.4f);
// Setting ScaleParam.TYPE_NOTIFICATION will update vibration scaling for both
@@ -150,7 +161,7 @@
mVibratorControlService.registerVibratorController(mFakeVibratorController);
int timeoutInMillis = 10;
CompletableFuture<Void> unusedFuture =
- mVibratorControlService.triggerVibrationParamsRequest(USAGE_RINGTONE,
+ mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE,
timeoutInMillis);
SparseArray<Float> vibrationScales = new SparseArray<>();
@@ -160,6 +171,9 @@
mVibratorControlService.onRequestVibrationParamsComplete(new Binder(),
VibrationParamGenerator.generateVibrationParams(vibrationScales));
+ verify(mStatsLoggerMock).logVibrationParamResponseIgnored();
+ verifyNoMoreInteractions(mStatsLoggerMock);
+
verifyZeroInteractions(mMockVibrationScaler);
}
@@ -174,6 +188,10 @@
VibrationParamGenerator.generateVibrationParams(vibrationScales),
mFakeVibratorController);
+ verify(mStatsLoggerMock).logVibrationParamScale(0.7f);
+ verify(mStatsLoggerMock).logVibrationParamScale(0.4f);
+ verifyNoMoreInteractions(mStatsLoggerMock);
+
verify(mMockVibrationScaler).updateAdaptiveHapticsScale(USAGE_ALARM, 0.7f);
verify(mMockVibrationScaler).updateAdaptiveHapticsScale(USAGE_NOTIFICATION, 0.4f);
// Setting ScaleParam.TYPE_NOTIFICATION will update vibration scaling for both
@@ -192,6 +210,7 @@
VibrationParamGenerator.generateVibrationParams(vibrationScales),
mFakeVibratorController);
+ verify(mStatsLoggerMock, never()).logVibrationParamScale(anyFloat());
verifyZeroInteractions(mMockVibrationScaler);
}
@@ -202,6 +221,8 @@
mVibratorControlService.clearVibrationParams(types, mFakeVibratorController);
+ verify(mStatsLoggerMock).logVibrationParamScale(-1f);
+
verify(mMockVibrationScaler).removeAdaptiveHapticsScale(USAGE_ALARM);
verify(mMockVibrationScaler).removeAdaptiveHapticsScale(USAGE_NOTIFICATION);
// Clearing ScaleParam.TYPE_NOTIFICATION will clear vibration scaling for both
@@ -214,6 +235,7 @@
mVibratorControlService.clearVibrationParams(ScaleParam.TYPE_ALARM,
mFakeVibratorController);
+ verify(mStatsLoggerMock, never()).logVibrationParamScale(anyFloat());
verifyZeroInteractions(mMockVibrationScaler);
}
@@ -222,7 +244,7 @@
int timeoutInMillis = 10;
mVibratorControlService.registerVibratorController(mFakeVibratorController);
CompletableFuture<Void> future =
- mVibratorControlService.triggerVibrationParamsRequest(USAGE_RINGTONE,
+ mVibratorControlService.triggerVibrationParamsRequest(UID, USAGE_RINGTONE,
timeoutInMillis);
try {
future.orTimeout(timeoutInMillis, TimeUnit.MILLISECONDS).get();
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 1ea90f5..d6ac517 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -70,7 +70,6 @@
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.Process;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.VibrationAttributes;
@@ -1551,6 +1550,48 @@
}
@Test
+ @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED)
+ public void vibrate_withAdaptiveHaptics_appliesCorrectAdaptiveScales() throws Exception {
+ // Keep user settings the same as device default so only adaptive scale is applied.
+ setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
+ mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_ALARM));
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
+ mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION));
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
+ mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH));
+
+ mockVibrators(1);
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
+ fakeVibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
+ fakeVibrator.setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK);
+ VibratorManagerService service = createSystemReadyService();
+
+ SparseArray<Float> vibrationScales = new SparseArray<>();
+ vibrationScales.put(ScaleParam.TYPE_ALARM, 0.7f);
+ vibrationScales.put(ScaleParam.TYPE_NOTIFICATION, 0.4f);
+
+ mVibratorControlService.setVibrationParams(
+ VibrationParamGenerator.generateVibrationParams(vibrationScales),
+ mFakeVibratorController);
+
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .compose();
+ vibrateAndWaitUntilFinished(service, effect, ALARM_ATTRS);
+ vibrateAndWaitUntilFinished(service, effect, NOTIFICATION_ATTRS);
+ vibrateAndWaitUntilFinished(service, effect, HAPTIC_FEEDBACK_ATTRS);
+
+ List<VibrationEffectSegment> segments = fakeVibrator.getAllEffectSegments();
+ assertEquals(3, segments.size());
+ assertEquals(0.7f, ((PrimitiveSegment) segments.get(0)).getScale(), 1e-5);
+ assertEquals(0.4f, ((PrimitiveSegment) segments.get(1)).getScale(), 1e-5);
+ assertEquals(1f, ((PrimitiveSegment) segments.get(2)).getScale(), 1e-5);
+ verify(mVibratorFrameworkStatsLoggerMock).logVibrationAdaptiveHapticScale(UID, 0.7f);
+ verify(mVibratorFrameworkStatsLoggerMock).logVibrationAdaptiveHapticScale(UID, 0.4f);
+ verify(mVibratorFrameworkStatsLoggerMock).logVibrationAdaptiveHapticScale(UID, 1f);
+ }
+
+ @Test
public void vibrate_withPowerModeChange_cancelVibrationIfNotAllowed() throws Exception {
mockVibrators(1, 2);
VibratorManagerService service = createSystemReadyService();
@@ -1998,8 +2039,7 @@
@Test
@RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED)
- public void onExternalVibration_withAdaptiveHaptics_returnsCorrectAdaptiveScales()
- throws RemoteException {
+ public void onExternalVibration_withAdaptiveHaptics_returnsCorrectAdaptiveScales() {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL,
IVibrator.CAP_AMPLITUDE_CONTROL);
@@ -2020,6 +2060,7 @@
mExternalVibratorService.onExternalVibrationStop(externalVibration);
assertEquals(scale.adaptiveHapticsScale, 0.7f, 0);
+ verify(mVibratorFrameworkStatsLoggerMock).logVibrationAdaptiveHapticScale(UID, 0.7f);
externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
AUDIO_NOTIFICATION_ATTRS,
@@ -2028,6 +2069,7 @@
mExternalVibratorService.onExternalVibrationStop(externalVibration);
assertEquals(scale.adaptiveHapticsScale, 0.4f, 0);
+ verify(mVibratorFrameworkStatsLoggerMock).logVibrationAdaptiveHapticScale(UID, 0.4f);
AudioAttributes ringtoneAudioAttrs = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
@@ -2036,14 +2078,15 @@
ringtoneAudioAttrs,
mock(IExternalVibrationController.class));
scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
+ mExternalVibratorService.onExternalVibrationStop(externalVibration);
assertEquals(scale.adaptiveHapticsScale, 1f, 0);
+ verify(mVibratorFrameworkStatsLoggerMock).logVibrationAdaptiveHapticScale(UID, 1f);
}
@Test
@RequiresFlagsDisabled(android.os.vibrator.Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED)
- public void onExternalVibration_withAdaptiveHapticsFlagDisabled_alwaysReturnScaleNone()
- throws RemoteException {
+ public void onExternalVibration_withAdaptiveHapticsFlagDisabled_alwaysReturnScaleNone() {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL,
IVibrator.CAP_AMPLITUDE_CONTROL);
@@ -2072,8 +2115,10 @@
AUDIO_NOTIFICATION_ATTRS,
mock(IExternalVibrationController.class));
scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
+ mExternalVibratorService.onExternalVibrationStop(externalVibration);
assertEquals(scale.adaptiveHapticsScale, 1f, 0);
+ verify(mVibratorFrameworkStatsLoggerMock).logVibrationAdaptiveHapticScale(UID, 1f);
}
@Test