Merge "Report firstLaunch metrics" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 5772fb4..2d10c05 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -19675,6 +19675,7 @@
public final class CaptureRequest extends android.hardware.camera2.CameraMetadata<android.hardware.camera2.CaptureRequest.Key<?>> implements android.os.Parcelable {
method public int describeContents();
+ method @FlaggedApi("com.android.internal.camera.flags.surface_leak_fix") protected void finalize();
method @Nullable public <T> T get(android.hardware.camera2.CaptureRequest.Key<T>);
method @NonNull public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getKeys();
method @Nullable public Object getTag();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 15f1eb4..892567c6 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1624,8 +1624,6 @@
package android.hardware.devicestate {
@FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceState {
- ctor @Deprecated public DeviceState(@IntRange(from=android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER, to=android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER) int, @NonNull String, int);
- ctor public DeviceState(@IntRange(from=android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER, to=android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER) int, @NonNull String, @NonNull java.util.Set<java.lang.Integer>);
field public static final int PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST = 8; // 0x8
}
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/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 66efccd1..c0db77c 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -309,6 +309,8 @@
private Object mUserTag;
+ private boolean mReleaseSurfaces = false;
+
/**
* Construct empty request.
*
@@ -610,6 +612,9 @@
Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader(),
Surface.class);
if (parcelableArray != null) {
+ if (Flags.surfaceLeakFix()) {
+ mReleaseSurfaces = true;
+ }
for (Parcelable p : parcelableArray) {
Surface s = (Surface) p;
mSurfaceSet.add(s);
@@ -792,6 +797,17 @@
}
}
+ @SuppressWarnings("Finalize")
+ @FlaggedApi(Flags.FLAG_SURFACE_LEAK_FIX)
+ @Override
+ protected void finalize() {
+ if (mReleaseSurfaces) {
+ for (Surface s : mSurfaceSet) {
+ s.release();
+ }
+ }
+ }
+
/**
* A builder for capture requests.
*
diff --git a/core/java/android/hardware/camera2/extension/SessionProcessor.java b/core/java/android/hardware/camera2/extension/SessionProcessor.java
index 2e428e5..0ec5c0a 100644
--- a/core/java/android/hardware/camera2/extension/SessionProcessor.java
+++ b/core/java/android/hardware/camera2/extension/SessionProcessor.java
@@ -363,11 +363,20 @@
private final class SessionProcessorImpl extends ISessionProcessorImpl.Stub {
private long mVendorId = -1;
+ OutputSurface mImageCaptureSurface;
+ OutputSurface mPreviewSurface;
+ OutputSurface mPostviewSurface;
+
@Override
public CameraSessionConfig initSession(IBinder token, String cameraId,
Map<String, CameraMetadataNative> charsMap, OutputSurface previewSurface,
OutputSurface imageCaptureSurface, OutputSurface postviewSurface)
throws RemoteException {
+ if (Flags.surfaceLeakFix()) {
+ mPreviewSurface = previewSurface;
+ mPostviewSurface = postviewSurface;
+ mImageCaptureSurface = imageCaptureSurface;
+ }
ExtensionConfiguration config = SessionProcessor.this.initSession(token, cameraId,
new CharacteristicsMap(charsMap),
new CameraOutputSurface(previewSurface),
@@ -390,6 +399,17 @@
@Override
public void deInitSession(IBinder token) throws RemoteException {
SessionProcessor.this.deInitSession(token);
+ if (Flags.surfaceLeakFix()) {
+ if ((mPreviewSurface != null) && (mPreviewSurface.surface != null)) {
+ mPreviewSurface.surface.release();
+ }
+ if ((mImageCaptureSurface != null) && (mImageCaptureSurface.surface != null)) {
+ mImageCaptureSurface.surface.release();
+ }
+ if ((mPostviewSurface != null) && (mPostviewSurface.surface != null)) {
+ mPostviewSurface.surface.release();
+ }
+ }
}
@Override
diff --git a/core/java/android/hardware/devicestate/DeviceState.java b/core/java/android/hardware/devicestate/DeviceState.java
index e35e801..905d911 100644
--- a/core/java/android/hardware/devicestate/DeviceState.java
+++ b/core/java/android/hardware/devicestate/DeviceState.java
@@ -25,8 +25,9 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-
-import com.android.internal.util.Preconditions;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -37,8 +38,7 @@
import java.util.Set;
/**
- * A state of the device defined by the {@link DeviceStateProvider} and managed by the
- * {@link DeviceStateManagerService}.
+ * A state of the device managed by {@link DeviceStateManager}.
* <p>
* Device state is an abstract concept that allows mapping the current state of the device to the
* state of the system. This is useful for variable-state devices, like foldable or rollable
@@ -268,68 +268,88 @@
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface DeviceStateProperties {}
- /** Unique identifier for the device state. */
- @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
- private final int mIdentifier;
+ /** @hide */
+ @IntDef(prefix = {"PROPERTY_"}, flag = true, value = {
+ PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED,
+ PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN,
+ PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ public @interface PhysicalDeviceStateProperties {}
- /** String description of the device state. */
+ /** @hide */
+ @IntDef(prefix = {"PROPERTY_"}, flag = true, value = {
+ PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
+ PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
+ PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST,
+ PROPERTY_APP_INACCESSIBLE,
+ PROPERTY_EMULATED_ONLY,
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY,
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
+ PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP,
+ PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE,
+ PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY,
+ PROPERTY_FEATURE_REAR_DISPLAY,
+ PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ public @interface SystemDeviceStateProperties {}
+
@NonNull
- private final String mName;
+ private final DeviceState.Configuration mDeviceStateConfiguration;
@DeviceStateFlags
private final int mFlags;
- private final Set<@DeviceStateProperties Integer> mProperties;
+ /** @hide */
+ public DeviceState(@NonNull DeviceState.Configuration deviceStateConfiguration) {
+ Objects.requireNonNull(deviceStateConfiguration, "Device StateConfiguration is null");
+ mDeviceStateConfiguration = deviceStateConfiguration;
+ mFlags = 0;
+ }
+
+ /** @hide */
+ public DeviceState(
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
+ MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
+ @NonNull String name,
+ @NonNull Set<@DeviceStateProperties Integer> properties) {
+ mDeviceStateConfiguration = new DeviceState.Configuration(identifier, name, properties,
+ Collections.emptySet());
+ mFlags = 0;
+ }
/**
* @deprecated Deprecated in favor of {@link #DeviceState(int, String, Set)}
* @hide
*/
// TODO(b/325124054): Make non-default and remove deprecated callback methods.
- @TestApi
@Deprecated
public DeviceState(
@IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
@NonNull String name,
@DeviceStateFlags int flags) {
- Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE_IDENTIFIER,
- MAXIMUM_DEVICE_STATE_IDENTIFIER,
- "identifier");
- mIdentifier = identifier;
- mName = name;
+ mDeviceStateConfiguration = new DeviceState.Configuration(identifier, name,
+ Collections.emptySet(), Collections.emptySet());
mFlags = flags;
- mProperties = Collections.emptySet();
- }
-
- /** @hide */
- @TestApi
- public DeviceState(
- @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
- MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
- @NonNull String name,
- @NonNull Set<@DeviceStateProperties Integer> properties) {
- Preconditions.checkArgumentInRange(identifier, MINIMUM_DEVICE_STATE_IDENTIFIER,
- MAXIMUM_DEVICE_STATE_IDENTIFIER,
- "identifier");
-
- mIdentifier = identifier;
- mName = name;
- mProperties = Set.copyOf(properties);
- mFlags = 0;
}
/** Returns the unique identifier for the device state. */
@IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER)
public int getIdentifier() {
- return mIdentifier;
+ return mDeviceStateConfiguration.getIdentifier();
}
/** Returns a string description of the device state. */
@NonNull
public String getName() {
- return mName;
+ return mDeviceStateConfiguration.getName();
}
/**
@@ -345,10 +365,13 @@
@Override
public String toString() {
- return "DeviceState{" + "identifier=" + mIdentifier + ", name='" + mName + '\''
- + ", app_accessible=" + !hasProperty(PROPERTY_APP_INACCESSIBLE)
+ return "DeviceState{" + "identifier=" + mDeviceStateConfiguration.getIdentifier()
+ + ", name='" + mDeviceStateConfiguration.getName() + '\''
+ + ", app_accessible=" + !mDeviceStateConfiguration.getSystemProperties().contains(
+ PROPERTY_APP_INACCESSIBLE)
+ ", cancel_when_requester_not_on_top="
- + hasProperty(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
+ + mDeviceStateConfiguration.getSystemProperties().contains(
+ PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
+ "}";
}
@@ -357,14 +380,12 @@
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DeviceState that = (DeviceState) o;
- return mIdentifier == that.mIdentifier
- && Objects.equals(mName, that.mName)
- && Objects.equals(mProperties, that.mProperties);
+ return Objects.equals(mDeviceStateConfiguration, that.mDeviceStateConfiguration);
}
@Override
public int hashCode() {
- return Objects.hash(mIdentifier, mName, mProperties);
+ return Objects.hash(mDeviceStateConfiguration);
}
/** Checks if a specific flag is set
@@ -381,7 +402,8 @@
* Checks if a specific property is set on this state
*/
public boolean hasProperty(@DeviceStateProperties int propertyToCheckFor) {
- return mProperties.contains(propertyToCheckFor);
+ return mDeviceStateConfiguration.mSystemProperties.contains(propertyToCheckFor)
+ || mDeviceStateConfiguration.mPhysicalProperties.contains(propertyToCheckFor);
}
/**
@@ -389,10 +411,191 @@
*/
public boolean hasProperties(@NonNull @DeviceStateProperties int... properties) {
for (int i = 0; i < properties.length; i++) {
- if (mProperties.contains(properties[i])) {
+ if (!hasProperty(properties[i])) {
return false;
}
}
return true;
}
+
+ /**
+ * Returns the underlying {@link DeviceState.Configuration} object used to model the
+ * device state.
+ * @hide
+ */
+ public Configuration getConfiguration() {
+ return mDeviceStateConfiguration;
+ }
+
+ /**
+ * Detailed description of a {@link DeviceState} that includes separated sets of
+ * {@link DeviceStateProperties} for properties that correspond to the state of the system when
+ * the device is in this state, as well as physical properties that describe this state.
+ *
+ * Instantiation of this class should only be done by the system server, and clients of
+ * {@link DeviceStateManager} will receive {@link DeviceState} objects.
+ *
+ * @see DeviceStateManager
+ * @hide
+ */
+ public static final class Configuration implements Parcelable {
+ /** Unique identifier for the device state. */
+ @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to = MAXIMUM_DEVICE_STATE_IDENTIFIER)
+ private final int mIdentifier;
+
+ /** String description of the device state. */
+ @NonNull
+ private final String mName;
+
+ /** {@link ArraySet} of system properties that apply to this state. */
+ @NonNull
+ private final ArraySet<@SystemDeviceStateProperties Integer> mSystemProperties;
+
+ /** {@link ArraySet} of physical device properties that apply to this state. */
+ @NonNull
+ private final ArraySet<@PhysicalDeviceStateProperties Integer> mPhysicalProperties;
+
+ private Configuration(int identifier, @NonNull String name,
+ @NonNull Set<@SystemDeviceStateProperties Integer> systemProperties,
+ @NonNull Set<@PhysicalDeviceStateProperties Integer> physicalProperties) {
+ mIdentifier = identifier;
+ mName = name;
+ mSystemProperties = new ArraySet<@SystemDeviceStateProperties Integer>(
+ systemProperties);
+ mPhysicalProperties = new ArraySet<@PhysicalDeviceStateProperties Integer>(
+ physicalProperties);
+ }
+
+ /** Returns the unique identifier for the device state. */
+ public int getIdentifier() {
+ return mIdentifier;
+ }
+
+ /** Returns a string description of the device state. */
+ @NonNull
+ public String getName() {
+ return mName;
+ }
+
+ /** Returns the {@link Set} of system properties that apply to this state. */
+ @NonNull
+ public Set<@SystemDeviceStateProperties Integer> getSystemProperties() {
+ return mSystemProperties;
+ }
+
+ /** Returns the {@link Set} of physical device properties that apply to this state. */
+ @NonNull
+ public Set<@DeviceStateProperties Integer> getPhysicalProperties() {
+ return mPhysicalProperties;
+ }
+
+ @Override
+ public String toString() {
+ return "DeviceState{" + "identifier=" + mIdentifier
+ + ", name='" + mName + '\''
+ + ", app_accessible=" + mSystemProperties.contains(PROPERTY_APP_INACCESSIBLE)
+ + ", cancel_when_requester_not_on_top="
+ + mSystemProperties.contains(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)
+ + "}";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DeviceState.Configuration that = (DeviceState.Configuration) o;
+ return mIdentifier == that.mIdentifier
+ && Objects.equals(mName, that.mName)
+ && Objects.equals(mSystemProperties, that.mSystemProperties)
+ && Objects.equals(mPhysicalProperties, that.mPhysicalProperties);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIdentifier, mName, mSystemProperties, mPhysicalProperties);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mIdentifier);
+ dest.writeString8(mName);
+
+ dest.writeInt(mSystemProperties.size());
+ for (int i = 0; i < mSystemProperties.size(); i++) {
+ dest.writeInt(mSystemProperties.valueAt(i));
+ }
+
+ dest.writeInt(mPhysicalProperties.size());
+ for (int i = 0; i < mPhysicalProperties.size(); i++) {
+ dest.writeInt(mPhysicalProperties.valueAt(i));
+ }
+ }
+
+ @NonNull
+ public static final Creator<DeviceState.Configuration> CREATOR = new Creator<>() {
+ @Override
+ public DeviceState.Configuration createFromParcel(Parcel source) {
+ int identifier = source.readInt();
+ String name = source.readString8();
+ ArraySet<@DeviceStateProperties Integer> systemProperties = new ArraySet<>();
+ for (int i = 0; i < source.readInt(); i++) {
+ systemProperties.add(source.readInt());
+ }
+ ArraySet<@DeviceStateProperties Integer> physicalProperties = new ArraySet<>();
+ for (int j = 0; j < source.readInt(); j++) {
+ physicalProperties.add(source.readInt());
+ }
+ return new DeviceState.Configuration(identifier, name, systemProperties,
+ physicalProperties);
+ }
+
+ @Override
+ public DeviceState.Configuration[] newArray(int size) {
+ return new DeviceState.Configuration[size];
+ }
+ };
+
+ /** @hide */
+ public static class Builder {
+ private final int mIdentifier;
+ private final String mName;
+ private Set<@SystemDeviceStateProperties Integer> mSystemProperties =
+ Collections.emptySet();
+ private Set<@PhysicalDeviceStateProperties Integer> mPhysicalProperties =
+ Collections.emptySet();
+
+ public Builder(int identifier, String name) {
+ mIdentifier = identifier;
+ mName = name;
+ }
+
+ /** Sets the system properties for this {@link DeviceState.Configuration.Builder} */
+ public Builder setSystemProperties(
+ Set<@SystemDeviceStateProperties Integer> systemProperties) {
+ mSystemProperties = systemProperties;
+ return this;
+ }
+
+ /** Sets the system properties for this {@link DeviceState.Configuration.Builder} */
+ public Builder setPhysicalProperties(
+ Set<@PhysicalDeviceStateProperties Integer> physicalProperties) {
+ mPhysicalProperties = physicalProperties;
+ return this;
+ }
+
+ /**
+ * Returns a new {@link DeviceState.Configuration} whose values match the values set on
+ * the builder.
+ */
+ public DeviceState.Configuration build() {
+ return new DeviceState.Configuration(mIdentifier, mName, mSystemProperties,
+ mPhysicalProperties);
+ }
+ }
+ }
}
diff --git a/core/java/android/hardware/devicestate/DeviceStateInfo.java b/core/java/android/hardware/devicestate/DeviceStateInfo.java
index bc6af37..c319c89 100644
--- a/core/java/android/hardware/devicestate/DeviceStateInfo.java
+++ b/core/java/android/hardware/devicestate/DeviceStateInfo.java
@@ -24,7 +24,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -56,19 +57,19 @@
* The list of states supported by the device.
*/
@NonNull
- public final int[] supportedStates;
+ public final ArrayList<DeviceState> supportedStates;
/**
* The base (non-override) state of the device. The base state is the state of the device
* ignoring any override requests made through a call to {@link DeviceStateManager#requestState(
* DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
*/
- public final int baseState;
+ public final DeviceState baseState;
/**
* The state of the device.
*/
- public final int currentState;
+ public final DeviceState currentState;
/**
* Creates a new instance of {@link DeviceStateInfo}.
@@ -76,8 +77,9 @@
* NOTE: Unlike {@link #DeviceStateInfo(DeviceStateInfo)}, this constructor does not copy the
* supplied parameters.
*/
- public DeviceStateInfo(@NonNull int[] supportedStates, int baseState, int state) {
- this.supportedStates = supportedStates;
+ public DeviceStateInfo(@NonNull List<DeviceState> supportedStates, DeviceState baseState,
+ DeviceState state) {
+ this.supportedStates = new ArrayList<>(supportedStates);
this.baseState = baseState;
this.currentState = state;
}
@@ -87,8 +89,7 @@
* the fields of the returned instance.
*/
public DeviceStateInfo(@NonNull DeviceStateInfo info) {
- this(Arrays.copyOf(info.supportedStates, info.supportedStates.length),
- info.baseState, info.currentState);
+ this(List.copyOf(info.supportedStates), info.baseState, info.currentState);
}
@Override
@@ -96,15 +97,15 @@
if (this == other) return true;
if (other == null || getClass() != other.getClass()) return false;
DeviceStateInfo that = (DeviceStateInfo) other;
- return baseState == that.baseState
- && currentState == that.currentState
- && Arrays.equals(supportedStates, that.supportedStates);
+ return baseState.equals(that.baseState)
+ && currentState.equals(that.currentState)
+ && Objects.equals(supportedStates, that.supportedStates);
}
@Override
public int hashCode() {
int result = Objects.hash(baseState, currentState);
- result = 31 * result + Arrays.hashCode(supportedStates);
+ result = 31 * result + supportedStates.hashCode();
return result;
}
@@ -112,13 +113,13 @@
@ChangeFlags
public int diff(@NonNull DeviceStateInfo other) {
int diff = 0;
- if (!Arrays.equals(supportedStates, other.supportedStates)) {
+ if (!supportedStates.equals(other.supportedStates)) {
diff |= CHANGED_SUPPORTED_STATES;
}
- if (baseState != other.baseState) {
+ if (!baseState.equals(other.baseState)) {
diff |= CHANGED_BASE_STATE;
}
- if (currentState != other.currentState) {
+ if (!currentState.equals(other.currentState)) {
diff |= CHANGED_CURRENT_STATE;
}
return diff;
@@ -126,13 +127,13 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(supportedStates.length);
- for (int i = 0; i < supportedStates.length; i++) {
- dest.writeInt(supportedStates[i]);
+ dest.writeInt(supportedStates.size());
+ for (int i = 0; i < supportedStates.size(); i++) {
+ dest.writeTypedObject(supportedStates.get(i).getConfiguration(), flags);
}
- dest.writeInt(baseState);
- dest.writeInt(currentState);
+ dest.writeTypedObject(baseState.getConfiguration(), flags);
+ dest.writeTypedObject(currentState.getConfiguration(), flags);
}
@Override
@@ -140,16 +141,21 @@
return 0;
}
- public static final @NonNull Creator<DeviceStateInfo> CREATOR = new Creator<DeviceStateInfo>() {
+ public static final @NonNull Creator<DeviceStateInfo> CREATOR = new Creator<>() {
@Override
public DeviceStateInfo createFromParcel(Parcel source) {
final int numberOfSupportedStates = source.readInt();
- final int[] supportedStates = new int[numberOfSupportedStates];
+ final ArrayList<DeviceState> supportedStates = new ArrayList<>(numberOfSupportedStates);
for (int i = 0; i < numberOfSupportedStates; i++) {
- supportedStates[i] = source.readInt();
+ DeviceState.Configuration configuration = source.readTypedObject(
+ DeviceState.Configuration.CREATOR);
+ supportedStates.add(i, new DeviceState(configuration));
}
- final int baseState = source.readInt();
- final int currentState = source.readInt();
+
+ final DeviceState baseState = new DeviceState(
+ source.readTypedObject(DeviceState.Configuration.CREATOR));
+ final DeviceState currentState = new DeviceState(
+ source.readTypedObject(DeviceState.Configuration.CREATOR));
return new DeviceStateInfo(supportedStates, baseState, currentState);
}
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index 8b4d43e..a4c3833 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -49,7 +49,7 @@
*
* @hide
*/
- public static final int INVALID_DEVICE_STATE = -1;
+ public static final int INVALID_DEVICE_STATE_IDENTIFIER = -1;
/**
* The minimum allowed device state identifier.
diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
index 6db5aee..d6cc00d 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
-import android.app.ActivityThread;
import android.content.Context;
import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
import android.os.Binder;
@@ -33,13 +32,9 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.Executor;
/**
@@ -55,18 +50,12 @@
private static final String TAG = "DeviceStateManagerGlobal";
private static final boolean DEBUG = Build.IS_DEBUGGABLE;
- // TODO(b/325124054): Remove when system server refactor is completed
- private static int[] sFoldedDeviceStates = new int[0];
-
/**
* Returns an instance of {@link DeviceStateManagerGlobal}. May return {@code null} if a
* connection with the device state service couldn't be established.
*/
@Nullable
public static DeviceStateManagerGlobal getInstance() {
- // TODO(b/325124054): Remove when system server refactor is completed
- instantiateFoldedStateArray();
-
synchronized (DeviceStateManagerGlobal.class) {
if (sInstance == null) {
IBinder b = ServiceManager.getService(Context.DEVICE_STATE_SERVICE);
@@ -79,16 +68,6 @@
}
}
- // TODO(b/325124054): Remove when system server refactor is completed
- // TODO(b/325330654): Investigate if we need a Context passed in to DSMGlobal
- private static void instantiateFoldedStateArray() {
- Context context = ActivityThread.currentApplication();
- if (context != null) {
- sFoldedDeviceStates = context.getResources().getIntArray(
- com.android.internal.R.array.config_foldedDeviceStates);
- }
- }
-
private final Object mLock = new Object();
@NonNull
private final IDeviceStateManager mDeviceStateManager;
@@ -115,6 +94,7 @@
*
* @see DeviceStateManager#getSupportedStates()
*/
+ // TODO(b/325124054): Remove unused methods when clients are migrated.
public int[] getSupportedStates() {
synchronized (mLock) {
final DeviceStateInfo currentInfo;
@@ -132,12 +112,12 @@
}
}
- return Arrays.copyOf(currentInfo.supportedStates, currentInfo.supportedStates.length);
+ return getSupportedStateIdentifiersLocked(currentInfo.supportedStates);
}
}
/**
- * Returns the {@link List} of supported device states.
+ * Returns {@link List} of supported {@link DeviceState}s.
*
* @see DeviceStateManager#getSupportedDeviceStates()
*/
@@ -158,7 +138,7 @@
}
}
- return createDeviceStateList(currentInfo.supportedStates);
+ return List.copyOf(currentInfo.supportedStates);
}
}
@@ -285,13 +265,14 @@
if (mLastReceivedInfo != null) {
// Copy the array to prevent the callback from modifying the internal state.
- final int[] supportedStates = Arrays.copyOf(mLastReceivedInfo.supportedStates,
- mLastReceivedInfo.supportedStates.length);
+ final int[] supportedStates = getSupportedStateIdentifiersLocked(
+ mLastReceivedInfo.supportedStates);
wrapper.notifySupportedStatesChanged(supportedStates);
- wrapper.notifySupportedDeviceStatesChanged(createDeviceStateList(supportedStates));
- wrapper.notifyBaseStateChanged(mLastReceivedInfo.baseState);
- wrapper.notifyStateChanged(mLastReceivedInfo.currentState);
- wrapper.notifyDeviceStateChanged(createDeviceState(mLastReceivedInfo.currentState));
+ wrapper.notifySupportedDeviceStatesChanged(
+ List.copyOf(mLastReceivedInfo.supportedStates));
+ wrapper.notifyBaseStateChanged(mLastReceivedInfo.baseState.getIdentifier());
+ wrapper.notifyStateChanged(mLastReceivedInfo.currentState.getIdentifier());
+ wrapper.notifyDeviceStateChanged(mLastReceivedInfo.currentState);
}
}
}
@@ -349,6 +330,15 @@
return -1;
}
+ @GuardedBy("mLock")
+ private int[] getSupportedStateIdentifiersLocked(List<DeviceState> states) {
+ int[] identifiers = new int[states.size()];
+ for (int i = 0; i < states.size(); i++) {
+ identifiers[i] = states.get(i).getIdentifier();
+ }
+ return identifiers;
+ }
+
@Nullable
private IBinder findRequestTokenLocked(@NonNull DeviceStateRequest request) {
for (int i = 0; i < mRequests.size(); i++) {
@@ -363,32 +353,31 @@
private void handleDeviceStateInfoChanged(@NonNull DeviceStateInfo info) {
ArrayList<DeviceStateCallbackWrapper> callbacks;
DeviceStateInfo oldInfo;
+ int[] supportedStateIdentifiers;
synchronized (mLock) {
oldInfo = mLastReceivedInfo;
mLastReceivedInfo = info;
callbacks = new ArrayList<>(mCallbacks);
+ supportedStateIdentifiers = getSupportedStateIdentifiersLocked(info.supportedStates);
}
final int diff = oldInfo == null ? ~0 : info.diff(oldInfo);
if ((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0) {
for (int i = 0; i < callbacks.size(); i++) {
- // Copy the array to prevent callbacks from modifying the internal state.
- final int[] supportedStates = Arrays.copyOf(info.supportedStates,
- info.supportedStates.length);
- callbacks.get(i).notifySupportedStatesChanged(supportedStates);
callbacks.get(i).notifySupportedDeviceStatesChanged(
- createDeviceStateList(supportedStates));
+ List.copyOf(info.supportedStates));
+ callbacks.get(i).notifySupportedStatesChanged(supportedStateIdentifiers);
}
}
if ((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0) {
for (int i = 0; i < callbacks.size(); i++) {
- callbacks.get(i).notifyBaseStateChanged(info.baseState);
+ callbacks.get(i).notifyBaseStateChanged(info.baseState.getIdentifier());
}
}
if ((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0) {
for (int i = 0; i < callbacks.size(); i++) {
- callbacks.get(i).notifyStateChanged(info.currentState);
- callbacks.get(i).notifyDeviceStateChanged(createDeviceState(info.currentState));
+ callbacks.get(i).notifyDeviceStateChanged(info.currentState);
+ callbacks.get(i).notifyStateChanged(info.currentState.getIdentifier());
}
}
}
@@ -421,36 +410,6 @@
}
}
- /**
- * Creates a {@link DeviceState} object from a device state identifier, with the
- * {@link DeviceState} property that corresponds to what display is primary.
- *
- */
- // TODO(b/325124054): Remove when system server refactor is completed
- @NonNull
- private DeviceState createDeviceState(int stateIdentifier) {
- final Set<@DeviceState.DeviceStateProperties Integer> properties = new HashSet<>();
- if (ArrayUtils.contains(sFoldedDeviceStates, stateIdentifier)) {
- properties.add(DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY);
- } else {
- properties.add(DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY);
- }
- return new DeviceState(stateIdentifier, "" /* name */, properties);
- }
-
- /**
- * Creates a list of {@link DeviceState} objects from an array of state identifiers.
- */
- // TODO(b/325124054): Remove when system server refactor is completed
- @NonNull
- private List<DeviceState> createDeviceStateList(int[] supportedStates) {
- List<DeviceState> deviceStateList = new ArrayList<>();
- for (int i = 0; i < supportedStates.length; i++) {
- deviceStateList.add(createDeviceState(supportedStates[i]));
- }
- return deviceStateList;
- }
-
private final class DeviceStateManagerCallback extends IDeviceStateManagerCallback.Stub {
@Override
public void onDeviceStateInfoChanged(DeviceStateInfo info) {
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index 62473c5..4328d9f 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -28,6 +28,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
+import android.app.AppGlobals;
import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
@@ -393,15 +394,34 @@
*
* @hide
*/
- public static boolean isStylusPointerIconEnabled(@NonNull Context context) {
+ public static boolean isStylusPointerIconEnabled(@NonNull Context context,
+ boolean forceReloadSetting) {
if (InputProperties.force_enable_stylus_pointer_icon().orElse(false)) {
+ // Sysprop override is set
return true;
}
- return context.getResources()
- .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon)
- && Settings.Secure.getIntForUser(context.getContentResolver(),
- Settings.Secure.STYLUS_POINTER_ICON_ENABLED,
- DEFAULT_STYLUS_POINTER_ICON_ENABLED, UserHandle.USER_CURRENT_OR_SELF) != 0;
+ if (!context.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableStylusPointerIcon)) {
+ // Stylus pointer icons are disabled for the build
+ return false;
+ }
+ if (forceReloadSetting) {
+ return Settings.Secure.getIntForUser(context.getContentResolver(),
+ Settings.Secure.STYLUS_POINTER_ICON_ENABLED,
+ DEFAULT_STYLUS_POINTER_ICON_ENABLED, UserHandle.USER_CURRENT_OR_SELF) != 0;
+ }
+ return AppGlobals.getIntCoreSetting(Settings.Secure.STYLUS_POINTER_ICON_ENABLED,
+ DEFAULT_STYLUS_POINTER_ICON_ENABLED) != 0;
+ }
+
+ /**
+ * Whether a pointer icon will be shown over the location of a stylus pointer.
+ *
+ * @hide
+ * @see #isStylusPointerIconEnabled(Context, boolean)
+ */
+ public static boolean isStylusPointerIconEnabled(@NonNull Context context) {
+ return isStylusPointerIconEnabled(context, false /* forceReloadSetting */);
}
/**
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/os/OWNERS b/core/java/android/os/OWNERS
index b1c24a7..90279c6 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -103,3 +103,6 @@
# ProfilingService
per-file ProfilingServiceManager.java = file:/PERFORMANCE_OWNERS
+
+# Memory
+per-file OomKillRecord.java = file:/MEMORY_OWNERS
\ No newline at end of file
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index b669814..8a17742 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -1259,6 +1259,24 @@
}
/**
+ * Reboot into recovery and wipe the data partition with ext4
+ *
+ * @throws IOException if something goes wrong.
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.RECOVERY,
+ android.Manifest.permission.REBOOT
+ })
+ public void wipePartitionToExt4()
+ throws IOException {
+ // Reformat /data partition with ext4
+ String command = "--wipe_data\n--reformat_data=ext4";
+ rebootRecoveryWithCommand(command);
+ }
+
+ /**
* Reboot into the recovery system with the supplied argument.
* @param args to pass to the recovery utility.
* @throws IOException if something goes wrong.
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/InsetsSource.java b/core/java/android/view/InsetsSource.java
index f9eba29..4ac78f5 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -355,11 +355,17 @@
final Rect frame = getFrame();
if (mBoundingRects == null) {
// No bounding rects set, make a single bounding rect that covers the intersection of
- // the |frame| and the |relativeFrame|.
+ // the |frame| and the |relativeFrame|. Also make it relative to the window origin.
return mTmpBoundingRect.setIntersect(frame, relativeFrame)
- ? new Rect[]{ new Rect(mTmpBoundingRect) }
+ ? new Rect[]{
+ new Rect(
+ mTmpBoundingRect.left - relativeFrame.left,
+ mTmpBoundingRect.top - relativeFrame.top,
+ mTmpBoundingRect.right - relativeFrame.left,
+ mTmpBoundingRect.bottom - relativeFrame.top
+ )
+ }
: NO_BOUNDING_RECTS;
-
}
// Special treatment for captionBar inset type. During drag-resizing, the |frame| and
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index eff35c0c0..a098e4d 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -4099,7 +4099,7 @@
* whose dataspace has RANGE_EXTENDED.
*
* @param sc The layer whose extended range brightness is being specified
- * @param currentBufferRatio The current hdr/sdr ratio of the current buffer. For example
+ * @param currentBufferRatio The current HDR/SDR ratio of the current buffer. For example
* if the buffer was rendered with a target SDR whitepoint of
* 100 nits and a max display brightness of 200 nits, this should
* be set to 2.0f.
@@ -4113,7 +4113,7 @@
*
* <p>Must be finite && >= 1.0f
*
- * @param desiredRatio The desired hdr/sdr ratio. This can be used to communicate the max
+ * @param desiredRatio The desired HDR/SDR ratio. This can be used to communicate the max
* desired brightness range. This is similar to the "max luminance"
* value in other HDR metadata formats, but represented as a ratio of
* the target SDR whitepoint to the max display brightness. The system
@@ -4150,15 +4150,15 @@
}
/**
- * Sets the desired hdr headroom for the layer.
+ * Sets the desired HDR headroom for the layer.
*
* <p>Prefer using this API over {@link #setExtendedRangeBrightness} for formats that
*. conform to HDR video standards like HLG or HDR10 which do not communicate a HDR/SDR
* ratio as part of generating the buffer.
*
- * @param sc The layer whose desired hdr headroom is being specified
+ * @param sc The layer whose desired HDR headroom is being specified
*
- * @param desiredRatio The desired hdr/sdr ratio. This can be used to communicate the max
+ * @param desiredRatio The desired HDR/SDR ratio. This can be used to communicate the max
* desired brightness range. This is similar to the "max luminance"
* value in other HDR metadata formats, but represented as a ratio of
* the target SDR whitepoint to the max display brightness. The system
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index fbefbf3..52ff142 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3732,6 +3732,11 @@
return afm.shouldAlwaysIncludeWebviewInAssistStructure();
}
+ private boolean shouldIncludeInvisibleView(AutofillManager afm) {
+ if (afm == null) return false;
+ return afm.shouldIncludeInvisibleViewInAssistStructure();
+ }
+
/** @hide */
private void populateChildrenForAutofill(ArrayList<View> list, @AutofillFlags int flags) {
final int childrenCount = mChildrenCount;
@@ -3754,7 +3759,7 @@
|| (shouldIncludeAllChildrenViewWithAutofillTypeNotNone(afm)
&& child.getAutofillType() != AUTOFILL_TYPE_NONE)
|| shouldIncludeAllChildrenViews(afm)
- || (Flags.includeInvisibleViewGroupInAssistStructure()
+ || (shouldIncludeInvisibleView(afm)
&& child instanceof ViewGroup && child.getVisibility() != View.VISIBLE)) {
// If the child is a ViewGroup object and its visibility is not visible, include
// it as part of the assist structure. The children of these invisible ViewGroup
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0bc9197..6f178bb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -64,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;
@@ -2867,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;
}
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/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/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index ae4a7d3..9708591 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -48,6 +48,7 @@
import android.content.res.Resources;
import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IBinder;
@@ -67,6 +68,8 @@
import android.view.accessibility.AccessibilityEvent.EventType;
import com.android.internal.R;
+import com.android.internal.accessibility.common.ShortcutConstants;
+import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IntPair;
@@ -78,6 +81,8 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.Executor;
/**
@@ -189,11 +194,13 @@
* <p>Note: Keep in sync with {@link #SHORTCUT_TYPES}.</p>
* @hide
*/
+ // TODO(b/323686675): reuse the one defined in ShortcutConstants
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
// LINT.IfChange(shortcut_type_intdef)
ACCESSIBILITY_BUTTON,
- ACCESSIBILITY_SHORTCUT_KEY
+ ACCESSIBILITY_SHORTCUT_KEY,
+ UserShortcutType.QUICK_SETTINGS,
// LINT.ThenChange(:shortcut_type_array)
})
public @interface ShortcutType {}
@@ -207,6 +214,7 @@
// LINT.IfChange(shortcut_type_array)
ACCESSIBILITY_BUTTON,
ACCESSIBILITY_SHORTCUT_KEY,
+ UserShortcutType.QUICK_SETTINGS,
// LINT.ThenChange(:shortcut_type_intdef)
};
@@ -1631,6 +1639,74 @@
}
/**
+ * Turns on or off a shortcut type of the accessibility features. The shortcut type is one
+ * of the shortcut defined in the {@link ShortcutConstants.USER_SHORTCUT_TYPES}.
+ *
+ * @throws SecurityException if the app does not hold the
+ * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+ public void enableShortcutsForTargets(boolean enable,
+ @UserShortcutType int shortcutTypes, @NonNull Set<String> targets,
+ @UserIdInt int userId) {
+ final IAccessibilityManager service;
+ synchronized (mLock) {
+ service = getServiceLocked();
+ if (service == null) {
+ return;
+ }
+ }
+ try {
+ service.enableShortcutsForTargets(
+ enable, shortcutTypes, targets.stream().toList(), userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns accessibility feature's component and the provided tile map. This includes the
+ * TileService provided by the AccessibilityService or Accessibility Activity and the tile
+ * component provided by the framework's feature.
+ *
+ * @return a map of a feature's component name, and its provided tile's component name. The
+ * returned map's keys and values are not null. If a feature doesn't provide a tile, it won't
+ * have an entry in this map.
+ * @hide
+ * @see ShortcutConstants.A11Y_FEATURE_TO_FRAMEWORK_TILE
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+ @NonNull
+ public Map<ComponentName, ComponentName> getA11yFeatureToTileMap(@UserIdInt int userId) {
+ final IAccessibilityManager service;
+ Map<ComponentName, ComponentName> a11yFeatureToTileMap = new ArrayMap<>();
+ synchronized (mLock) {
+ service = getServiceLocked();
+ if (service == null) {
+ return a11yFeatureToTileMap;
+ }
+ }
+ try {
+ Bundle a11yFeatureToTile = service.getA11yFeatureToTileMap(userId);
+ for (String key : a11yFeatureToTile.keySet()) {
+ ComponentName feature = ComponentName.unflattenFromString(key);
+ if (feature == null) {
+ continue;
+ }
+ ComponentName tileService = a11yFeatureToTile.getParcelable(key,
+ ComponentName.class);
+ if (tileService != null) {
+ a11yFeatureToTileMap.put(feature, tileService);
+ }
+ }
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ return a11yFeatureToTileMap;
+ }
+
+ /**
* Register the provided {@link RemoteAction} with the given actionId
* <p>
* To perform established system actions, an accessibility service uses the GLOBAL_ACTION
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 9617606..e215950 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -22,6 +22,7 @@
import android.accessibilityservice.IAccessibilityServiceClient;
import android.content.ComponentName;
import android.content.pm.ParceledListSlice;
+import android.os.Bundle;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
@@ -143,4 +144,10 @@
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE)")
oneway void notifyQuickSettingsTilesChanged(int userId, in List<ComponentName> tileComponentNames);
+
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)")
+ oneway void enableShortcutsForTargets(boolean enable, int shortcutTypes, in List<String> shortcutTargets, int userId);
+
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)")
+ Bundle getA11yFeatureToTileMap(int userId);
}
diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java
index 334c2b77..1acfc1b 100644
--- a/core/java/android/view/autofill/AutofillFeatureFlags.java
+++ b/core/java/android/view/autofill/AutofillFeatureFlags.java
@@ -220,6 +220,19 @@
DEVICE_CONFIG_ALWAYS_INCLUDE_WEBVIEW_IN_ASSIST_STRUCTURE =
"always_include_webview_in_assist_structure";
+ /**
+ * Whether to include invisible views in the assist structure. Including invisible views can fix
+ * some cases in which Session is destroyed earlier than it is suppose to.
+ *
+ * <p>See
+ * frameworks/base/services/autofill/bugfixes.aconfig#include_invisible_view_group_in_assist_structure
+ * for more information.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_INCLUDE_INVISIBLE_VIEW_GROUP_IN_ASSIST_STRUCTURE =
+ "include_invisible_view_group_in_assist_structure";
+
// END AUTOFILL FOR ALL APPS FLAGS //
@@ -473,6 +486,13 @@
DEVICE_CONFIG_ALWAYS_INCLUDE_WEBVIEW_IN_ASSIST_STRUCTURE, true);
}
+ /** @hide */
+ public static boolean shouldIncludeInvisibleViewInAssistStructure() {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_INCLUDE_INVISIBLE_VIEW_GROUP_IN_ASSIST_STRUCTURE,
+ false);
+ }
/**
* Whether should enable multi-line filter
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index cf6b9e5..1484bfb 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -739,6 +739,9 @@
// Indicate whether WebView should always be included in the assist structure
private boolean mShouldAlwaysIncludeWebviewInAssistStructure;
+ // Indicate whether invisibles views should be included in the assist structure
+ private boolean mShouldIncludeInvisibleViewInAssistStructure;
+
// Controls logic around apps changing some properties of their views when activity loses
// focus due to autofill showing biometric activity, password manager, or password breach check.
private boolean mRelayoutFix;
@@ -968,6 +971,9 @@
mShouldAlwaysIncludeWebviewInAssistStructure =
AutofillFeatureFlags.shouldAlwaysIncludeWebviewInAssistStructure();
+ mShouldIncludeInvisibleViewInAssistStructure =
+ AutofillFeatureFlags.shouldIncludeInvisibleViewInAssistStructure();
+
mRelayoutFix = Flags.relayout();
mIsCredmanIntegrationEnabled = Flags.autofillCredmanIntegration();
}
@@ -1055,6 +1061,13 @@
}
/**
+ * @hide
+ */
+ public boolean shouldIncludeInvisibleViewInAssistStructure() {
+ return mShouldIncludeInvisibleViewInAssistStructure;
+ }
+
+ /**
* Get the denied or allowed activitiy names under specified package from the list string and
* set it in fields accordingly
*
@@ -1480,20 +1493,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 +1527,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 +1624,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/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 8ddc178..7885cd9 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -900,6 +900,8 @@
+ Integer.toHexString(mIsDefaultResId));
pw.println(prefix + "Service:");
mService.dump(pw, prefix + " ");
+ pw.println(prefix + "InputMethodSubtype array: count=" + mSubtypes.getCount());
+ mSubtypes.dump(pw, prefix + " ");
}
@Override
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index b0b9460..be91cfb 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -28,6 +28,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.Printer;
import android.util.Slog;
import com.android.internal.inputmethod.SubtypeLocaleUtils;
@@ -791,6 +792,20 @@
dest.writeInt(mIsAsciiCapable ? 1 : 0);
}
+ void dump(@NonNull Printer pw, @NonNull String prefix) {
+ pw.println(prefix + "mSubtypeNameOverride=" + mSubtypeNameOverride
+ + " mPkLanguageTag=" + mPkLanguageTag
+ + " mPkLayoutType=" + mPkLayoutType
+ + " mSubtypeId=" + mSubtypeId
+ + " mSubtypeLocale=" + mSubtypeLocale
+ + " mSubtypeLanguageTag=" + mSubtypeLanguageTag
+ + " mSubtypeMode=" + mSubtypeMode
+ + " mIsAuxiliary=" + mIsAuxiliary
+ + " mOverridesImplicitlyEnabledSubtype=" + mOverridesImplicitlyEnabledSubtype
+ + " mIsAsciiCapable=" + mIsAsciiCapable
+ + " mSubtypeHashCode=" + mSubtypeHashCode);
+ }
+
public static final @android.annotation.NonNull Parcelable.Creator<InputMethodSubtype> CREATOR
= new Parcelable.Creator<InputMethodSubtype>() {
@Override
diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
index ee36dc7..c243a22 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
@@ -16,9 +16,11 @@
package android.view.inputmethod;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.BadParcelableException;
import android.os.Parcel;
+import android.util.Printer;
import android.util.Slog;
import java.io.ByteArrayInputStream;
@@ -174,6 +176,19 @@
private volatile byte[] mCompressedData;
private volatile int mDecompressedSize;
+ void dump(@NonNull Printer pw, @NonNull String prefix) {
+ final var innerPrefix = prefix + " ";
+ for (int i = 0; i < mCount; i++) {
+ pw.println(prefix + "InputMethodSubtype #" + i + ":");
+ final var subtype = get(i);
+ if (subtype != null) {
+ subtype.dump(pw, innerPrefix);
+ } else {
+ pw.println(innerPrefix + "missing subtype");
+ }
+ }
+ }
+
private static byte[] marshall(final InputMethodSubtype[] array) {
Parcel parcel = null;
try {
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/accessibility/common/ShortcutConstants.java b/core/java/com/android/internal/accessibility/common/ShortcutConstants.java
index 7ec8838..c08968d 100644
--- a/core/java/com/android/internal/accessibility/common/ShortcutConstants.java
+++ b/core/java/com/android/internal/accessibility/common/ShortcutConstants.java
@@ -16,10 +16,23 @@
package com.android.internal.accessibility.common;
+import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_TILE_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_TILE_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.FONT_SIZE_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.FONT_SIZE_TILE_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.ONE_HANDED_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.ONE_HANDED_TILE_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME;
+
import android.annotation.IntDef;
+import android.content.ComponentName;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Map;
/**
* Collection of common constants for accessibility shortcut.
@@ -44,6 +57,10 @@
* choose accessibility shortcut as preferred shortcut.
* {@code TRIPLETAP} for displaying specifying magnification to be toggled via quickly
* tapping screen 3 times as preferred shortcut.
+ * {@code TWOFINGER_DOUBLETAP} for displaying specifying magnification to be toggled via
+ * quickly tapping screen 2 times with two fingers as preferred shortcut.
+ * {@code QUICK_SETTINGS} for displaying specifying the accessibility services or features which
+ * choose Quick Settings as preferred shortcut.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
@@ -51,12 +68,18 @@
UserShortcutType.SOFTWARE,
UserShortcutType.HARDWARE,
UserShortcutType.TRIPLETAP,
+ UserShortcutType.TWOFINGER_DOUBLETAP,
+ UserShortcutType.QUICK_SETTINGS,
})
public @interface UserShortcutType {
int DEFAULT = 0;
- int SOFTWARE = 1; // 1 << 0
- int HARDWARE = 2; // 1 << 1
- int TRIPLETAP = 4; // 1 << 2
+ // LINT.IfChange(shortcut_type_intdef)
+ int SOFTWARE = 1 << 0;
+ int HARDWARE = 1 << 1;
+ int TRIPLETAP = 1 << 2;
+ int TWOFINGER_DOUBLETAP = 1 << 3;
+ int QUICK_SETTINGS = 1 << 4;
+ // LINT.ThenChange(:shortcut_type_array)
}
/**
@@ -64,9 +87,13 @@
* non-default IntDef types.
*/
public static final int[] USER_SHORTCUT_TYPES = {
+ // LINT.IfChange(shortcut_type_array)
UserShortcutType.SOFTWARE,
UserShortcutType.HARDWARE,
- UserShortcutType.TRIPLETAP
+ UserShortcutType.TRIPLETAP,
+ UserShortcutType.TWOFINGER_DOUBLETAP,
+ UserShortcutType.QUICK_SETTINGS,
+ // LINT.ThenChange(:shortcut_type_intdef)
};
@@ -109,4 +136,30 @@
int LAUNCH = 0;
int EDIT = 1;
}
+
+ /**
+ * Annotation for different FAB shortcut type's menu size
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FloatingMenuSize.UNKNOWN,
+ FloatingMenuSize.SMALL,
+ FloatingMenuSize.LARGE,
+ })
+ public @interface FloatingMenuSize {
+ int UNKNOWN = -1;
+ int SMALL = 0;
+ int LARGE = 1;
+ }
+
+ /**
+ * A map of a11y feature to its qs tile component
+ */
+ public static final Map<ComponentName, ComponentName> A11Y_FEATURE_TO_FRAMEWORK_TILE = Map.of(
+ COLOR_INVERSION_COMPONENT_NAME, COLOR_INVERSION_TILE_COMPONENT_NAME,
+ DALTONIZER_COMPONENT_NAME, DALTONIZER_TILE_COMPONENT_NAME,
+ ONE_HANDED_COMPONENT_NAME, ONE_HANDED_TILE_COMPONENT_NAME,
+ REDUCE_BRIGHT_COLORS_COMPONENT_NAME, REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME,
+ FONT_SIZE_COMPONENT_NAME, FONT_SIZE_TILE_COMPONENT_NAME
+ );
}
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
index 4f9fc39..e8472d4 100644
--- a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
@@ -70,6 +70,13 @@
public @interface A11yTextChangeType {
}
+ /** Denotes the accessibility enabled status */
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface State {
+ int OFF = 0;
+ int ON = 1;
+ }
+
/** Specifies no content has been changed for accessibility. */
public static final int NONE = 0;
/** Specifies some readable sequence has been changed. */
diff --git a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
index 3fd3030..f9c4d37 100644
--- a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
+++ b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
@@ -53,10 +53,13 @@
* Opts in component id into colon-separated {@link UserShortcutType}
* key's string from Settings.
*
- * @param context The current context.
+ * @param context The current context.
* @param shortcutType The preferred shortcut type user selected.
- * @param componentId The component id that need to be opted in Settings.
+ * @param componentId The component id that need to be opted in Settings.
+ * @deprecated Use
+ * {@link AccessibilityManager#enableShortcutsForTargets(boolean, int, Set, int)}
*/
+ @Deprecated
public static void optInValueToSettings(Context context, @UserShortcutType int shortcutType,
@NonNull String componentId) {
final StringJoiner joiner = new StringJoiner(String.valueOf(SERVICES_SEPARATOR));
@@ -83,7 +86,11 @@
* @param context The current context.
* @param shortcutType The preferred shortcut type user selected.
* @param componentId The component id that need to be opted out of Settings.
+ *
+ * @deprecated Use
+ * {@link AccessibilityManager#enableShortcutForTargets(boolean, int, Set, int)}
*/
+ @Deprecated
public static void optOutValueFromSettings(
Context context, @UserShortcutType int shortcutType, @NonNull String componentId) {
final StringJoiner joiner = new StringJoiner(String.valueOf(SERVICES_SEPARATOR));
@@ -166,6 +173,10 @@
return Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
case UserShortcutType.TRIPLETAP:
return Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED;
+ case UserShortcutType.TWOFINGER_DOUBLETAP:
+ return Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED;
+ case UserShortcutType.QUICK_SETTINGS:
+ return Settings.Secure.ACCESSIBILITY_QS_TARGETS;
default:
throw new IllegalArgumentException(
"Unsupported user shortcut type: " + type);
@@ -252,10 +263,13 @@
* If you just want to know the current state, you can use
* {@link AccessibilityManager#getAccessibilityShortcutTargets(int)}
*/
+ @NonNull
public static Set<String> getShortcutTargetsFromSettings(
Context context, @UserShortcutType int shortcutType, int userId) {
final String targetKey = convertToKey(shortcutType);
- if (Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED.equals(targetKey)) {
+ if (Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED.equals(targetKey)
+ || Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED
+ .equals(targetKey)) {
boolean magnificationEnabled = Settings.Secure.getIntForUser(
context.getContentResolver(), targetKey, /* def= */ 0, userId) == 1;
return magnificationEnabled ? Set.of(MAGNIFICATION_CONTROLLER_NAME)
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 2f1d654..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;
@@ -2578,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(
@@ -3942,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/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 6ffc638..a2efbd2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -370,9 +370,10 @@
/**
* Enters stage split from a current running app.
*
+ * @param displayId the id of the current display.
* @param leftOrTop indicates where the stage split is.
*/
- void enterStageSplitFromRunningApp(boolean leftOrTop);
+ void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop);
/**
* Shows the media output switcher dialog.
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 1504a00..a98f947 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -410,6 +410,7 @@
stats[sub_heap].swappedOut += usage.swap;
stats[sub_heap].swappedOutPss += usage.swap_pss;
}
+ return true;
};
return meminfo::ForEachVmaFromFile(smaps_path, vma_scan);
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/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-watch/colors.xml b/core/res/res/values-watch/colors.xml
index 0b00bd8..e2b7505 100644
--- a/core/res/res/values-watch/colors.xml
+++ b/core/res/res/values-watch/colors.xml
@@ -18,11 +18,26 @@
<resources>
<color name="system_error_light">#B3261E</color>
<color name="system_on_error_light">#FFFFFF</color>
- <color name="system_error_container_light">#F9DEDC</color>
+ <color name="system_error_container_light">#F7DCDA</color>
<color name="system_on_error_container_light">#410E0B</color>
- <color name="system_error_dark">#EC928E</color>
- <color name="system_on_error_dark">#410E0B</color>
- <color name="system_error_container_dark">#F2B8B5</color>
- <color name="system_on_error_container_dark">#601410</color>
+ <color name="system_error_dark">#F2B8B5</color>
+ <color name="system_on_error_dark">#601410</color>
+ <color name="system_error_container_dark">#FF8986</color>
+ <color name="system_on_error_container_dark">#410E0B</color>
+
+ <!-- With material deprecation of 'background' in favor of 'surface' we flatten these
+ on watches to match the black background requirements -->
+ <color name="system_surface_dark">#000000</color>
+ <color name="system_surface_dim_dark">#000000</color>
+ <color name="system_surface_bright_dark">#000000</color>
+
+ <!-- Wear flattens the typical 5 container layers to 3; container + high & low -->
+ <color name="system_surface_container_dark">#303030</color>
+ <color name="system_surface_variant_dark">#303030</color>
+ <color name="system_surface_container_high_dark">#474747</color>
+ <color name="system_surface_container_highest_dark">#474747</color>
+ <color name="system_surface_container_low_dark">#252626</color>
+ <color name="system_surface_container_lowest_dark">#252626</color>
+
</resources>
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_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/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/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index 936f4d7..61e05da 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -291,6 +291,17 @@
}
@Test
+ public void testCalculateBoundingRects_noBoundingRectsAndFrameNotAtOrigin_createsSingleRect() {
+ mSource.setFrame(new Rect(100, 100, 1200, 200));
+ mSource.setBoundingRects(null);
+
+ final Rect[] rects = mSource.calculateBoundingRects(new Rect(100, 100, 1100, 1100), false);
+
+ assertEquals(1, rects.length);
+ assertEquals(new Rect(0, 0, 1000, 100), rects[0]);
+ }
+
+ @Test
public void testCalculateBoundingRects_noBoundingRectsAndLargerFrame_singleRectFitsRelFrame() {
mSource.setFrame(new Rect(0, 0, 1000, 100));
mSource.setBoundingRects(null);
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java
index e2f2554..1013bf5 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java
@@ -16,13 +16,24 @@
package android.view.accessibility;
+import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_TILE_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
+import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_TILE_COMPONENT_NAME;
+
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -34,6 +45,8 @@
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.RemoteException;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -41,6 +54,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
+import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.util.IntPair;
import com.android.server.accessibility.test.MessageCapturingHandler;
@@ -54,6 +68,8 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.Executors;
/**
@@ -263,6 +279,75 @@
verify(mMockService).unregisterProxyForDisplay(proxy.getDisplayId());
}
+ @Test
+ public void getA11yFeatureToTileMap_catchRemoteExceptionAndRethrow() throws Exception {
+ AccessibilityManager manager = createManager(WITH_A11Y_ENABLED);
+ doThrow(new RemoteException(new SecurityException()))
+ .when(mMockService)
+ .getA11yFeatureToTileMap(anyInt());
+
+ Throwable rethrownException = assertThrows(RuntimeException.class,
+ () -> manager.getA11yFeatureToTileMap(UserHandle.USER_CURRENT));
+ assertThat(rethrownException.getCause().getCause()).isInstanceOf(SecurityException.class);
+ }
+
+ @Test
+ public void getA11yFeatureToTileMap_verifyServiceMethodCalled() throws Exception {
+ AccessibilityManager manager = createManager(WITH_A11Y_ENABLED);
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(
+ COLOR_INVERSION_COMPONENT_NAME.flattenToString(),
+ COLOR_INVERSION_TILE_COMPONENT_NAME);
+ bundle.putParcelable(
+ DALTONIZER_COMPONENT_NAME.flattenToString(),
+ DALTONIZER_TILE_COMPONENT_NAME);
+ when(mMockService.getA11yFeatureToTileMap(UserHandle.USER_CURRENT)).thenReturn(bundle);
+
+ assertThat(manager.getA11yFeatureToTileMap(UserHandle.USER_CURRENT))
+ .containsExactlyEntriesIn(Map.of(
+ COLOR_INVERSION_COMPONENT_NAME, COLOR_INVERSION_TILE_COMPONENT_NAME,
+ DALTONIZER_COMPONENT_NAME, DALTONIZER_TILE_COMPONENT_NAME
+ ));
+ verify(mMockService).getA11yFeatureToTileMap(UserHandle.USER_CURRENT);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_catchRemoteExceptionAndRethrow() throws Exception {
+ AccessibilityManager manager = createManager(WITH_A11Y_ENABLED);
+ doThrow(new RemoteException(new SecurityException()))
+ .when(mMockService)
+ .enableShortcutsForTargets(anyBoolean(), anyInt(), anyList(), anyInt());
+
+ Throwable rethrownException = assertThrows(RuntimeException.class,
+ () -> manager.enableShortcutsForTargets(
+ /* enable= */ false,
+ UserShortcutType.HARDWARE,
+ Set.of(DALTONIZER_COMPONENT_NAME.flattenToString()),
+ UserHandle.USER_CURRENT
+ ));
+ assertThat(rethrownException.getCause().getCause()).isInstanceOf(SecurityException.class);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_verifyServiceMethodCalled() throws Exception {
+ AccessibilityManager manager = createManager(WITH_A11Y_ENABLED);
+ int shortcutTypes = UserShortcutType.HARDWARE | UserShortcutType.TRIPLETAP;
+
+ manager.enableShortcutsForTargets(
+ /* enable= */ false,
+ shortcutTypes,
+ Set.of(DALTONIZER_COMPONENT_NAME.flattenToString()),
+ UserHandle.USER_CURRENT
+ );
+
+ verify(mMockService).enableShortcutsForTargets(
+ /* enable= */ false,
+ shortcutTypes,
+ List.of(DALTONIZER_COMPONENT_NAME.flattenToString()),
+ UserHandle.USER_CURRENT
+ );
+ }
+
private class MyAccessibilityProxy extends AccessibilityDisplayProxy {
MyAccessibilityProxy(int displayId,
@NonNull List<AccessibilityServiceInfo> serviceInfos) {
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateInfoTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateInfoTest.java
index dcef0a7..76772b7 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateInfoTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateInfoTest.java
@@ -20,16 +20,20 @@
import static junit.framework.Assert.assertNotNull;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
+import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.List;
+
/**
* Unit tests for {@link DeviceStateInfo}.
* <p/>
@@ -38,11 +42,20 @@
@RunWith(JUnit4.class)
@SmallTest
public final class DeviceStateInfoTest {
+
+ private static final DeviceState DEVICE_STATE_0 = new DeviceState(
+ new DeviceState.Configuration.Builder(0, "STATE_0").build());
+ private static final DeviceState DEVICE_STATE_1 = new DeviceState(
+ new DeviceState.Configuration.Builder(1, "STATE_1").build());
+ private static final DeviceState DEVICE_STATE_2 = new DeviceState(
+ new DeviceState.Configuration.Builder(2, "STATE_2").build());
+
@Test
public void create() {
- final int[] supportedStates = new int[] { 0, 1, 2 };
- final int baseState = 0;
- final int currentState = 2;
+ final List<DeviceState> supportedStates = List.of(DEVICE_STATE_0, DEVICE_STATE_1,
+ DEVICE_STATE_2);
+ final DeviceState baseState = DEVICE_STATE_0;
+ final DeviceState currentState = DEVICE_STATE_2;
final DeviceStateInfo info = new DeviceStateInfo(supportedStates, baseState, currentState);
assertNotNull(info.supportedStates);
@@ -53,27 +66,30 @@
@Test
public void equals() {
- final int[] supportedStates = new int[] { 0, 1, 2 };
- final int baseState = 0;
- final int currentState = 2;
+ final List<DeviceState> supportedStates = List.of(DEVICE_STATE_0, DEVICE_STATE_1,
+ DEVICE_STATE_2);
+ final DeviceState baseState = DEVICE_STATE_0;
+ final DeviceState currentState = DEVICE_STATE_2;
final DeviceStateInfo info = new DeviceStateInfo(supportedStates, baseState, currentState);
- assertTrue(info.equals(info));
+ Assert.assertEquals(info, info);
final DeviceStateInfo sameInfo = new DeviceStateInfo(supportedStates, baseState,
currentState);
- assertTrue(info.equals(sameInfo));
+ Assert.assertEquals(info, sameInfo);
- final DeviceStateInfo differentInfo = new DeviceStateInfo(new int[]{ 0, 2}, baseState,
+ final DeviceStateInfo differentInfo = new DeviceStateInfo(
+ List.of(DEVICE_STATE_0, DEVICE_STATE_2), baseState,
currentState);
- assertFalse(info.equals(differentInfo));
+ assertNotEquals(info, differentInfo);
}
@Test
public void diff_sameObject() {
- final int[] supportedStates = new int[] { 0, 1, 2 };
- final int baseState = 0;
- final int currentState = 2;
+ final List<DeviceState> supportedStates = List.of(DEVICE_STATE_0, DEVICE_STATE_1,
+ DEVICE_STATE_2);
+ final DeviceState baseState = DEVICE_STATE_0;
+ final DeviceState currentState = DEVICE_STATE_2;
final DeviceStateInfo info = new DeviceStateInfo(supportedStates, baseState, currentState);
assertEquals(0, info.diff(info));
@@ -81,8 +97,10 @@
@Test
public void diff_differentSupportedStates() {
- final DeviceStateInfo info = new DeviceStateInfo(new int[] { 1 }, 0, 0);
- final DeviceStateInfo otherInfo = new DeviceStateInfo(new int[] { 2 }, 0, 0);
+ final DeviceStateInfo info = new DeviceStateInfo(List.of(DEVICE_STATE_1), DEVICE_STATE_0,
+ DEVICE_STATE_0);
+ final DeviceStateInfo otherInfo = new DeviceStateInfo(List.of(DEVICE_STATE_2),
+ DEVICE_STATE_0, DEVICE_STATE_0);
final int diff = info.diff(otherInfo);
assertTrue((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0);
assertFalse((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0);
@@ -91,8 +109,10 @@
@Test
public void diff_differentNonOverrideState() {
- final DeviceStateInfo info = new DeviceStateInfo(new int[] { 1 }, 1, 0);
- final DeviceStateInfo otherInfo = new DeviceStateInfo(new int[] { 1 }, 2, 0);
+ final DeviceStateInfo info = new DeviceStateInfo(List.of(DEVICE_STATE_1), DEVICE_STATE_1,
+ DEVICE_STATE_0);
+ final DeviceStateInfo otherInfo = new DeviceStateInfo(List.of(DEVICE_STATE_1),
+ DEVICE_STATE_2, DEVICE_STATE_0);
final int diff = info.diff(otherInfo);
assertFalse((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0);
assertTrue((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0);
@@ -101,8 +121,10 @@
@Test
public void diff_differentState() {
- final DeviceStateInfo info = new DeviceStateInfo(new int[] { 1 }, 0, 1);
- final DeviceStateInfo otherInfo = new DeviceStateInfo(new int[] { 1 }, 0, 2);
+ final DeviceStateInfo info = new DeviceStateInfo(List.of(DEVICE_STATE_1), DEVICE_STATE_0,
+ DEVICE_STATE_1);
+ final DeviceStateInfo otherInfo = new DeviceStateInfo(List.of(DEVICE_STATE_1),
+ DEVICE_STATE_0, DEVICE_STATE_2);
final int diff = info.diff(otherInfo);
assertFalse((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0);
assertFalse((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0);
@@ -111,9 +133,10 @@
@Test
public void writeToParcel() {
- final int[] supportedStates = new int[] { 0, 1, 2 };
- final int nonOverrideState = 0;
- final int state = 2;
+ final List<DeviceState> supportedStates = List.of(DEVICE_STATE_0, DEVICE_STATE_1,
+ DEVICE_STATE_2);
+ final DeviceState nonOverrideState = DEVICE_STATE_0;
+ final DeviceState state = DEVICE_STATE_2;
final DeviceStateInfo originalInfo =
new DeviceStateInfo(supportedStates, nonOverrideState, state);
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
index 03c38cc..ee238c0 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
@@ -41,6 +41,7 @@
import org.junit.runners.JUnit4;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
@@ -51,8 +52,10 @@
@RunWith(JUnit4.class)
@SmallTest
public final class DeviceStateManagerGlobalTest {
- private static final int DEFAULT_DEVICE_STATE = 0;
- private static final int OTHER_DEVICE_STATE = 1;
+ private static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(
+ new DeviceState.Configuration.Builder(0 /* identifier */, "" /* name */).build());
+ private static final DeviceState OTHER_DEVICE_STATE = new DeviceState(
+ new DeviceState.Configuration.Builder(1 /* identifier */, "" /* name */).build());
private TestDeviceStateManagerService mService;
private DeviceStateManagerGlobal mDeviceStateManagerGlobal;
@@ -76,41 +79,37 @@
ConcurrentUtils.DIRECT_EXECUTOR);
// Verify initial callbacks
- verify(callback1).onSupportedStatesChanged(eq(mService.getSupportedStates()));
- verify(callback1).onBaseStateChanged(eq(mService.getBaseState()));
- verify(callback1).onStateChanged(eq(mService.getMergedState()));
- verify(callback2).onSupportedStatesChanged(eq(mService.getSupportedStates()));
- verify(callback2).onBaseStateChanged(eq(mService.getBaseState()));
- verify(callback2).onStateChanged(eq(mService.getMergedState()));
+ verify(callback1).onSupportedStatesChanged(eq(mService.getSupportedDeviceStates()));
+ verify(callback1).onDeviceStateChanged(eq(mService.getMergedState()));
+ verify(callback2).onDeviceStateChanged(eq(mService.getMergedState()));
reset(callback1);
reset(callback2);
// Change the supported states and verify callback
- mService.setSupportedStates(new int[]{ DEFAULT_DEVICE_STATE });
- verify(callback1).onSupportedStatesChanged(eq(mService.getSupportedStates()));
- verify(callback2).onSupportedStatesChanged(eq(mService.getSupportedStates()));
- mService.setSupportedStates(new int[]{ DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE });
+ mService.setSupportedStates(List.of(DEFAULT_DEVICE_STATE));
+ verify(callback1).onSupportedStatesChanged(eq(mService.getSupportedDeviceStates()));
+ verify(callback2).onSupportedStatesChanged(eq(mService.getSupportedDeviceStates()));
+ mService.setSupportedStates(List.of(DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE));
reset(callback1);
reset(callback2);
// Change the base state and verify callback
mService.setBaseState(OTHER_DEVICE_STATE);
- verify(callback1).onBaseStateChanged(eq(mService.getBaseState()));
- verify(callback1).onStateChanged(eq(mService.getMergedState()));
- verify(callback2).onBaseStateChanged(eq(mService.getBaseState()));
- verify(callback2).onStateChanged(eq(mService.getMergedState()));
+ verify(callback1).onDeviceStateChanged(eq(mService.getMergedState()));
+ verify(callback2).onDeviceStateChanged(eq(mService.getMergedState()));
reset(callback1);
reset(callback2);
// Change the requested state and verify callback
- DeviceStateRequest request = DeviceStateRequest.newBuilder(DEFAULT_DEVICE_STATE).build();
+ DeviceStateRequest request = DeviceStateRequest.newBuilder(
+ DEFAULT_DEVICE_STATE.getIdentifier()).build();
mDeviceStateManagerGlobal.requestState(request, null /* executor */, null /* callback */);
- verify(callback1).onStateChanged(eq(mService.getMergedState()));
- verify(callback2).onStateChanged(eq(mService.getMergedState()));
+ verify(callback1).onDeviceStateChanged(eq(mService.getMergedState()));
+ verify(callback2).onDeviceStateChanged(eq(mService.getMergedState()));
}
@Test
@@ -121,14 +120,13 @@
ConcurrentUtils.DIRECT_EXECUTOR);
// Verify initial callbacks
- verify(callback).onSupportedStatesChanged(eq(mService.getSupportedStates()));
- verify(callback).onBaseStateChanged(eq(mService.getBaseState()));
- verify(callback).onStateChanged(eq(mService.getMergedState()));
+ verify(callback).onSupportedStatesChanged(eq(mService.getSupportedDeviceStates()));
+ verify(callback).onDeviceStateChanged(eq(mService.getMergedState()));
reset(callback);
mDeviceStateManagerGlobal.unregisterDeviceStateCallback(callback);
- mService.setSupportedStates(new int[]{OTHER_DEVICE_STATE});
+ mService.setSupportedStates(List.of(OTHER_DEVICE_STATE));
mService.setBaseState(OTHER_DEVICE_STATE);
verifyZeroInteractions(callback);
}
@@ -139,18 +137,19 @@
mDeviceStateManagerGlobal.registerDeviceStateCallback(callback,
ConcurrentUtils.DIRECT_EXECUTOR);
- verify(callback).onStateChanged(eq(mService.getBaseState()));
+ verify(callback).onDeviceStateChanged(eq(mService.getBaseState()));
reset(callback);
- DeviceStateRequest request = DeviceStateRequest.newBuilder(OTHER_DEVICE_STATE).build();
+ DeviceStateRequest request = DeviceStateRequest.newBuilder(
+ OTHER_DEVICE_STATE.getIdentifier()).build();
mDeviceStateManagerGlobal.requestState(request, null /* executor */, null /* callback */);
- verify(callback).onStateChanged(eq(OTHER_DEVICE_STATE));
+ verify(callback).onDeviceStateChanged(eq(OTHER_DEVICE_STATE));
reset(callback);
mDeviceStateManagerGlobal.cancelStateRequest();
- verify(callback).onStateChanged(eq(mService.getBaseState()));
+ verify(callback).onDeviceStateChanged(eq(mService.getBaseState()));
}
@Test
@@ -159,22 +158,20 @@
mDeviceStateManagerGlobal.registerDeviceStateCallback(callback,
ConcurrentUtils.DIRECT_EXECUTOR);
- verify(callback).onBaseStateChanged(eq(mService.getBaseState()));
- verify(callback).onStateChanged(eq(mService.getBaseState()));
+ verify(callback).onDeviceStateChanged(eq(mService.getBaseState()));
reset(callback);
- DeviceStateRequest request = DeviceStateRequest.newBuilder(OTHER_DEVICE_STATE).build();
+ DeviceStateRequest request = DeviceStateRequest.newBuilder(
+ OTHER_DEVICE_STATE.getIdentifier()).build();
mDeviceStateManagerGlobal.requestBaseStateOverride(request, null /* executor */,
null /* callback */);
- verify(callback).onBaseStateChanged(eq(OTHER_DEVICE_STATE));
- verify(callback).onStateChanged(eq(OTHER_DEVICE_STATE));
+ verify(callback).onDeviceStateChanged(eq(OTHER_DEVICE_STATE));
reset(callback);
mDeviceStateManagerGlobal.cancelBaseStateOverride();
- verify(callback).onBaseStateChanged(eq(mService.getBaseState()));
- verify(callback).onStateChanged(eq(mService.getBaseState()));
+ verify(callback).onDeviceStateChanged(eq(mService.getBaseState()));
}
@Test
@@ -183,44 +180,43 @@
mDeviceStateManagerGlobal.registerDeviceStateCallback(callback,
ConcurrentUtils.DIRECT_EXECUTOR);
- verify(callback).onBaseStateChanged(eq(mService.getBaseState()));
- verify(callback).onStateChanged(eq(mService.getBaseState()));
+ verify(callback).onDeviceStateChanged(eq(mService.getBaseState()));
reset(callback);
- DeviceStateRequest request = DeviceStateRequest.newBuilder(OTHER_DEVICE_STATE).build();
+ DeviceStateRequest request = DeviceStateRequest.newBuilder(
+ OTHER_DEVICE_STATE.getIdentifier()).build();
mDeviceStateManagerGlobal.requestBaseStateOverride(request, null /* executor */,
null /* callback */);
- verify(callback).onBaseStateChanged(eq(OTHER_DEVICE_STATE));
- verify(callback).onStateChanged(eq(OTHER_DEVICE_STATE));
+ verify(callback).onDeviceStateChanged(eq(OTHER_DEVICE_STATE));
assertEquals(OTHER_DEVICE_STATE, mService.getBaseState());
reset(callback);
DeviceStateRequest secondRequest = DeviceStateRequest.newBuilder(
- DEFAULT_DEVICE_STATE).build();
+ DEFAULT_DEVICE_STATE.getIdentifier()).build();
mDeviceStateManagerGlobal.requestState(secondRequest, null, null);
assertEquals(OTHER_DEVICE_STATE, mService.getBaseState());
- verify(callback).onStateChanged(eq(DEFAULT_DEVICE_STATE));
+ verify(callback).onDeviceStateChanged(eq(DEFAULT_DEVICE_STATE));
reset(callback);
mDeviceStateManagerGlobal.cancelStateRequest();
- verify(callback).onStateChanged(OTHER_DEVICE_STATE);
+ verify(callback).onDeviceStateChanged(OTHER_DEVICE_STATE);
reset(callback);
mDeviceStateManagerGlobal.cancelBaseStateOverride();
- verify(callback).onBaseStateChanged(DEFAULT_DEVICE_STATE);
- verify(callback).onStateChanged(DEFAULT_DEVICE_STATE);
+ verify(callback).onDeviceStateChanged(DEFAULT_DEVICE_STATE);
}
@Test
public void verifyDeviceStateRequestCallbacksCalled() {
DeviceStateRequest.Callback callback = mock(TestDeviceStateRequestCallback.class);
- DeviceStateRequest request = DeviceStateRequest.newBuilder(OTHER_DEVICE_STATE).build();
+ DeviceStateRequest request = DeviceStateRequest.newBuilder(
+ OTHER_DEVICE_STATE.getIdentifier()).build();
mDeviceStateManagerGlobal.requestState(request,
ConcurrentUtils.DIRECT_EXECUTOR /* executor */,
callback /* callback */);
@@ -257,12 +253,14 @@
}
}
- private int[] mSupportedStates = new int[] { DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE };
- private int mBaseState = DEFAULT_DEVICE_STATE;
+ private List<DeviceState> mSupportedDeviceStates = List.of(DEFAULT_DEVICE_STATE,
+ OTHER_DEVICE_STATE);
+
+ private DeviceState mBaseState = DEFAULT_DEVICE_STATE;
private Request mRequest;
private Request mBaseStateRequest;
- private Set<IDeviceStateManagerCallback> mCallbacks = new HashSet<>();
+ private final Set<IDeviceStateManagerCallback> mCallbacks = new HashSet<>();
TestDeviceStateManagerService(FakePermissionEnforcer enforcer) {
super(enforcer);
@@ -270,10 +268,15 @@
private DeviceStateInfo getInfo() {
final int mergedBaseState = mBaseStateRequest == null
- ? mBaseState : mBaseStateRequest.state;
+ ? mBaseState.getIdentifier() : mBaseStateRequest.state;
final int mergedState = mRequest == null
? mergedBaseState : mRequest.state;
- return new DeviceStateInfo(mSupportedStates, mergedBaseState, mergedState);
+
+ final DeviceState baseState = new DeviceState(
+ new DeviceState.Configuration.Builder(mergedBaseState, "" /* name */).build());
+ final DeviceState state = new DeviceState(
+ new DeviceState.Configuration.Builder(mergedState, "" /* name */).build());
+ return new DeviceStateInfo(mSupportedDeviceStates, baseState, state);
}
private void notifyDeviceStateInfoChanged() {
@@ -392,25 +395,25 @@
onStateRequestOverlayDismissed_enforcePermission();
}
- public void setSupportedStates(int[] states) {
- mSupportedStates = states;
+ public void setSupportedStates(List<DeviceState> states) {
+ mSupportedDeviceStates = states;
notifyDeviceStateInfoChanged();
}
- public int[] getSupportedStates() {
- return mSupportedStates;
+ public List<DeviceState> getSupportedDeviceStates() {
+ return mSupportedDeviceStates;
}
- public void setBaseState(int state) {
+ public void setBaseState(DeviceState state) {
mBaseState = state;
notifyDeviceStateInfoChanged();
}
- public int getBaseState() {
+ public DeviceState getBaseState() {
return getInfo().baseState;
}
- public int getMergedState() {
+ public DeviceState getMergedState() {
return getInfo().currentState;
}
}
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java
index c287721..68de21f 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateTest.java
@@ -16,19 +16,27 @@
package android.hardware.devicestate;
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS;
import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
+import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
+import junit.framework.Assert;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
/**
* Unit tests for {@link android.hardware.devicestate.DeviceState}.
* <p/>
@@ -39,33 +47,50 @@
public final class DeviceStateTest {
@Test
public void testConstruct() {
- final DeviceState state = new DeviceState(MINIMUM_DEVICE_STATE_IDENTIFIER /* identifier */,
- "TEST_CLOSED" /* name */, DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS /* flags */);
+ DeviceState.Configuration config = new DeviceState.Configuration.Builder(
+ MINIMUM_DEVICE_STATE_IDENTIFIER, "TEST_CLOSED")
+ .setSystemProperties(
+ new HashSet<>(List.of(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS)))
+ .build();
+ final DeviceState state = new DeviceState(config);
assertEquals(state.getIdentifier(), MINIMUM_DEVICE_STATE_IDENTIFIER);
assertEquals(state.getName(), "TEST_CLOSED");
- assertEquals(state.getFlags(), DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS);
+ assertTrue(state.hasProperty(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS));
}
@Test
- public void testConstruct_nullName() {
- final DeviceState state = new DeviceState(MAXIMUM_DEVICE_STATE_IDENTIFIER /* identifier */,
- null /* name */, 0/* flags */);
- assertEquals(state.getIdentifier(), MAXIMUM_DEVICE_STATE_IDENTIFIER);
- assertNull(state.getName());
- assertEquals(state.getFlags(), 0);
+ public void testHasProperties() {
+ DeviceState.Configuration config = new DeviceState.Configuration.Builder(
+ MINIMUM_DEVICE_STATE_IDENTIFIER, "TEST")
+ .setSystemProperties(new HashSet<>(List.of(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
+ PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST)))
+ .build();
+
+ final DeviceState state = new DeviceState(config);
+
+ assertTrue(state.hasProperty(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS));
+ assertTrue(state.hasProperty(PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST));
+ assertTrue(state.hasProperties(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
+ PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST));
}
@Test
- public void testConstruct_tooLargeIdentifier() {
- assertThrows(IllegalArgumentException.class,
- () -> new DeviceState(MAXIMUM_DEVICE_STATE_IDENTIFIER + 1 /* identifier */,
- null /* name */, 0 /* flags */));
- }
+ public void writeToParcel() {
+ final DeviceState originalState = new DeviceState(
+ new DeviceState.Configuration.Builder(0, "TEST_STATE")
+ .setSystemProperties(Set.of(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
+ PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST))
+ .setPhysicalProperties(
+ Set.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED))
+ .build());
- @Test
- public void testConstruct_tooSmallIdentifier() {
- assertThrows(IllegalArgumentException.class,
- () -> new DeviceState(MINIMUM_DEVICE_STATE_IDENTIFIER - 1 /* identifier */,
- null /* name */, 0 /* flags */));
+ final Parcel parcel = Parcel.obtain();
+ originalState.getConfiguration().writeToParcel(parcel, 0 /* flags */);
+ parcel.setDataPosition(0);
+
+ final DeviceState.Configuration stateConfiguration =
+ DeviceState.Configuration.CREATOR.createFromParcel(parcel);
+
+ Assert.assertEquals(originalState, new DeviceState(stateConfiguration));
}
}
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index a621642..bca741f 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -89,5 +89,7 @@
<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/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
index 88fd461..fa35b63 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
@@ -16,7 +16,7 @@
package androidx.window.common;
-import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN;
import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_USE_BASE_STATE;
@@ -69,14 +69,14 @@
* example is activated via public API and can be active in both the "open" and "half folded"
* device states.
*/
- private int mCurrentDeviceState = INVALID_DEVICE_STATE;
+ private int mCurrentDeviceState = INVALID_DEVICE_STATE_IDENTIFIER;
/**
* Base device state received via
* {@link DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int)}.
* "Base" in this context means the "physical" state of the device.
*/
- private int mCurrentBaseDeviceState = INVALID_DEVICE_STATE;
+ private int mCurrentBaseDeviceState = INVALID_DEVICE_STATE_IDENTIFIER;
@NonNull
private final RawFoldingFeatureProducer mRawFoldSupplier;
@@ -177,7 +177,7 @@
if (hasListeners()) {
mRawFoldSupplier.addDataChangedCallback(this::notifyFoldingFeatureChange);
} else {
- mCurrentDeviceState = INVALID_DEVICE_STATE;
+ mCurrentDeviceState = INVALID_DEVICE_STATE_IDENTIFIER;
mRawFoldSupplier.removeDataChangedCallback(this::notifyFoldingFeatureChange);
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index b315f94..d31bf2a 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -16,7 +16,7 @@
package androidx.window.extensions.area;
-import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
import android.app.Activity;
import android.content.Context;
@@ -79,7 +79,7 @@
private int mRearDisplaySessionStatus = WindowAreaComponent.SESSION_STATE_INACTIVE;
@GuardedBy("mLock")
- private int mCurrentDeviceState = INVALID_DEVICE_STATE;
+ private int mCurrentDeviceState = INVALID_DEVICE_STATE_IDENTIFIER;
@GuardedBy("mLock")
private int[] mCurrentSupportedDeviceStates;
@@ -143,7 +143,7 @@
mRearDisplayStatusListeners.add(consumer);
// If current device state is still invalid, the initial value has not been provided.
- if (mCurrentDeviceState == INVALID_DEVICE_STATE) {
+ if (mCurrentDeviceState == INVALID_DEVICE_STATE_IDENTIFIER) {
return;
}
consumer.accept(getCurrentRearDisplayModeStatus());
@@ -308,7 +308,7 @@
mRearDisplayPresentationStatusListeners.add(consumer);
// If current device state is still invalid, the initial value has not been provided
- if (mCurrentDeviceState == INVALID_DEVICE_STATE) {
+ if (mCurrentDeviceState == INVALID_DEVICE_STATE_IDENTIFIER) {
return;
}
@WindowAreaStatus int currentStatus = getCurrentRearDisplayPresentationModeStatus();
@@ -467,7 +467,7 @@
@GuardedBy("mLock")
private int getCurrentRearDisplayModeStatus() {
- if (mRearDisplayState == INVALID_DEVICE_STATE) {
+ if (mRearDisplayState == INVALID_DEVICE_STATE_IDENTIFIER) {
return WindowAreaComponent.STATUS_UNSUPPORTED;
}
@@ -495,7 +495,7 @@
@GuardedBy("mLock")
private void updateRearDisplayStatusListeners(@WindowAreaStatus int windowAreaStatus) {
- if (mRearDisplayState == INVALID_DEVICE_STATE) {
+ if (mRearDisplayState == INVALID_DEVICE_STATE_IDENTIFIER) {
return;
}
synchronized (mLock) {
@@ -507,7 +507,7 @@
@GuardedBy("mLock")
private int getCurrentRearDisplayPresentationModeStatus() {
- if (mConcurrentDisplayState == INVALID_DEVICE_STATE) {
+ if (mConcurrentDisplayState == INVALID_DEVICE_STATE_IDENTIFIER) {
return WindowAreaComponent.STATUS_UNSUPPORTED;
}
@@ -530,7 +530,7 @@
@GuardedBy("mLock")
private void updateRearDisplayPresentationStatusListeners(
@WindowAreaStatus int windowAreaStatus) {
- if (mConcurrentDisplayState == INVALID_DEVICE_STATE) {
+ if (mConcurrentDisplayState == INVALID_DEVICE_STATE_IDENTIFIER) {
return;
}
RearDisplayPresentationStatus consumerValue = new RearDisplayPresentationStatus(
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index a541c59..c68b0be 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -148,4 +148,7 @@
<!-- Whether pointer pilfer is required to start back animation. -->
<bool name="config_backAnimationRequiresPointerPilfer">true</bool>
+
+ <!-- Whether desktop mode is supported on the current device -->
+ <bool name="config_isDesktopModeSupported">false</bool>
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java
index 1071d72..838603f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java
@@ -53,4 +53,7 @@
/** Called when requested to go to fullscreen from the current focused desktop app. */
void moveFocusedTaskToFullscreen(int displayId);
+
+ /** Called when requested to go to split screen from the current focused desktop app. */
+ void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index 7b84868..494d893 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -16,13 +16,13 @@
package com.android.wm.shell.desktopmode;
-import static android.content.res.Configuration.SCREENLAYOUT_SIZE_XLARGE;
-
import android.annotation.NonNull;
-import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
import android.os.SystemProperties;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.window.flags.Flags;
+import com.android.wm.shell.R;
/**
* Constants for desktop mode feature
@@ -70,8 +70,11 @@
private static final boolean USE_ROUNDED_CORNERS = SystemProperties.getBoolean(
"persist.wm.debug.desktop_use_rounded_corners", true);
- private static final boolean ENFORCE_DISPLAY_RESTRICTIONS = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode_enforce_display_restrictions", true);
+ /**
+ * Flag to indicate whether to restrict desktop mode to supported devices.
+ */
+ private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean(
+ "persist.wm.debug.desktop_mode_enforce_device_restrictions", true);
/**
* Return {@code true} if desktop windowing is enabled
@@ -113,19 +116,25 @@
}
/**
- * Return whether the display size restrictions should be enforced.
+ * Return {@code true} if desktop mode should be restricted to supported devices.
*/
- public static boolean enforceDisplayRestrictions() {
- return ENFORCE_DISPLAY_RESTRICTIONS;
+ @VisibleForTesting
+ public static boolean enforceDeviceRestrictions() {
+ return ENFORCE_DEVICE_RESTRICTIONS;
}
/**
- * Return {@code true} if the display associated with the task is at least of size
- * {@link android.content.res.Configuration#SCREENLAYOUT_SIZE_XLARGE} or has been overridden to
- * ignore the size constraint.
+ * Return {@code true} if the current device supports desktop mode.
*/
- public static boolean meetsMinimumDisplayRequirements(@NonNull RunningTaskInfo taskInfo) {
- return !enforceDisplayRestrictions()
- || taskInfo.configuration.isLayoutSizeAtLeast(SCREENLAYOUT_SIZE_XLARGE);
+ @VisibleForTesting
+ public static boolean isDesktopModeSupported(@NonNull Context context) {
+ return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported);
+ }
+
+ /**
+ * Return {@code true} if desktop mode can be entered on the current device.
+ */
+ public static boolean canEnterDesktopMode(@NonNull Context context) {
+ return !enforceDeviceRestrictions() || isDesktopModeSupported(context);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 2c66fd6..95237c3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -62,6 +62,7 @@
import com.android.wm.shell.common.annotations.ExternalThread
import com.android.wm.shell.common.annotations.ShellMainThread
import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT
+import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener
import com.android.wm.shell.draganddrop.DragAndDropController
@@ -305,7 +306,7 @@
task: RunningTaskInfo,
wct: WindowContainerTransaction = WindowContainerTransaction()
) {
- if (!DesktopModeStatus.meetsMinimumDisplayRequirements(task)) {
+ if (!DesktopModeStatus.canEnterDesktopMode(context)) {
KtProtoLog.w(
WM_SHELL_DESKTOP_MODE, "DesktopTasksController: Cannot enter desktop, " +
"display does not meet minimum size requirements")
@@ -388,14 +389,8 @@
/** Enter fullscreen by moving the focused freeform task in given `displayId` to fullscreen. */
fun enterFullscreen(displayId: Int) {
- if (DesktopModeStatus.isEnabled()) {
- shellTaskOrganizer
- .getRunningTasks(displayId)
- .find { taskInfo ->
- taskInfo.isFocused && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM
- }
- ?.let { moveToFullscreenWithAnimation(it, it.positionInParent) }
- }
+ getFocusedFreeformTask(displayId)
+ ?.let { moveToFullscreenWithAnimation(it, it.positionInParent) }
}
/** Move a desktop app to split screen. */
@@ -876,12 +871,28 @@
wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi())
}
+ /** Enter split by using the focused desktop task in given `displayId`. */
+ fun enterSplit(
+ displayId: Int,
+ leftOrTop: Boolean
+ ) {
+ getFocusedFreeformTask(displayId)?.let { requestSplit(it, leftOrTop) }
+ }
+
+ private fun getFocusedFreeformTask(displayId: Int): RunningTaskInfo? {
+ return shellTaskOrganizer.getRunningTasks(displayId)
+ .find { taskInfo -> taskInfo.isFocused &&
+ taskInfo.windowingMode == WINDOWING_MODE_FREEFORM }
+ }
+
/**
* Requests a task be transitioned from desktop to split select. Applies needed windowing
* changes if this transition is enabled.
*/
+ @JvmOverloads
fun requestSplit(
- taskInfo: RunningTaskInfo
+ taskInfo: RunningTaskInfo,
+ leftOrTop: Boolean = false,
) {
val windowingMode = taskInfo.windowingMode
if (windowingMode == WINDOWING_MODE_FULLSCREEN || windowingMode == WINDOWING_MODE_FREEFORM
@@ -889,7 +900,8 @@
val wct = WindowContainerTransaction()
addMoveToSplitChanges(wct, taskInfo)
splitScreenController.requestEnterSplitSelect(taskInfo, wct,
- SPLIT_POSITION_BOTTOM_OR_RIGHT, taskInfo.configuration.windowConfiguration.bounds)
+ if (leftOrTop) SPLIT_POSITION_TOP_OR_LEFT else SPLIT_POSITION_BOTTOM_OR_RIGHT,
+ taskInfo.configuration.windowConfiguration.bounds)
}
}
@@ -1140,6 +1152,12 @@
this@DesktopTasksController.enterFullscreen(displayId)
}
}
+
+ override fun moveFocusedTaskToStageSplit(displayId: Int, leftOrTop: Boolean) {
+ mainExecutor.execute {
+ this@DesktopTasksController.enterSplit(displayId, leftOrTop)
+ }
+ }
}
/** The interface for calls from outside the host process. */
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/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index bf22193..9c01442 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -1052,7 +1052,7 @@
&& taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED
&& taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
&& !taskInfo.configuration.windowConfiguration.isAlwaysOnTop()
- && DesktopModeStatus.meetsMinimumDisplayRequirements(taskInfo);
+ && DesktopModeStatus.canEnterDesktopMode(mContext);
}
private void createWindowDecoration(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 39803e2..c9669a7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -318,11 +318,12 @@
relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode());
relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId);
- if (captionLayoutId == R.layout.desktop_mode_app_controls_window_decor
- && TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo)) {
- // App is requesting to customize the caption bar. Allow input to fall through to the
- // windows below so that the app can respond to input events on their custom content.
- relayoutParams.mAllowCaptionInputFallthrough = true;
+ if (captionLayoutId == R.layout.desktop_mode_app_controls_window_decor) {
+ // If the app is requesting to customize the caption bar, allow input to fall through
+ // to the windows below so that the app can respond to input events on their custom
+ // content.
+ relayoutParams.mAllowCaptionInputFallthrough =
+ TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo);
// Report occluding elements as bounding rects to the insets system so that apps can
// draw in the empty space in the center:
// First, the "app chip" section of the caption bar (+ some extra margins).
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/CopyContentInSplit.kt
index 89ef91e..6171074 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/CopyContentInSplit.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
@@ -28,7 +27,6 @@
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -66,8 +64,4 @@
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt
index 4336692..9e6a686 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromNotification.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.flicker.rules.ChangeDisplayOrientationRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
@@ -30,7 +29,6 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -77,8 +75,4 @@
secondaryApp.exit(wmHelper)
sendNotificationApp.exit(wmHelper)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromShortcut.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromShortcut.kt
index 8c7e63f..3f07be0 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromShortcut.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromShortcut.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.flicker.rules.ChangeDisplayOrientationRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
@@ -30,7 +29,6 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -88,8 +86,4 @@
secondaryApp.exit(wmHelper)
tapl.enableBlockTimeout(false)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromTaskbar.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromTaskbar.kt
index 2072831..5328013 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromTaskbar.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenByDragFromTaskbar.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
@@ -29,7 +28,6 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -76,8 +74,4 @@
secondaryApp.exit(wmHelper)
tapl.enableBlockTimeout(false)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenFromOverview.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenFromOverview.kt
index 09e77cc..be4035d 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenFromOverview.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/EnterSplitScreenFromOverview.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
@@ -28,7 +27,6 @@
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -72,8 +70,4 @@
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt
index babdae1..9312c0a 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchAppByDoubleTapDivider.kt
@@ -20,7 +20,6 @@
import android.graphics.Point
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.helpers.WindowUtils
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
@@ -30,7 +29,6 @@
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -151,8 +149,4 @@
val LARGE_SCREEN_DP_THRESHOLD = 600
return sizeDp.x >= LARGE_SCREEN_DP_THRESHOLD && sizeDp.y >= LARGE_SCREEN_DP_THRESHOLD
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromAnotherApp.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromAnotherApp.kt
index 3e85479..de26982 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromAnotherApp.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromAnotherApp.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
@@ -28,7 +27,6 @@
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -69,8 +67,4 @@
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromHome.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromHome.kt
index 655ae4e..873b019 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromHome.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromHome.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
@@ -28,7 +27,6 @@
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -68,8 +66,4 @@
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromRecent.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromRecent.kt
index 2208258..15934d0 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromRecent.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBackToSplitFromRecent.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
@@ -28,7 +27,6 @@
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -70,8 +68,4 @@
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBetweenSplitPairs.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBetweenSplitPairs.kt
index 2ac63c2..79e69ae 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBetweenSplitPairs.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/SwitchBetweenSplitPairs.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
@@ -28,7 +27,6 @@
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -71,8 +69,4 @@
thirdApp.exit(wmHelper)
fourthApp.exit(wmHelper)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/UnlockKeyguardToSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/UnlockKeyguardToSplitScreen.kt
index 35b122d..0f932d4 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/UnlockKeyguardToSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/splitscreen/scenarios/UnlockKeyguardToSplitScreen.kt
@@ -19,7 +19,6 @@
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
-import android.tools.AndroidLoggerSetupRule
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
@@ -28,7 +27,6 @@
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import org.junit.After
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
@@ -68,8 +66,4 @@
primaryApp.exit(wmHelper)
secondaryApp.exit(wmHelper)
}
-
- companion object {
- @ClassRule @JvmField val setupLoggerRule = AndroidLoggerSetupRule()
- }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 4c8a308..0136751 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -23,8 +23,6 @@
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
-import android.content.res.Configuration.SCREENLAYOUT_SIZE_NORMAL
-import android.content.res.Configuration.SCREENLAYOUT_SIZE_XLARGE
import android.os.Binder
import android.testing.AndroidTestingRunner
import android.view.Display.DEFAULT_DISPLAY
@@ -38,6 +36,7 @@
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.dx.mockito.inline.extended.ExtendedMockito.never
import com.android.dx.mockito.inline.extended.StaticMockitoSession
@@ -53,6 +52,7 @@
import com.android.wm.shell.common.MultiInstanceHelper
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
+import com.android.wm.shell.common.split.SplitScreenConstants
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask
@@ -88,6 +88,7 @@
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
+import org.mockito.quality.Strictness
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -125,7 +126,8 @@
@Before
fun setUp() {
- mockitoSession = mockitoSession().spyStatic(DesktopModeStatus::class.java).startMocking()
+ mockitoSession = mockitoSession().strictness(Strictness.LENIENT)
+ .spyStatic(DesktopModeStatus::class.java).startMocking()
whenever(DesktopModeStatus.isEnabled()).thenReturn(true)
shellInit = Mockito.spy(ShellInit(testExecutor))
@@ -334,25 +336,25 @@
}
@Test
- fun moveToDesktop_screenSizeBelowXLarge_doesNothing() {
+ fun moveToDesktop_deviceNotSupported_doesNothing() {
val task = setUpFullscreenTask()
- // Update screen layout to be below minimum size
- task.configuration.screenLayout = SCREENLAYOUT_SIZE_NORMAL
+ // Simulate non compatible device
+ doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
controller.moveToDesktop(task)
verifyWCTNotExecuted()
}
@Test
- fun moveToDesktop_screenSizeBelowXLarge_displayRestrictionsOverridden_taskIsMovedToDesktop() {
+ fun moveToDesktop_deviceNotSupported_deviceRestrictionsOverridden_taskIsMovedToDesktop() {
val task = setUpFullscreenTask()
- // Update screen layout to be below minimum size
- task.configuration.screenLayout = SCREENLAYOUT_SIZE_NORMAL
+ // Simulate non compatible device
+ doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
- // Simulate enforce display restrictions system property overridden to false
- whenever(DesktopModeStatus.enforceDisplayRestrictions()).thenReturn(false)
+ // Simulate enforce device restrictions system property overridden to false
+ whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(false)
controller.moveToDesktop(task)
@@ -362,7 +364,7 @@
}
@Test
- fun moveToDesktop_screenSizeXLarge_taskIsMovedToDesktop() {
+ fun moveToDesktop_deviceSupported_taskIsMovedToDesktop() {
val task = setUpFullscreenTask()
controller.moveToDesktop(task)
@@ -839,6 +841,22 @@
.isEqualTo(WINDOWING_MODE_FULLSCREEN)
}
+ fun enterSplit_freeformTaskIsMovedToSplit() {
+ val task1 = setUpFreeformTask()
+ val task2 = setUpFreeformTask()
+ val task3 = setUpFreeformTask()
+
+ task1.isFocused = false
+ task2.isFocused = true
+ task3.isFocused = false
+
+ controller.enterSplit(DEFAULT_DISPLAY, false)
+
+ verify(splitScreenController).requestEnterSplitSelect(task2, any(),
+ SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT,
+ task2.configuration.windowConfiguration.bounds)
+ }
+
private fun setUpFreeformTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
val task = createFreeformTask(displayId)
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
@@ -857,7 +875,8 @@
private fun setUpFullscreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
val task = createFullscreenTask(displayId)
- task.configuration.screenLayout = SCREENLAYOUT_SIZE_XLARGE
+ doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
runningTasks.add(task)
return task
@@ -865,7 +884,8 @@
private fun setUpSplitScreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
val task = createSplitScreenTask(displayId)
- task.configuration.screenLayout = SCREENLAYOUT_SIZE_XLARGE
+ doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
whenever(splitScreenController.isTaskInSplitScreen(task.taskId)).thenReturn(true)
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
runningTasks.add(task)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 83519bb..6940739 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -23,8 +23,6 @@
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
import android.content.Context
-import android.content.res.Configuration.SCREENLAYOUT_SIZE_NORMAL
-import android.content.res.Configuration.SCREENLAYOUT_SIZE_XLARGE
import android.graphics.Rect
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
@@ -47,6 +45,7 @@
import android.view.WindowInsets.Type.statusBars
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.StaticMockitoSession
import com.android.window.flags.Flags
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
@@ -367,30 +366,41 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- fun testWindowDecor_screenSizeBelowXLarge_decorNotCreated() {
- val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
- // Update screen layout to be below minimum size
- task.configuration.screenLayout = SCREENLAYOUT_SIZE_NORMAL
-
- onTaskOpening(task)
- verify(mockDesktopModeWindowDecorFactory, never())
- .create(any(), any(), any(), eq(task), any(), any(), any(), any(), any())
- }
-
- @Test
- @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- fun testWindowDecor_screenSizeBelowXLarge_displayRestrictionsOverridden_decorCreated() {
+ fun testWindowDecor_desktopModeUnsupportedOnDevice_decorNotCreated() {
val mockitoSession: StaticMockitoSession = mockitoSession()
.strictness(Strictness.LENIENT)
.spyStatic(DesktopModeStatus::class.java)
.startMocking()
try {
- // Simulate enforce display restrictions system property overridden to false
- whenever(DesktopModeStatus.enforceDisplayRestrictions()).thenReturn(false)
+ // Simulate default enforce device restrictions system property
+ whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
- // Update screen layout to be below minimum size
- task.configuration.screenLayout = SCREENLAYOUT_SIZE_NORMAL
+ // Simulate device that doesn't support desktop mode
+ doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+
+ onTaskOpening(task)
+ verify(mockDesktopModeWindowDecorFactory, never())
+ .create(any(), any(), any(), eq(task), any(), any(), any(), any(), any())
+ } finally {
+ mockitoSession.finishMocking()
+ }
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+ fun testWindowDecor_desktopModeUnsupportedOnDevice_deviceRestrictionsOverridden_decorCreated() {
+ val mockitoSession: StaticMockitoSession = mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .spyStatic(DesktopModeStatus::class.java)
+ .startMocking()
+ try {
+ // Simulate enforce device restrictions system property overridden to false
+ whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(false)
+ // Simulate device that doesn't support desktop mode
+ doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+
+ val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
setUpMockDecorationsForTasks(task)
onTaskOpening(task)
@@ -403,14 +413,25 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
- fun testWindowDecor_screenSizeXLarge_decorCreated() {
- val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
- task.configuration.screenLayout = SCREENLAYOUT_SIZE_XLARGE
- setUpMockDecorationsForTasks(task)
+ fun testWindowDecor_deviceSupportsDesktopMode_decorCreated() {
+ val mockitoSession: StaticMockitoSession = mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .spyStatic(DesktopModeStatus::class.java)
+ .startMocking()
+ try {
+ // Simulate default enforce device restrictions system property
+ whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true)
- onTaskOpening(task)
- verify(mockDesktopModeWindowDecorFactory)
- .create(any(), any(), any(), eq(task), any(), any(), any(), any(), any())
+ val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true)
+ doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
+ setUpMockDecorationsForTasks(task)
+
+ onTaskOpening(task)
+ verify(mockDesktopModeWindowDecorFactory)
+ .create(any(), any(), any(), eq(task), any(), any(), any(), any(), any())
+ } finally {
+ mockitoSession.finishMocking()
+ }
}
private fun onTaskOpening(task: RunningTaskInfo, leash: SurfaceControl = SurfaceControl()) {
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 ba3f6dd..f9b5882 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
@@ -173,7 +173,7 @@
}
@Test
- public void updateRelayoutParams_freeformAndTransparent_allowsInputFallthrough() {
+ public void updateRelayoutParams_freeformAndTransparentAppearance_allowsInputFallthrough() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
taskInfo.taskDescription.setSystemBarsAppearance(
@@ -191,7 +191,7 @@
}
@Test
- public void updateRelayoutParams_freeformButOpaque_disallowsInputFallthrough() {
+ public void updateRelayoutParams_freeformButOpaqueAppearance_disallowsInputFallthrough() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
taskInfo.taskDescription.setSystemBarsAppearance(0);
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/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/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/location/api/system-current.txt b/location/api/system-current.txt
index 2e7a541..254d74a 100644
--- a/location/api/system-current.txt
+++ b/location/api/system-current.txt
@@ -616,8 +616,8 @@
@FlaggedApi(Flags.FLAG_NEW_GEOCODER) public abstract class GeocodeProviderBase {
ctor public GeocodeProviderBase(@NonNull android.content.Context, @NonNull String);
method @NonNull public final android.os.IBinder getBinder();
- method public abstract void onForwardGeocode(@NonNull android.location.provider.ForwardGeocodeRequest, @NonNull android.os.OutcomeReceiver<java.util.List<android.location.Address>,java.lang.Exception>);
- method public abstract void onReverseGeocode(@NonNull android.location.provider.ReverseGeocodeRequest, @NonNull android.os.OutcomeReceiver<java.util.List<android.location.Address>,java.lang.Exception>);
+ method public abstract void onForwardGeocode(@NonNull android.location.provider.ForwardGeocodeRequest, @NonNull android.os.OutcomeReceiver<java.util.List<android.location.Address>,java.lang.Throwable>);
+ method public abstract void onReverseGeocode(@NonNull android.location.provider.ReverseGeocodeRequest, @NonNull android.os.OutcomeReceiver<java.util.List<android.location.Address>,java.lang.Throwable>);
field public static final String ACTION_GEOCODE_PROVIDER = "com.android.location.service.GeocodeProvider";
}
diff --git a/location/java/android/location/provider/GeocodeProviderBase.java b/location/java/android/location/provider/GeocodeProviderBase.java
index e2c48b9..71644d07 100644
--- a/location/java/android/location/provider/GeocodeProviderBase.java
+++ b/location/java/android/location/provider/GeocodeProviderBase.java
@@ -104,14 +104,14 @@
*/
public abstract void onForwardGeocode(
@NonNull ForwardGeocodeRequest request,
- @NonNull OutcomeReceiver<List<Address>, Exception> callback);
+ @NonNull OutcomeReceiver<List<Address>, Throwable> callback);
/**
* Requests reverse geocoding of the given arguments. The given callback must be invoked once.
*/
public abstract void onReverseGeocode(
@NonNull ReverseGeocodeRequest request,
- @NonNull OutcomeReceiver<List<Address>, Exception> callback);
+ @NonNull OutcomeReceiver<List<Address>, Throwable> callback);
private class Service extends IGeocodeProvider.Stub {
@Override
@@ -145,7 +145,7 @@
}
}
- private static class SingleUseCallback implements OutcomeReceiver<List<Address>, Exception> {
+ private static class SingleUseCallback implements OutcomeReceiver<List<Address>, Throwable> {
private final AtomicReference<IGeocodeCallback> mCallback;
@@ -154,7 +154,7 @@
}
@Override
- public void onError(Exception e) {
+ public void onError(Throwable e) {
try {
Objects.requireNonNull(mCallback.getAndSet(null)).onError(e.toString());
} catch (RemoteException r) {
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/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one_dark.xml b/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_middle.xml
similarity index 60%
rename from packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one_dark.xml
rename to packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_middle.xml
index 39f49ca..781373d 100644
--- a/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one_dark.xml
+++ b/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_middle.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2023 The Android Open Source Project
+ ~ 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.
@@ -15,16 +15,10 @@
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools" tools:ignore="NewApi"
- android:color="@android:color/transparent">
- <item
- android:bottom="1dp"
- android:shape="rectangle"
- android:top="1dp">
- <shape>
- <corners android:radius="28dp" />
- <solid android:color="@android:color/system_surface_container_high_dark" />
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:tools="http://schemas.android.com/tools" tools:ignore="NewApi">
+ <shape android:shape="rectangle">
+ <solid android:color="?androidprv:attr/materialColorSurfaceContainer" />
</shape>
- </item>
-</ripple>
\ No newline at end of file
+</inset>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one.xml b/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one.xml
index f13402c..f28c354 100644
--- a/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one.xml
+++ b/packages/CredentialManager/res/drawable/fill_dialog_dynamic_list_item_one.xml
@@ -15,16 +15,12 @@
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools" tools:ignore="NewApi"
- android:color="@android:color/transparent">
- <item
- android:bottom="1dp"
- android:shape="rectangle"
- android:top="1dp">
- <shape>
- <corners android:radius="4dp" />
- <solid android:color="@color/dropdown_container" />
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:tools="http://schemas.android.com/tools" tools:ignore="NewApi">
+ <shape android:shape="rectangle">
+ <corners android:topLeftRadius="4dp" android:topRightRadius="4dp"
+ android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp"/>
+ <solid android:color="?androidprv:attr/materialColorSurfaceContainer" />
</shape>
- </item>
-</ripple>
\ No newline at end of file
+</inset>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/more_options_list_item.xml b/packages/CredentialManager/res/drawable/more_options_list_item.xml
index d7b509e..3f9d815 100644
--- a/packages/CredentialManager/res/drawable/more_options_list_item.xml
+++ b/packages/CredentialManager/res/drawable/more_options_list_item.xml
@@ -15,17 +15,16 @@
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools" tools:ignore="NewApi"
- android:color="@android:color/transparent">
- <item
- android:bottom="1dp"
- android:shape="rectangle"
- android:top="1dp">
- <shape>
- <corners android:bottomLeftRadius="4dp"
- android:bottomRightRadius="4dp"/>
- <solid android:color="@color/sign_in_options_container" />
- </shape>
- </item>
-</ripple>
\ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:tools="http://schemas.android.com/tools" tools:ignore="NewApi"
+ android:insetLeft="-2dp"
+ android:insetRight="-2dp"
+ android:insetBottom="-2dp">
+ <shape>
+ <corners android:topLeftRadius="0dp" android:topRightRadius="0dp"
+ android:bottomLeftRadius="4dp" android:bottomRightRadius="4dp"/>
+ <solid android:color="?androidprv:attr/materialColorSurfaceContainer"/>
+ <stroke android:color="?androidprv:attr/materialColorOutlineVariant" android:width="1dp"/>
+ </shape>
+</inset>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/layout/credman_dropdown_bottom_sheet.xml b/packages/CredentialManager/res/layout/credman_dropdown_bottom_sheet.xml
index 910ff96..7f09dd5 100644
--- a/packages/CredentialManager/res/layout/credman_dropdown_bottom_sheet.xml
+++ b/packages/CredentialManager/res/layout/credman_dropdown_bottom_sheet.xml
@@ -14,30 +14,52 @@
~ limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@android:id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="@dimen/dropdown_touch_target_min_height"
android:orientation="horizontal"
- android:layout_marginEnd="@dimen/dropdown_layout_horizontal_margin"
android:elevation="3dp">
- <ImageView
- android:id="@android:id/icon1"
+ <LinearLayout
+ android:id="@+id/credential_card"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_alignParentStart="true"
- android:contentDescription="@string/more_options_content_description"
- android:background="@null"/>
- <TextView
- android:id="@android:id/text1"
- android:layout_width="wrap_content"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@android:id/icon1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:paddingLeft="@dimen/autofill_view_left_padding"
+ android:src="@drawable/more_horiz_24px"
+ android:tint="?androidprv:attr/materialColorOnSurface"
+ android:layout_alignParentStart="true"
+ android:contentDescription="@string/more_options_content_description"
+ android:background="@null"/>
+
+ <LinearLayout
+ android:id="@+id/text_container"
+ android:layout_width="@dimen/autofill_dropdown_textview_max_width"
android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_toEndOf="@android:id/icon1"
- android:minWidth="@dimen/autofill_dropdown_textview_min_width"
- android:maxWidth="@dimen/autofill_dropdown_textview_max_width"
- style="@style/autofill.TextTitle"/>
+ android:paddingLeft="@dimen/autofill_view_left_padding"
+ android:paddingRight="@dimen/autofill_view_right_padding"
+ android:paddingTop="@dimen/more_options_item_vertical_padding"
+ android:paddingBottom="@dimen/more_options_item_vertical_padding"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@android:id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:textColor="?androidprv:attr/materialColorOnSurface"
+ android:layout_toEndOf="@android:id/icon1"
+ style="@style/autofill.TextTitle"/>
+ </LinearLayout>
+
+ </LinearLayout>
</RelativeLayout>
diff --git a/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml b/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml
index 4bf0e99..08948d7 100644
--- a/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml
+++ b/packages/CredentialManager/res/layout/credman_dropdown_presentation_layout.xml
@@ -14,37 +14,60 @@
~ limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@android:id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="@dimen/dropdown_touch_target_min_height"
- android:layout_marginEnd="@dimen/dropdown_layout_horizontal_margin"
android:elevation="3dp">
- <ImageView
- android:id="@android:id/icon1"
+ <LinearLayout
+ android:id="@+id/credential_card"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_alignParentStart="true"
- android:background="@null"/>
- <TextView
- android:id="@android:id/text1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_toEndOf="@android:id/icon1"
- android:minWidth="@dimen/autofill_dropdown_textview_min_width"
- android:maxWidth="@dimen/autofill_dropdown_textview_max_width"
- style="@style/autofill.TextTitle"/>
- <TextView
- android:id="@android:id/text2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@android:id/text1"
- android:layout_toEndOf="@android:id/icon1"
- android:minWidth="@dimen/autofill_dropdown_textview_min_width"
- android:maxWidth="@dimen/autofill_dropdown_textview_max_width"
- style="@style/autofill.TextSubtitle"/>
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@android:id/icon1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_alignParentStart="true"
+ android:paddingLeft="@dimen/autofill_view_left_padding"
+ app:tint="?androidprv:attr/materialColorOnSurface"
+ android:background="@null"/>
+
+ <LinearLayout
+ android:id="@+id/text_container"
+ android:layout_width="@dimen/autofill_dropdown_textview_max_width"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/autofill_view_left_padding"
+ android:paddingRight="@dimen/autofill_view_right_padding"
+ android:paddingTop="@dimen/autofill_view_top_padding"
+ android:paddingBottom="@dimen/autofill_view_bottom_padding"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@android:id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_toEndOf="@android:id/icon1"
+ android:textColor="?androidprv:attr/materialColorOnSurface"
+ style="@style/autofill.TextTitle"/>
+
+ <TextView
+ android:id="@android:id/text2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/text1"
+ android:layout_toEndOf="@android:id/icon1"
+ android:textColor="?androidprv:attr/materialColorOnSurfaceVariant"
+ style="@style/autofill.TextSubtitle"/>
+
+ </LinearLayout>
+
+ </LinearLayout>
</RelativeLayout>
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/res/values/colors.xml b/packages/CredentialManager/res/values/colors.xml
index b4d2eeb..9d31b35 100644
--- a/packages/CredentialManager/res/values/colors.xml
+++ b/packages/CredentialManager/res/values/colors.xml
@@ -15,14 +15,12 @@
-->
<!-- Color palette -->
-<resources>
- <!-- These colors are used for Remote Views. -->
- <color name="text_primary">#1A1B20</color>
- <color name="text_secondary">#44474F</color>
- <color name="dropdown_container">#F3F3FA</color>
- <color name="sign_in_options_container">#DADADA</color>
- <color name="sign_in_options_icon_color">#1B1B1B</color>
+<resources
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <!-- These colors are used for Inline Suggestions. -->
- <color name="inline_background">#FFFFFF</color>
+ <!-- These colors are used for Remote Views. -->
+ <color name="onSurface">?androidprv:attr/materialColorOnSurface</color>
+ <color name="onSurfaceVariant">?androidprv:attr/materialColorOnSurfaceVariant</color>
+ <color name="surfaceDim">?androidprv:attr/materialColorSurfaceDim</color>
+ <color name="surfaceContainer">?androidprv:attr/materialColorSurfaceContainer</color>
</resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/values/dimens.xml b/packages/CredentialManager/res/values/dimens.xml
index 82dee5c..314437e 100644
--- a/packages/CredentialManager/res/values/dimens.xml
+++ b/packages/CredentialManager/res/values/dimens.xml
@@ -18,16 +18,18 @@
<resources>
<dimen name="autofill_view_top_padding">12dp</dimen>
- <dimen name="autofill_view_right_padding">12dp</dimen>
+ <dimen name="autofill_view_right_padding">16dp</dimen>
<dimen name="autofill_view_bottom_padding">12dp</dimen>
<dimen name="autofill_view_left_padding">16dp</dimen>
- <dimen name="autofill_view_icon_to_text_padding">10dp</dimen>
+ <dimen name="autofill_view_icon_to_text_padding">16dp</dimen>
+ <dimen name="autofill_view_end_items_padding">8dp</dimen>
+ <dimen name="more_options_item_vertical_padding">14dp</dimen>
<dimen name="autofill_icon_size">24dp</dimen>
<dimen name="autofill_dropdown_textview_min_width">112dp</dimen>
<dimen name="autofill_dropdown_textview_max_width">230dp</dimen>
<dimen name="dropdown_layout_horizontal_margin">24dp</dimen>
<integer name="autofill_max_visible_datasets">4</integer>
- <dimen name="dropdown_touch_target_min_height">48dp</dimen>
+ <dimen name="dropdown_touch_target_min_height">49dp</dimen>
<dimen name="horizontal_chip_padding">8dp</dimen>
<dimen name="vertical_chip_padding">6dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
index d7a2e36..4f2fa79 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
@@ -295,8 +295,9 @@
}
var dropdownPresentation: RemoteViews? = null
if (i < maxDatasetDisplayLimit) {
- dropdownPresentation = RemoteViewsFactory
- .createDropdownPresentation(this, icon, primaryEntry)
+ dropdownPresentation = RemoteViewsFactory.createDropdownPresentation(
+ this, icon, primaryEntry, /*isFirstEntry= */ i == 0,
+ /*isLastEntry= */ (totalEntryCount - i == 1))
}
val dataSetBuilder = Dataset.Builder()
@@ -572,6 +573,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 642a377..99a9409 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -259,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/common/ui/RemoteViewsFactory.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt
index 7966a86..a46e358 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt
@@ -31,12 +31,13 @@
private const val setMaxHeightMethodName = "setMaxHeight"
private const val setBackgroundResourceMethodName = "setBackgroundResource"
private const val bulletPoint = "\u2022"
- private const val passwordCharacterLength = 15
fun createDropdownPresentation(
context: Context,
icon: Icon,
- credentialEntryInfo: CredentialEntryInfo
+ credentialEntryInfo: CredentialEntryInfo,
+ isFirstEntry: Boolean,
+ isLastEntry: Boolean,
): RemoteViews {
var layoutId: Int = com.android.credentialmanager.R.layout
.credman_dropdown_presentation_layout
@@ -44,7 +45,6 @@
if (credentialEntryInfo.credentialType == CredentialType.UNKNOWN) {
return remoteViews
}
- setRemoteViewsPaddings(remoteViews, context, /* primaryTextBottomPadding=*/0)
val displayName = credentialEntryInfo.displayName ?: credentialEntryInfo.userName
remoteViews.setTextViewText(android.R.id.text1, displayName)
val secondaryText =
@@ -56,12 +56,6 @@
else (credentialEntryInfo.credentialTypeDisplayName + " " + bulletPoint + " "
+ credentialEntryInfo.providerDisplayName)
remoteViews.setTextViewText(android.R.id.text2, secondaryText)
- val textColorPrimary = ContextCompat.getColor(context,
- com.android.credentialmanager.R.color.text_primary)
- remoteViews.setTextColor(android.R.id.text1, textColorPrimary)
- val textColorSecondary = ContextCompat.getColor(context, com.android
- .credentialmanager.R.color.text_secondary)
- remoteViews.setTextColor(android.R.id.text2, textColorSecondary)
remoteViews.setImageViewIcon(android.R.id.icon1, icon);
remoteViews.setBoolean(
android.R.id.icon1, setAdjustViewBoundsMethodName, true);
@@ -73,9 +67,23 @@
remoteViews.setContentDescription(android.R.id.icon1, credentialEntryInfo
.providerDisplayName);
val drawableId =
- com.android.credentialmanager.R.drawable.fill_dialog_dynamic_list_item_one
+ if (isFirstEntry)
+ com.android.credentialmanager.R.drawable.fill_dialog_dynamic_list_item_one else
+ com.android.credentialmanager.R.drawable.fill_dialog_dynamic_list_item_middle
remoteViews.setInt(
android.R.id.content, setBackgroundResourceMethodName, drawableId);
+ if (isFirstEntry) remoteViews.setViewPadding(
+ com.android.credentialmanager.R.id.credential_card,
+ /* left=*/0,
+ /* top=*/8,
+ /* right=*/0,
+ /* bottom=*/0)
+ if (isLastEntry) remoteViews.setViewPadding(
+ com.android.credentialmanager.R.id.credential_card,
+ /*left=*/0,
+ /* top=*/0,
+ /* right=*/0,
+ /* bottom=*/8)
return remoteViews
}
@@ -83,19 +91,9 @@
var layoutId: Int = com.android.credentialmanager.R.layout
.credman_dropdown_bottom_sheet
val remoteViews = RemoteViews(context.packageName, layoutId)
- setRemoteViewsPaddings(remoteViews, context)
remoteViews.setTextViewText(android.R.id.text1, ContextCompat.getString(context,
com.android.credentialmanager
.R.string.dropdown_presentation_more_sign_in_options_text))
-
- val textColorPrimary = ContextCompat.getColor(context,
- com.android.credentialmanager.R.color.text_primary)
- remoteViews.setTextColor(android.R.id.text1, textColorPrimary)
- val icon = Icon.createWithResource(context, com
- .android.credentialmanager.R.drawable.more_horiz_24px)
- icon.setTint(ContextCompat.getColor(context,
- com.android.credentialmanager.R.color.sign_in_options_icon_color))
- remoteViews.setImageViewIcon(android.R.id.icon1, icon)
remoteViews.setBoolean(
android.R.id.icon1, setAdjustViewBoundsMethodName, true);
remoteViews.setInt(
@@ -109,50 +107,5 @@
android.R.id.content, setBackgroundResourceMethodName, drawableId);
return remoteViews
}
-
- private fun setRemoteViewsPaddings(
- remoteViews: RemoteViews, context: Context) {
- val bottomPadding = context.resources.getDimensionPixelSize(
- com.android.credentialmanager.R.dimen.autofill_view_bottom_padding)
- setRemoteViewsPaddings(remoteViews, context, bottomPadding)
- }
-
- private fun setRemoteViewsPaddings(
- remoteViews: RemoteViews, context: Context, primaryTextBottomPadding: Int) {
- val leftPadding = context.resources.getDimensionPixelSize(
- com.android.credentialmanager.R.dimen.autofill_view_left_padding)
- val iconToTextPadding = context.resources.getDimensionPixelSize(
- com.android.credentialmanager.R.dimen.autofill_view_icon_to_text_padding)
- val rightPadding = context.resources.getDimensionPixelSize(
- com.android.credentialmanager.R.dimen.autofill_view_right_padding)
- val topPadding = context.resources.getDimensionPixelSize(
- com.android.credentialmanager.R.dimen.autofill_view_top_padding)
- val bottomPadding = context.resources.getDimensionPixelSize(
- com.android.credentialmanager.R.dimen.autofill_view_bottom_padding)
- remoteViews.setViewPadding(
- android.R.id.icon1,
- leftPadding,
- /* top=*/0,
- /* right=*/0,
- /* bottom=*/0)
- remoteViews.setViewPadding(
- android.R.id.text1,
- iconToTextPadding,
- /* top=*/topPadding,
- /* right=*/rightPadding,
- primaryTextBottomPadding)
- remoteViews.setViewPadding(
- android.R.id.text2,
- iconToTextPadding,
- /* top=*/0,
- /* right=*/rightPadding,
- /* bottom=*/bottomPadding)
- }
-
- private fun isDarkMode(context: Context): Boolean {
- val currentNightMode = context.resources.configuration.uiMode and
- Configuration.UI_MODE_NIGHT_MASK
- return currentNightMode == Configuration.UI_MODE_NIGHT_YES
- }
}
}
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/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index a490b6f..30d5d4b 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -268,6 +268,7 @@
Settings.Secure.EVEN_DIMMER_MIN_NITS,
Settings.Secure.STYLUS_POINTER_ICON_ENABLED,
Settings.Secure.CAMERA_EXTENSIONS_FALLBACK,
- Settings.Secure.VISUAL_QUERY_ACCESSIBILITY_DETECTION_ENABLED
+ Settings.Secure.VISUAL_QUERY_ACCESSIBILITY_DETECTION_ENABLED,
+ Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 4cdf98cb..893932f 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -423,5 +423,6 @@
VALIDATORS.put(Secure.AUTOFILL_SERVICE, AUTOFILL_SERVICE_VALIDATOR);
VALIDATORS.put(Secure.STYLUS_POINTER_ICON_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.CAMERA_EXTENSIONS_FALLBACK, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.IMMERSIVE_MODE_CONFIRMATIONS, ANY_STRING_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 09d076e..46c89900 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -702,7 +702,6 @@
Settings.Secure.ENABLED_PRINT_SERVICES,
Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE,
Settings.Secure.GLOBAL_ACTIONS_PANEL_DEBUG_ENABLED,
- Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY,
Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY,
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index d05d40d..da06830 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -610,3 +610,10 @@
description: "Refactors media code to follow the recommended architecture"
bug: "326408371"
}
+
+flag {
+ name: "qs_tile_focus_state"
+ namespace: "systemui"
+ description: "enables new focus outline for qs tiles when focused on with physical keyboard"
+ bug: "312899524"
+}
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 eb6d303..3050f7a 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
@@ -90,7 +90,6 @@
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.layout.positionInWindow
-import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.testTag
@@ -108,6 +107,7 @@
import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.window.Popup
import androidx.core.view.setPadding
+import androidx.window.layout.WindowMetricsCalculator
import com.android.compose.modifiers.thenIf
import com.android.compose.theme.LocalAndroidColorScheme
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
@@ -398,11 +398,11 @@
}
} else {
CommunalContent(
+ modifier = cardModifier.animateItemPlacement(),
model = list[index],
viewModel = viewModel,
size = size,
selected = false,
- modifier = cardModifier,
)
}
}
@@ -645,7 +645,7 @@
) {
val colors = LocalAndroidColorScheme.current
Card(
- modifier = modifier.padding(CardOutlineWidth),
+ modifier = modifier,
colors =
CardDefaults.cardColors(
containerColor = colors.primary,
@@ -716,7 +716,7 @@
}
val colors = LocalAndroidColorScheme.current
Card(
- modifier = modifier.padding(CardOutlineWidth),
+ modifier = modifier,
colors = CardDefaults.cardColors(containerColor = Color.Transparent),
border = BorderStroke(1.dp, colors.primary),
shape = RoundedCornerShape(200.dp),
@@ -756,21 +756,17 @@
Box(
modifier = modifier,
) {
- val paddingInPx =
- if (selected) with(LocalDensity.current) { CardOutlineWidth.toPx().toInt() } else 0
AndroidView(
modifier = Modifier.fillMaxSize().allowGestures(allowed = !viewModel.isEditMode),
factory = { context ->
model.appWidgetHost
.createViewForCommunal(context, model.appWidgetId, model.providerInfo)
- .apply { updateAppWidgetSize(Bundle.EMPTY, listOf(size)) }
- },
- update = { view ->
- // Remove the extra padding applied to AppWidgetHostView to allow widgets to
- // occupy the entire box. The added padding is now adjusted to leave only
- // sufficient space for displaying the outline around the box when the widget
- // is selected.
- view.setPadding(paddingInPx)
+ .apply {
+ updateAppWidgetSize(Bundle.EMPTY, listOf(size))
+ // Remove the extra padding applied to AppWidgetHostView to allow widgets to
+ // occupy the entire box.
+ setPadding(0)
+ }
},
// For reusing composition in lazy lists.
onReset = {},
@@ -906,14 +902,14 @@
if (!isEditMode || toolbarSize == null) {
return PaddingValues(start = 48.dp, end = 48.dp, top = Dimensions.GridTopSpacing)
}
- val configuration = LocalConfiguration.current
+ val context = LocalContext.current
val density = LocalDensity.current
- val screenHeight = configuration.screenHeightDp.dp
+ val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
+ val screenHeight = with(density) { windowMetrics.bounds.height().toDp() }
val toolbarHeight = with(density) { Dimensions.ToolbarPaddingTop + toolbarSize.height.toDp() }
val verticalPadding =
- ((screenHeight - toolbarHeight - Dimensions.GridHeight) / 2).coerceAtLeast(
- Dimensions.Spacing
- )
+ ((screenHeight - toolbarHeight - Dimensions.GridHeight + Dimensions.GridTopSpacing) / 2)
+ .coerceAtLeast(Dimensions.Spacing)
return PaddingValues(
start = Dimensions.ToolbarPaddingHorizontal,
end = Dimensions.ToolbarPaddingHorizontal,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
index beb8ddef..1adb335 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
@@ -41,7 +41,6 @@
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.toOffset
import androidx.compose.ui.unit.toSize
-import androidx.compose.ui.zIndex
import com.android.systemui.communal.ui.compose.extensions.firstItemAtOffset
import com.android.systemui.communal.ui.compose.extensions.plus
import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
@@ -247,7 +246,7 @@
content: @Composable (isDragging: Boolean) -> Unit
) {
if (!enabled) {
- return Box(modifier = modifier) { content(false) }
+ return content(false)
}
val dragging = index == dragDropState.draggingItemIndex
@@ -258,7 +257,7 @@
)
val draggingModifier =
if (dragging) {
- Modifier.zIndex(1f).graphicsLayer {
+ Modifier.graphicsLayer {
translationX = dragDropState.draggingItemOffset.x
translationY = dragDropState.draggingItemOffset.y
alpha = itemAlpha
@@ -268,13 +267,14 @@
}
Box(modifier) {
+ Box(draggingModifier) { content(dragging) }
AnimatedVisibility(
+ modifier = Modifier.matchParentSize(),
visible = (dragging || selected) && !dragDropState.isDraggingToRemove,
enter = fadeIn(),
exit = fadeOut()
) {
- HighlightedItem()
+ HighlightedItem(Modifier.matchParentSize())
}
- Box(modifier = draggingModifier, propagateMinConstraints = true) { content(dragging) }
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorTest.kt
index 97c407c..970ce1f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorTest.kt
@@ -47,6 +47,17 @@
private val displayRepository by lazy { kosmos.displayRepository }
@Test
+ fun propertiesInitialized() =
+ testScope.runTest {
+ val propertiesInitialized by collectLastValue(underTest.propertiesInitialized)
+ assertThat(propertiesInitialized).isFalse()
+
+ repository.supportsUdfps()
+ runCurrent()
+ assertThat(propertiesInitialized).isTrue()
+ }
+
+ @Test
fun sensorLocation_resolution1f() =
testScope.runTest {
val currSensorLocation by collectLastValue(underTest.sensorLocation)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
index b3380ff..69a1a0f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.data.repository
import android.graphics.Point
+import android.os.PowerManager.WAKE_REASON_UNKNOWN
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -26,8 +27,9 @@
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.kosmos.testScope
-import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
-import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.power.data.repository.powerRepository
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.statusbar.CircleReveal
import com.android.systemui.statusbar.LightRevealEffect
import com.android.systemui.testKosmos
@@ -51,7 +53,7 @@
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val fakeKeyguardRepository = kosmos.fakeKeyguardRepository
- private val powerInteractor = kosmos.powerInteractor
+ private val powerRepository = kosmos.powerRepository
private lateinit var underTest: LightRevealScrimRepositoryImpl
@get:Rule val animatorTestRule = AnimatorTestRule(this)
@@ -63,7 +65,7 @@
LightRevealScrimRepositoryImpl(
kosmos.fakeKeyguardRepository,
context,
- kosmos.powerInteractor,
+ powerRepository,
mock()
)
}
@@ -73,7 +75,14 @@
val values = mutableListOf<LightRevealEffect>()
val job = launch { underTest.revealEffect.collect { values.add(it) } }
- powerInteractor.setAwakeForTest()
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_WAKE,
+ lastWakeReason = WakeSleepReason.fromPowerManagerWakeReason(WAKE_REASON_UNKNOWN),
+ powerButtonLaunchGestureTriggered =
+ powerRepository.wakefulness.value.powerButtonLaunchGestureTriggered,
+ )
+ powerRepository.updateWakefulness(rawState = WakefulnessState.AWAKE)
+
// We should initially emit the default reveal effect.
runCurrent()
values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT })
@@ -171,7 +180,7 @@
testScope.runTest {
val value by collectLastValue(underTest.revealAmount)
runCurrent()
- underTest.startRevealAmountAnimator(true)
+ underTest.startRevealAmountAnimator(true, 500L)
assertEquals(0.0f, value)
animatorTestRule.advanceTimeBy(500L)
assertEquals(1.0f, value)
@@ -183,11 +192,11 @@
testScope.runTest {
val value by collectLastValue(underTest.revealAmount)
runCurrent()
- underTest.startRevealAmountAnimator(true)
+ underTest.startRevealAmountAnimator(true, 500L)
assertEquals(0.0f, value)
animatorTestRule.advanceTimeBy(250L)
assertEquals(0.5f, value)
- underTest.startRevealAmountAnimator(true)
+ underTest.startRevealAmountAnimator(true, 500L)
animatorTestRule.advanceTimeBy(250L)
assertEquals(1.0f, value)
}
@@ -198,9 +207,9 @@
testScope.runTest {
val lastValue by collectLastValue(underTest.revealAmount)
runCurrent()
- underTest.startRevealAmountAnimator(true)
+ underTest.startRevealAmountAnimator(true, 500L)
animatorTestRule.advanceTimeBy(500L)
- underTest.startRevealAmountAnimator(false)
+ underTest.startRevealAmountAnimator(false, 500L)
animatorTestRule.advanceTimeBy(500L)
assertEquals(0.0f, lastValue)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
index 2b6e6c7..3e0a1f3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
@@ -24,7 +24,6 @@
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.LightRevealEffect
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.testKosmos
@@ -50,7 +49,6 @@
private val fakeLightRevealScrimRepository = kosmos.fakeLightRevealScrimRepository
private val fakeKeyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
- private val testScope = kosmos.testScope
private val underTest = kosmos.lightRevealScrimInteractor
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/PanelExpansionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImplTest.kt
similarity index 78%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/PanelExpansionInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImplTest.kt
index 6b5997f..16b68cc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/PanelExpansionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImplTest.kt
@@ -16,24 +16,21 @@
@file:OptIn(ExperimentalCoroutinesApi::class)
-package com.android.systemui.scene.domain.interactor
+package com.android.systemui.shade.domain.interactor
-import android.platform.test.annotations.DisableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
-import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
-import com.android.systemui.shade.data.repository.fakeShadeRepository
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.panelExpansionInteractor
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -48,7 +45,7 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
-class PanelExpansionInteractorTest : SysuiTestCase() {
+class PanelExpansionInteractorImplTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
@@ -60,9 +57,8 @@
ObservableTransitionState.Idle(Scenes.Lockscreen)
)
private val fakeSceneDataSource = kosmos.fakeSceneDataSource
- private val fakeShadeRepository = kosmos.fakeShadeRepository
- private lateinit var underTest: PanelExpansionInteractor
+ private lateinit var underTest: PanelExpansionInteractorImpl
@Before
fun setUp() {
@@ -73,7 +69,7 @@
@EnableSceneContainer
fun legacyPanelExpansion_whenIdle_whenLocked() =
testScope.runTest {
- underTest = kosmos.panelExpansionInteractor
+ underTest = kosmos.panelExpansionInteractorImpl
setUnlocked(false)
val panelExpansion by collectLastValue(underTest.legacyPanelExpansion)
@@ -97,7 +93,7 @@
@EnableSceneContainer
fun legacyPanelExpansion_whenIdle_whenUnlocked() =
testScope.runTest {
- underTest = kosmos.panelExpansionInteractor
+ underTest = kosmos.panelExpansionInteractorImpl
setUnlocked(true)
val panelExpansion by collectLastValue(underTest.legacyPanelExpansion)
@@ -116,33 +112,6 @@
changeScene(Scenes.Communal) { assertThat(panelExpansion).isEqualTo(1f) }
assertThat(panelExpansion).isEqualTo(1f)
}
-
- @Test
- @DisableFlags(FLAG_SCENE_CONTAINER)
- fun legacyPanelExpansion_whenInLegacyMode() =
- testScope.runTest {
- underTest = kosmos.panelExpansionInteractor
- val leet = 0.1337f
- fakeShadeRepository.setLegacyShadeExpansion(leet)
- setUnlocked(false)
- val panelExpansion by collectLastValue(underTest.legacyPanelExpansion)
-
- changeScene(Scenes.Lockscreen)
- assertThat(panelExpansion).isEqualTo(leet)
-
- changeScene(Scenes.Bouncer)
- assertThat(panelExpansion).isEqualTo(leet)
-
- changeScene(Scenes.Shade)
- assertThat(panelExpansion).isEqualTo(leet)
-
- changeScene(Scenes.QuickSettings)
- assertThat(panelExpansion).isEqualTo(leet)
-
- changeScene(Scenes.Communal)
- assertThat(panelExpansion).isEqualTo(leet)
- }
-
private fun TestScope.setUnlocked(isUnlocked: Boolean) {
val isDeviceUnlocked by collectLastValue(deviceUnlockedInteractor.isDeviceUnlocked)
deviceEntryRepository.setUnlocked(isUnlocked)
diff --git a/packages/SystemUI/res/drawable/qs_tile_background_flagged.xml b/packages/SystemUI/res/drawable/qs_tile_background_flagged.xml
new file mode 100644
index 0000000..cf7a730
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_tile_background_flagged.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+ <!-- Since this layer list has just one layer, we can remove it and replace with the inner
+ layer drawable. However this should only be done when the flag
+ com.android.systemui.qs_tile_focus_state has completed all its stages and this drawable
+ fully replaces the previous one to ensure consistency with code sections searching for
+ specific ids in drawable hierarchy -->
+ <item
+ android:id="@id/background">
+ <layer-list>
+ <item
+ android:id="@+id/qs_tile_background_base"
+ android:drawable="@drawable/qs_tile_background_shape" />
+ <item android:id="@+id/qs_tile_background_overlay">
+ <selector>
+ <item
+ android:state_hovered="true"
+ android:drawable="@drawable/qs_tile_background_shape" />
+ </selector>
+ </item>
+ <!-- In the layer below we have negative insets because we need the focus outline
+ to draw outside the bounds, around the main background. We use 5dp because
+ the outline stroke is 3dp and the required padding is 2dp.-->
+ <item
+ android:top="-5dp"
+ android:right="-5dp"
+ android:left="-5dp"
+ android:bottom="-5dp">
+ <selector>
+ <item
+ android:state_focused="true"
+ android:drawable="@drawable/qs_tile_focused_background"/>
+ </selector>
+ </item>
+ </layer-list>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_tile_focused_background.xml b/packages/SystemUI/res/drawable/qs_tile_focused_background.xml
new file mode 100644
index 0000000..fd456df
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_tile_focused_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <corners android:radius="30dp"/>
+ <stroke android:width="3dp" android:color="?androidprv:attr/materialColorSecondaryFixed"/>
+</shape>
\ No newline at end of file
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/strings.xml b/packages/SystemUI/res/values/strings.xml
index f71c415..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>
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/systemui/SystemUIAppComponentFactoryBase.kt b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt
index e88aaf01..aab0b1e 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt
@@ -22,7 +22,6 @@
import android.content.ContentProvider
import android.content.Context
import android.content.Intent
-import android.util.Log
import androidx.core.app.AppComponentFactory
import com.android.systemui.dagger.ContextComponentHelper
import com.android.systemui.dagger.SysUIComponent
@@ -91,7 +90,8 @@
return app
}
- @UsesReflection(KeepTarget(instanceOfClassConstant = SysUIComponent::class, methodName = "inject"))
+ @UsesReflection(
+ KeepTarget(instanceOfClassConstant = SysUIComponent::class, methodName = "inject"))
override fun instantiateProviderCompat(cl: ClassLoader, className: String): ContentProvider {
val contentProvider = super.instantiateProviderCompat(cl, className)
if (contentProvider is ContextInitializer) {
@@ -103,11 +103,12 @@
.getMethod("inject", contentProvider.javaClass)
injectMethod.invoke(rootComponent, contentProvider)
} catch (e: NoSuchMethodException) {
- Log.w(TAG, "No injector for class: " + contentProvider.javaClass, e)
+ throw RuntimeException("No injector for class: " + contentProvider.javaClass, e)
} catch (e: IllegalAccessException) {
- Log.w(TAG, "No injector for class: " + contentProvider.javaClass, e)
+ throw RuntimeException("Injector inaccessible for class: " +
+ contentProvider.javaClass, e)
} catch (e: InvocationTargetException) {
- Log.w(TAG, "No injector for class: " + contentProvider.javaClass, e)
+ throw RuntimeException("Error while injecting: " + contentProvider.javaClass, e)
}
initializer
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
index 6d4baf4..cd3b8a6 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
@@ -17,6 +17,7 @@
package com.android.systemui.accessibility.floatingmenu;
import static android.view.WindowInsets.Type.ime;
+import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
import static androidx.core.view.WindowInsetsCompat.Type;
@@ -48,6 +49,7 @@
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.ArraySet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
@@ -64,6 +66,7 @@
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate;
+import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto;
@@ -162,35 +165,45 @@
final Runnable mDismissMenuAction = new Runnable() {
@Override
public void run() {
- mSecureSettings.putStringForUser(
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, /* value= */ "",
- UserHandle.USER_CURRENT);
+ if (android.view.accessibility.Flags.a11yQsShortcut()) {
+ mAccessibilityManager.enableShortcutsForTargets(
+ /* enable= */ false,
+ ShortcutConstants.UserShortcutType.SOFTWARE,
+ new ArraySet<>(mAccessibilityManager.getAccessibilityShortcutTargets(
+ ACCESSIBILITY_BUTTON)),
+ mSecureSettings.getRealUserHandle(UserHandle.USER_CURRENT)
+ );
+ } else {
+ mSecureSettings.putStringForUser(
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, /* value= */ "",
+ UserHandle.USER_CURRENT);
- final List<ComponentName> hardwareKeyShortcutComponents =
- mAccessibilityManager.getAccessibilityShortcutTargets(
- ACCESSIBILITY_SHORTCUT_KEY)
- .stream()
- .map(ComponentName::unflattenFromString)
- .toList();
+ final List<ComponentName> hardwareKeyShortcutComponents =
+ mAccessibilityManager.getAccessibilityShortcutTargets(
+ ACCESSIBILITY_SHORTCUT_KEY)
+ .stream()
+ .map(ComponentName::unflattenFromString)
+ .toList();
- // Should disable the corresponding service when the fragment type is
- // INVISIBLE_TOGGLE, which will enable service when the shortcut is on.
- final List<AccessibilityServiceInfo> serviceInfoList =
- mAccessibilityManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
- serviceInfoList.forEach(info -> {
- if (getAccessibilityServiceFragmentType(info) != INVISIBLE_TOGGLE) {
- return;
- }
+ // Should disable the corresponding service when the fragment type is
+ // INVISIBLE_TOGGLE, which will enable service when the shortcut is on.
+ final List<AccessibilityServiceInfo> serviceInfoList =
+ mAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+ serviceInfoList.forEach(info -> {
+ if (getAccessibilityServiceFragmentType(info) != INVISIBLE_TOGGLE) {
+ return;
+ }
- final ComponentName serviceComponentName = info.getComponentName();
- if (hardwareKeyShortcutComponents.contains(serviceComponentName)) {
- return;
- }
+ final ComponentName serviceComponentName = info.getComponentName();
+ if (hardwareKeyShortcutComponents.contains(serviceComponentName)) {
+ return;
+ }
- setAccessibilityServiceState(getContext(), serviceComponentName, /* enabled= */
- false);
- });
+ setAccessibilityServiceState(getContext(), serviceComponentName, /* enabled= */
+ false);
+ });
+ }
mFloatingMenu.hide();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt
index 0c0ed77..40d38dd 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt
@@ -51,6 +51,8 @@
* There is never more than one instance of the FingerprintProperty at any given time.
*/
interface FingerprintPropertyRepository {
+ /** Whether the fingerprint properties have been initialized yet. */
+ val propertiesInitialized: StateFlow<Boolean>
/** The id of fingerprint sensor. */
val sensorId: Flow<Int>
@@ -59,7 +61,7 @@
val strength: Flow<SensorStrength>
/** The types of fingerprint sensor (rear, ultrasonic, optical, etc.). */
- val sensorType: Flow<FingerprintSensorType>
+ val sensorType: StateFlow<FingerprintSensorType>
/** The sensor location relative to each physical display. */
val sensorLocations: Flow<Map<String, SensorLocationInternal>>
@@ -105,15 +107,30 @@
.stateIn(
applicationScope,
started = SharingStarted.Eagerly,
- initialValue = DEFAULT_PROPS,
+ initialValue = UNINITIALIZED_PROPS,
+ )
+
+ override val propertiesInitialized: StateFlow<Boolean> =
+ props
+ .map { it != UNINITIALIZED_PROPS }
+ .stateIn(
+ applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = props.value != UNINITIALIZED_PROPS,
)
override val sensorId: Flow<Int> = props.map { it.sensorId }
override val strength: Flow<SensorStrength> = props.map { it.sensorStrength.toSensorStrength() }
- override val sensorType: Flow<FingerprintSensorType> =
- props.map { it.sensorType.toSensorType() }
+ override val sensorType: StateFlow<FingerprintSensorType> =
+ props
+ .map { it.sensorType.toSensorType() }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = props.value.sensorType.toSensorType(),
+ )
override val sensorLocations: Flow<Map<String, SensorLocationInternal>> =
props.map {
@@ -124,6 +141,17 @@
companion object {
private const val TAG = "FingerprintPropertyRepositoryImpl"
+ private val UNINITIALIZED_PROPS =
+ FingerprintSensorPropertiesInternal(
+ -2 /* sensorId */,
+ SensorProperties.STRENGTH_CONVENIENCE,
+ 0 /* maxEnrollmentsPerUser */,
+ listOf<ComponentInfoInternal>(),
+ FingerprintSensorProperties.TYPE_UNKNOWN,
+ false /* halControlsIllumination */,
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT)
+ )
private val DEFAULT_PROPS =
FingerprintSensorPropertiesInternal(
-1 /* sensorId */,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt
index ff9cdbd..5ae2ff0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt
@@ -24,22 +24,35 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
@SysUISingleton
class FingerprintPropertyInteractor
@Inject
constructor(
+ @Application private val applicationScope: CoroutineScope,
@Application private val context: Context,
repository: FingerprintPropertyRepository,
configurationInteractor: ConfigurationInteractor,
displayStateInteractor: DisplayStateInteractor,
) {
- val isUdfps: Flow<Boolean> = repository.sensorType.map { it.isUdfps() }
+ val propertiesInitialized: StateFlow<Boolean> = repository.propertiesInitialized
+ val isUdfps: StateFlow<Boolean> =
+ repository.sensorType
+ .map { it.isUdfps() }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = repository.sensorType.value.isUdfps(),
+ )
/**
* Devices with multiple physical displays use unique display ids to determine which sensor is
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt
index 72b9da6..80b52ed 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt
@@ -16,17 +16,17 @@
package com.android.systemui.deviceentry.domain.interactor
-import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
+import com.android.systemui.biometrics.domain.interactor.FingerprintPropertyInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.map
/** Encapsulates business logic for device entry under-display fingerprint state changes. */
@ExperimentalCoroutinesApi
@@ -34,14 +34,13 @@
class DeviceEntryUdfpsInteractor
@Inject
constructor(
+ fingerprintPropertyInteractor: FingerprintPropertyInteractor,
// TODO (b/309655554): create & use interactors for these repositories
- fingerprintPropertyRepository: FingerprintPropertyRepository,
fingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
biometricSettingsRepository: BiometricSettingsRepository,
) {
/** Whether the device supports an under display fingerprint sensor. */
- val isUdfpsSupported: Flow<Boolean> =
- fingerprintPropertyRepository.sensorType.map { it.isUdfps() }
+ val isUdfpsSupported: StateFlow<Boolean> = fingerprintPropertyInteractor.isUdfps
/** Whether the under-display fingerprint sensor is enrolled and enabled for device entry. */
val isUdfpsEnrolledAndEnabled: Flow<Boolean> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
index 0659c7c..a49b3ae 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
@@ -19,7 +19,6 @@
import android.os.Handler
import android.util.Log
-import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
@@ -30,7 +29,6 @@
import java.io.PrintWriter
import java.util.TreeMap
import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -49,7 +47,6 @@
class KeyguardBlueprintRepository
@Inject
constructor(
- configurationRepository: ConfigurationRepository,
blueprints: Set<@JvmSuppressWildcards KeyguardBlueprint>,
@Main val handler: Handler,
val assert: ThreadAssert,
@@ -60,7 +57,6 @@
TreeMap<String, KeyguardBlueprint>().apply { putAll(blueprints.associateBy { it.id }) }
val blueprint: MutableStateFlow<KeyguardBlueprint> = MutableStateFlow(blueprintIdMap[DEFAULT]!!)
val refreshTransition = MutableSharedFlow<Config>(extraBufferCapacity = 1)
- val configurationChange: Flow<Unit> = configurationRepository.onAnyConfigurationChange
private var targetTransitionConfig: Config? = null
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
index d9479de..eac476f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
@@ -26,7 +26,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
-import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.power.data.repository.PowerRepository
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakeSleepReason.TAP
import com.android.systemui.res.R
@@ -47,6 +47,7 @@
import kotlinx.coroutines.flow.map
val DEFAULT_REVEAL_EFFECT = LiftReveal
+const val DEFAULT_REVEAL_DURATION = 500L
/**
* Encapsulates state relevant to the light reveal scrim, the view used to reveal/hide screen
@@ -63,7 +64,9 @@
val revealAmount: Flow<Float>
- fun startRevealAmountAnimator(reveal: Boolean)
+ val isAnimating: Boolean
+
+ fun startRevealAmountAnimator(reveal: Boolean, duration: Long = DEFAULT_REVEAL_DURATION)
}
@SysUISingleton
@@ -72,7 +75,7 @@
constructor(
keyguardRepository: KeyguardRepository,
val context: Context,
- powerInteractor: PowerInteractor,
+ powerRepository: PowerRepository,
private val scrimLogger: ScrimLogger,
) : LightRevealScrimRepository {
companion object {
@@ -125,7 +128,7 @@
/** The reveal effect we'll use for the next non-biometric unlock (tap, power button, etc). */
private val nonBiometricRevealEffect: Flow<LightRevealEffect?> =
- powerInteractor.detailedWakefulness.flatMapLatest { wakefulnessModel ->
+ powerRepository.wakefulness.flatMapLatest { wakefulnessModel ->
when {
wakefulnessModel.isAwakeOrAsleepFrom(WakeSleepReason.POWER_BUTTON) ->
powerButtonRevealEffect
@@ -134,7 +137,7 @@
}
}
- private val revealAmountAnimator = ValueAnimator.ofFloat(0f, 1f).apply { duration = 500 }
+ private val revealAmountAnimator = ValueAnimator.ofFloat(0f, 1f)
override val revealAmount: Flow<Float> = callbackFlow {
val updateListener =
@@ -149,18 +152,21 @@
revealAmountAnimator.addUpdateListener(updateListener)
awaitClose { revealAmountAnimator.removeUpdateListener(updateListener) }
}
+ override val isAnimating: Boolean
+ get() = revealAmountAnimator.isRunning
private var willBeOrIsRevealed: Boolean? = null
- override fun startRevealAmountAnimator(reveal: Boolean) {
+ override fun startRevealAmountAnimator(reveal: Boolean, duration: Long) {
if (reveal == willBeOrIsRevealed) return
willBeOrIsRevealed = reveal
+ revealAmountAnimator.duration = duration
if (reveal && !revealAmountAnimator.isRunning) {
revealAmountAnimator.start()
} else {
revealAmountAnimator.reverse()
}
- scrimLogger.d(TAG, "startRevealAmountAnimator, reveal: ", reveal)
+ scrimLogger.d(TAG, "startRevealAmountAnimator, reveal", reveal)
}
override val revealEffect =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
index bc3f0cc..c877192 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
@@ -20,6 +20,8 @@
package com.android.systemui.keyguard.domain.interactor
import android.content.Context
+import com.android.systemui.biometrics.domain.interactor.FingerprintPropertyInteractor
+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.keyguard.data.repository.KeyguardBlueprintRepository
@@ -34,7 +36,9 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
@@ -47,6 +51,8 @@
private val context: Context,
private val splitShadeStateController: SplitShadeStateController,
private val clockInteractor: KeyguardClockInteractor,
+ configurationInteractor: ConfigurationInteractor,
+ fingerprintPropertyInteractor: FingerprintPropertyInteractor,
) {
/** The current blueprint for the lockscreen. */
@@ -58,11 +64,14 @@
*/
val refreshTransition = keyguardBlueprintRepository.refreshTransition
+ private val configOrPropertyChange =
+ merge(
+ configurationInteractor.onAnyConfigurationChange,
+ fingerprintPropertyInteractor.propertiesInitialized.filter { it }.map {}, // map to Unit
+ )
init {
applicationScope.launch {
- keyguardBlueprintRepository.configurationChange
- .onStart { emit(Unit) }
- .collect { updateBlueprint() }
+ configOrPropertyChange.onStart { emit(Unit) }.collect { updateBlueprint() }
}
applicationScope.launch { clockInteractor.currentClock.collect { updateBlueprint() } }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
index 8905c9e..2d944c6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
@@ -25,14 +25,13 @@
import com.android.systemui.power.shared.model.ScreenPowerState
import com.android.systemui.statusbar.LightRevealEffect
import com.android.systemui.util.kotlin.sample
+import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
-@ExperimentalCoroutinesApi
@SysUISingleton
class LightRevealScrimInteractor
@Inject
@@ -41,7 +40,7 @@
private val lightRevealScrimRepository: LightRevealScrimRepository,
@Application private val scope: CoroutineScope,
private val scrimLogger: ScrimLogger,
- private val powerInteractor: PowerInteractor,
+ private val powerInteractor: Lazy<PowerInteractor>,
) {
init {
listenForStartedKeyguardTransitionStep()
@@ -81,31 +80,33 @@
}
private fun screenIsShowingContent() =
- powerInteractor.screenPowerState.value != ScreenPowerState.SCREEN_OFF &&
- powerInteractor.screenPowerState.value != ScreenPowerState.SCREEN_TURNING_ON
+ powerInteractor.get().screenPowerState.value != ScreenPowerState.SCREEN_OFF &&
+ powerInteractor.get().screenPowerState.value != ScreenPowerState.SCREEN_TURNING_ON
+
+ val isAnimating: Boolean
+ get() = lightRevealScrimRepository.isAnimating
+
+ /**
+ * Whether the light reveal scrim will be fully revealed (revealAmount = 1.0f) in the given
+ * state after the transition is complete. If false, scrim will be fully hidden.
+ */
+ private fun willBeRevealedInState(state: KeyguardState): Boolean {
+ return when (state) {
+ KeyguardState.OFF -> false
+ KeyguardState.DOZING -> false
+ KeyguardState.AOD -> false
+ KeyguardState.DREAMING -> true
+ KeyguardState.DREAMING_LOCKSCREEN_HOSTED -> true
+ KeyguardState.GLANCEABLE_HUB -> true
+ KeyguardState.ALTERNATE_BOUNCER -> true
+ KeyguardState.PRIMARY_BOUNCER -> true
+ KeyguardState.LOCKSCREEN -> true
+ KeyguardState.GONE -> true
+ KeyguardState.OCCLUDED -> true
+ }
+ }
companion object {
-
- /**
- * Whether the light reveal scrim will be fully revealed (revealAmount = 1.0f) in the given
- * state after the transition is complete. If false, scrim will be fully hidden.
- */
- private fun willBeRevealedInState(state: KeyguardState): Boolean {
- return when (state) {
- KeyguardState.OFF -> false
- KeyguardState.DOZING -> false
- KeyguardState.AOD -> false
- KeyguardState.DREAMING -> true
- KeyguardState.DREAMING_LOCKSCREEN_HOSTED -> true
- KeyguardState.GLANCEABLE_HUB -> true
- KeyguardState.ALTERNATE_BOUNCER -> true
- KeyguardState.PRIMARY_BOUNCER -> true
- KeyguardState.LOCKSCREEN -> true
- KeyguardState.GONE -> true
- KeyguardState.OCCLUDED -> true
- }
- }
-
val TAG = LightRevealScrimInteractor::class.simpleName!!
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
index 3fc9b42..1085f94 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
@@ -26,7 +26,6 @@
import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
-import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.LockIconView
import com.android.keyguard.LockIconViewController
import com.android.systemui.Flags.keyguardBottomAreaRefactor
@@ -56,7 +55,6 @@
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
- private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val authController: AuthController,
private val windowManager: WindowManager,
private val context: Context,
@@ -111,7 +109,12 @@
}
override fun applyConstraints(constraintSet: ConstraintSet) {
- val isUdfpsSupported = keyguardUpdateMonitor.isUdfpsSupported
+ val isUdfpsSupported =
+ if (DeviceEntryUdfpsRefactor.isEnabled) {
+ deviceEntryIconViewModel.get().isUdfpsSupported.value
+ } else {
+ authController.isUdfpsSupported
+ }
val scaleFactor: Float = authController.scaleFactor
val mBottomPaddingPx =
context.resources.getDimensionPixelSize(R.dimen.lock_icon_margin_bottom)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
index 662a77e..4c0a949 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
@@ -20,6 +20,8 @@
import android.content.Context
import com.android.settingslib.Utils
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
@@ -30,12 +32,14 @@
import kotlinx.coroutines.flow.onStart
/** Models the UI state for the device entry icon background view. */
+@Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA")
@ExperimentalCoroutinesApi
class DeviceEntryBackgroundViewModel
@Inject
constructor(
val context: Context,
val deviceEntryIconViewModel: DeviceEntryIconViewModel,
+ keyguardTransitionInteractor: KeyguardTransitionInteractor,
configurationInteractor: ConfigurationInteractor,
lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel,
aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
@@ -94,6 +98,23 @@
alternateBouncerToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
)
.merge()
+ .onStart {
+ when (
+ keyguardTransitionInteractor.currentKeyguardState.replayCache.last()
+ ) {
+ KeyguardState.GLANCEABLE_HUB,
+ KeyguardState.DREAMING_LOCKSCREEN_HOSTED,
+ KeyguardState.GONE,
+ KeyguardState.OCCLUDED,
+ KeyguardState.OFF,
+ KeyguardState.DOZING,
+ KeyguardState.DREAMING,
+ KeyguardState.PRIMARY_BOUNCER,
+ KeyguardState.AOD -> emit(0f)
+ KeyguardState.ALTERNATE_BOUNCER,
+ KeyguardState.LOCKSCREEN -> emit(1f)
+ }
+ }
} else {
flowOf(0f)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
index bd19c80..1a01897 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
@@ -36,6 +36,7 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
@@ -62,6 +63,7 @@
private val deviceEntryInteractor: DeviceEntryInteractor,
private val deviceEntrySourceInteractor: DeviceEntrySourceInteractor,
) {
+ val isUdfpsSupported: StateFlow<Boolean> = deviceEntryUdfpsInteractor.isUdfpsSupported
private val intEvaluator = IntEvaluator()
private val floatEvaluator = FloatEvaluator()
private val showingAlternateBouncer: Flow<Boolean> =
@@ -137,7 +139,7 @@
) { alpha, alphaMultiplier ->
alpha * alphaMultiplier
}
- val useBackgroundProtection: Flow<Boolean> = deviceEntryUdfpsInteractor.isUdfpsSupported
+ val useBackgroundProtection: StateFlow<Boolean> = isUdfpsSupported
val burnInOffsets: Flow<BurnInOffsets> =
deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { udfpsEnrolled ->
if (udfpsEnrolled) {
@@ -211,7 +213,7 @@
val isLongPressEnabled: Flow<Boolean> =
combine(
iconType,
- deviceEntryUdfpsInteractor.isUdfpsSupported,
+ isUdfpsSupported,
) { deviceEntryStatus, isUdfps ->
when (deviceEntryStatus) {
DeviceEntryIconView.IconType.LOCK -> isUdfps
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index e5af8e6..58858df 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -46,7 +46,6 @@
import com.android.systemui.FontSizeUtils;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
-import com.android.systemui.res.R;
import com.android.systemui.qs.QSEditEvent;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.TileLayout;
@@ -57,6 +56,7 @@
import com.android.systemui.qs.dagger.QSThemedContext;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tileimpl.QSTileViewImpl;
+import com.android.systemui.res.R;
import java.util.ArrayList;
import java.util.List;
@@ -319,6 +319,9 @@
}
FrameLayout frame = (FrameLayout) inflater.inflate(R.layout.qs_customize_tile_frame, parent,
false);
+ if (com.android.systemui.Flags.qsTileFocusState()) {
+ frame.setClipChildren(false);
+ }
View view = new CustomizeTileView(context);
frame.addView(view);
return new Holder(frame);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 9fefcbd..6cc682a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -47,6 +47,7 @@
import androidx.annotation.VisibleForTesting
import com.android.app.tracing.traceSection
import com.android.settingslib.Utils
+import com.android.systemui.Flags
import com.android.systemui.FontSizeUtils
import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
@@ -134,7 +135,7 @@
*/
protected var showRippleEffect = true
- private lateinit var ripple: RippleDrawable
+ private lateinit var qsTileBackground: LayerDrawable
private lateinit var backgroundDrawable: LayerDrawable
private lateinit var backgroundBaseDrawable: Drawable
private lateinit var backgroundOverlayDrawable: Drawable
@@ -283,15 +284,20 @@
addView(sideView)
}
- fun createTileBackground(): Drawable {
- ripple = mContext.getDrawable(R.drawable.qs_tile_background) as RippleDrawable
- backgroundDrawable = ripple.findDrawableByLayerId(R.id.background) as LayerDrawable
+ private fun createTileBackground(): Drawable {
+ qsTileBackground = if (Flags.qsTileFocusState()) {
+ mContext.getDrawable(R.drawable.qs_tile_background_flagged) as LayerDrawable
+ } else {
+ mContext.getDrawable(R.drawable.qs_tile_background) as RippleDrawable
+ }
+ backgroundDrawable =
+ qsTileBackground.findDrawableByLayerId(R.id.background) as LayerDrawable
backgroundBaseDrawable =
backgroundDrawable.findDrawableByLayerId(R.id.qs_tile_background_base)
backgroundOverlayDrawable =
backgroundDrawable.findDrawableByLayerId(R.id.qs_tile_background_overlay)
backgroundOverlayDrawable.mutate().setTintMode(PorterDuff.Mode.SRC)
- return ripple
+ return qsTileBackground
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
@@ -366,14 +372,16 @@
override fun setClickable(clickable: Boolean) {
super.setClickable(clickable)
- background = if (clickable && showRippleEffect) {
- ripple.also {
- // In case that the colorBackgroundDrawable was used as the background, make sure
- // it has the correct callback instead of null
- backgroundDrawable.callback = it
+ if (!Flags.qsTileFocusState()){
+ background = if (clickable && showRippleEffect) {
+ qsTileBackground.also {
+ // In case that the colorBackgroundDrawable was used as the background, make sure
+ // it has the correct callback instead of null
+ backgroundDrawable.callback = it
+ }
+ } else {
+ backgroundDrawable
}
- } else {
- backgroundDrawable
}
}
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/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 5f8b5dd..d0ff338 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -33,6 +33,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
@@ -111,6 +112,7 @@
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder;
+import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.ShellInterface;
import dagger.Lazy;
@@ -673,9 +675,13 @@
}
@Override
- public void enterStageSplitFromRunningApp(boolean leftOrTop) {
+ public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {
if (mOverviewProxy != null) {
try {
+ if (DesktopModeStatus.isEnabled() && (sysUiState.getFlags()
+ & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0) {
+ return;
+ }
mOverviewProxy.enterStageSplitFromRunningApp(leftOrTop);
} catch (RemoteException e) {
Log.w(TAG_OPS, "Unable to enter stage split from the current running app");
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/PanelExpansionInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/PanelExpansionInteractor.kt
deleted file mode 100644
index 3a5ea5c..0000000
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/PanelExpansionInteractor.kt
+++ /dev/null
@@ -1,105 +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.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.scene.domain.interactor
-
-import com.android.compose.animation.scene.ObservableTransitionState
-import com.android.compose.animation.scene.SceneKey
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.scene.shared.flag.SceneContainerFlag
-import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.data.repository.ShadeRepository
-import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.map
-
-@SysUISingleton
-class PanelExpansionInteractor
-@Inject
-constructor(
- sceneInteractor: SceneInteractor,
- shadeRepository: ShadeRepository,
-) {
-
- /**
- * The amount by which the "panel" has been expanded (`0` when fully collapsed, `1` when fully
- * expanded).
- *
- * This is a legacy concept from the time when the "panel" included the notification/QS shades
- * as well as the keyguard (lockscreen and bouncer). This value is meant only for
- * backwards-compatibility and should not be consumed by newer code.
- */
- @Deprecated("Use SceneInteractor.currentScene instead.")
- val legacyPanelExpansion: Flow<Float> =
- if (SceneContainerFlag.isEnabled) {
- sceneInteractor.transitionState.flatMapLatest { state ->
- when (state) {
- is ObservableTransitionState.Idle ->
- flowOf(
- if (state.scene != Scenes.Gone) {
- // When resting on a non-Gone scene, the panel is fully expanded.
- 1f
- } else {
- // When resting on the Gone scene, the panel is considered fully
- // collapsed.
- 0f
- }
- )
- is ObservableTransitionState.Transition ->
- when {
- state.fromScene == Scenes.Gone ->
- if (state.toScene.isExpandable()) {
- // Moving from Gone to a scene that can animate-expand has a
- // panel
- // expansion
- // that tracks with the transition.
- state.progress
- } else {
- // Moving from Gone to a scene that doesn't animate-expand
- // immediately makes
- // the panel fully expanded.
- flowOf(1f)
- }
- state.toScene == Scenes.Gone ->
- if (state.fromScene.isExpandable()) {
- // Moving to Gone from a scene that can animate-expand has a
- // panel
- // expansion
- // that tracks with the transition.
- state.progress.map { 1 - it }
- } else {
- // Moving to Gone from a scene that doesn't animate-expand
- // immediately makes
- // the panel fully collapsed.
- flowOf(0f)
- }
- else -> flowOf(1f)
- }
- }
- }
- } else {
- shadeRepository.legacyShadeExpansion
- }
-
- private fun SceneKey.isExpandable(): Boolean {
- return this == Scenes.Shade || this == Scenes.QuickSettings
- }
-}
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/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index a1644b2..fcd3327 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -246,6 +246,7 @@
import javax.inject.Provider;
import kotlinx.coroutines.CoroutineDispatcher;
+import kotlinx.coroutines.flow.Flow;
@SysUISingleton
public final class NotificationPanelViewController implements ShadeSurface, Dumpable {
@@ -1979,7 +1980,6 @@
mNotificationStackScrollLayoutController.resetScrollPosition();
}
- @Override
public void collapse(boolean animate, boolean delayed, float speedUpFactor) {
boolean waiting = false;
if (animate && !isFullyCollapsed()) {
@@ -1997,7 +1997,6 @@
}
}
- @Override
public void collapse(boolean delayed, float speedUpFactor) {
if (!canBeCollapsed()) {
return;
@@ -4000,11 +3999,15 @@
}
@Override
+ public Flow<Float> getLegacyPanelExpansion() {
+ return mShadeRepository.getLegacyShadeExpansion();
+ }
+
+ @Override
public boolean isFullyExpanded() {
return mExpandedHeight >= getMaxPanelTransitionDistance();
}
- @Override
public boolean isShadeFullyExpanded() {
if (mBarState == SHADE) {
return isFullyExpanded();
@@ -4035,7 +4038,6 @@
return !isFullyCollapsed() && !isTracking() && !isClosing();
}
- @Override
public void instantCollapse() {
abortAnimations();
setExpandedFraction(0f);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt
index 4054a86..25e27ae 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeEmptyImplModule.kt
@@ -21,6 +21,7 @@
import com.android.systemui.shade.data.repository.PrivacyChipRepositoryImpl
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.shade.data.repository.ShadeRepositoryImpl
+import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorEmptyImpl
import com.android.systemui.shade.domain.interactor.ShadeBackActionInteractor
@@ -66,5 +67,11 @@
@Binds
@SysUISingleton
+ abstract fun bindsPanelExpansionInteractor(
+ sbai: ShadeViewControllerEmptyImpl
+ ): PanelExpansionInteractor
+
+ @Binds
+ @SysUISingleton
abstract fun bindsPrivacyChipRepository(impl: PrivacyChipRepositoryImpl): PrivacyChipRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index 504dbfd..3e9a32b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -25,6 +25,8 @@
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.shade.data.repository.ShadeRepositoryImpl
import com.android.systemui.shade.domain.interactor.BaseShadeInteractor
+import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
+import com.android.systemui.shade.domain.interactor.PanelExpansionInteractorImpl
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorSceneContainerImpl
@@ -116,6 +118,20 @@
@Provides
@SysUISingleton
+ fun providePanelExpansionInteractor(
+ sceneContainerFlags: SceneContainerFlags,
+ sceneContainerOn: Provider<PanelExpansionInteractorImpl>,
+ sceneContainerOff: Provider<NotificationPanelViewController>
+ ): PanelExpansionInteractor {
+ return if (sceneContainerFlags.isEnabled()) {
+ sceneContainerOn.get()
+ } else {
+ sceneContainerOff.get()
+ }
+ }
+
+ @Provides
+ @SysUISingleton
fun provideQuickSettingsController(
sceneContainerFlags: SceneContainerFlags,
sceneContainerOn: Provider<QuickSettingsControllerSceneImpl>,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
index 941c6f3..5c276b1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
@@ -16,6 +16,7 @@
package com.android.systemui.shade
import android.view.ViewPropertyAnimator
+import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
import com.android.systemui.shade.domain.interactor.ShadeBackActionInteractor
import com.android.systemui.statusbar.GestureRecorder
import com.android.systemui.statusbar.phone.CentralSurfaces
@@ -26,7 +27,11 @@
* this class. If any method in this class is needed outside of CentralSurfacesImpl, it must be
* pulled up into ShadeViewController.
*/
-interface ShadeSurface : ShadeViewController, ShadeBackActionInteractor, ShadeLockscreenInteractor {
+interface ShadeSurface :
+ ShadeViewController,
+ ShadeBackActionInteractor,
+ ShadeLockscreenInteractor,
+ PanelExpansionInteractor {
/** Initialize objects instead of injecting to avoid circular dependencies. */
fun initDependencies(
centralSurfaces: CentralSurfaces,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
index 7a1637e..07236d1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
@@ -40,25 +40,6 @@
*/
val isPanelExpanded: Boolean
- /** Returns whether the shade is fully expanded in either QS or QQS. */
- val isShadeFullyExpanded: Boolean
-
- /**
- * Animates the collapse of a shade with the given delay and the default duration divided by
- * speedUpFactor.
- */
- fun collapse(delayed: Boolean, speedUpFactor: Float)
-
- /** Collapses the shade. */
- fun collapse(animate: Boolean, delayed: Boolean, speedUpFactor: Float)
-
- /** Collapses the shade instantly without animation. */
- fun instantCollapse()
-
- /** Returns whether the shade can be collapsed. */
- @Deprecated("Do not use outside of the shade package. Not supported by scenes.")
- fun canBeCollapsed(): Boolean
-
/** Returns whether the shade is in the process of collapsing. */
val isCollapsing: Boolean
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
index 3be3f6b..6e03686 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
@@ -19,23 +19,24 @@
import android.view.MotionEvent
import android.view.ViewGroup
import android.view.ViewTreeObserver
+import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
import com.android.systemui.shade.domain.interactor.ShadeBackActionInteractor
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController
import java.util.function.Consumer
import javax.inject.Inject
+import kotlinx.coroutines.flow.flowOf
/** Empty implementation of ShadeViewController for variants with no shade. */
class ShadeViewControllerEmptyImpl @Inject constructor() :
- ShadeViewController, ShadeBackActionInteractor, ShadeLockscreenInteractor {
+ ShadeViewController,
+ ShadeBackActionInteractor,
+ ShadeLockscreenInteractor,
+ PanelExpansionInteractor {
override fun expandToNotifications() {}
override val isExpandingOrCollapsing: Boolean = false
override val isExpanded: Boolean = false
override val isPanelExpanded: Boolean = false
- override val isShadeFullyExpanded: Boolean = false
- override fun collapse(delayed: Boolean, speedUpFactor: Float) {}
- override fun collapse(animate: Boolean, delayed: Boolean, speedUpFactor: Float) {}
- override fun instantCollapse() {}
override fun animateCollapseQs(fullyCollapse: Boolean) {}
override fun canBeCollapsed(): Boolean = false
override val isCollapsing: Boolean = false
@@ -86,6 +87,7 @@
override val shadeHeadsUpTracker = ShadeHeadsUpTrackerEmptyImpl()
override val shadeFoldAnimator = ShadeFoldAnimatorEmptyImpl()
+ override val legacyPanelExpansion = flowOf(0f)
}
class ShadeHeadsUpTrackerEmptyImpl : ShadeHeadsUpTracker {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractor.kt
new file mode 100644
index 0000000..01118bd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractor.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.shade.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Expansion-related methods used throughout SysUI before the addition of the scene container as the
+ * top layer component. This interface exists to allow the scene container to fulfil
+ * NotificationPanelViewController's contracts with the rest of SysUI. Once the scene container is
+ * the only shade implementation in SysUI, the remaining implementation of this should be deleted
+ * after inlining all of its method bodies. No new calls to any of these methods should be added.
+ */
+@SysUISingleton
+@Deprecated("Use ShadeInteractor instead.")
+interface PanelExpansionInteractor {
+ /**
+ * The amount by which the "panel" has been expanded (`0` when fully collapsed, `1` when fully
+ * expanded).
+ *
+ * This is a legacy concept from the time when the "panel" included the notification/QS shades
+ * as well as the keyguard (lockscreen and bouncer). This value is meant only for
+ * backwards-compatibility and should not be consumed by newer code.
+ */
+ @Deprecated("Use SceneInteractor.currentScene instead.") val legacyPanelExpansion: Flow<Float>
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt
new file mode 100644
index 0000000..20f73b0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorImpl.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.shade.domain.interactor
+
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.compose.animation.scene.SceneKey
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+
+@SysUISingleton
+class PanelExpansionInteractorImpl
+@Inject
+constructor(
+ sceneInteractor: SceneInteractor,
+) : PanelExpansionInteractor {
+
+ /**
+ * The amount by which the "panel" has been expanded (`0` when fully collapsed, `1` when fully
+ * expanded).
+ *
+ * This is a legacy concept from the time when the "panel" included the notification/QS shades
+ * as well as the keyguard (lockscreen and bouncer). This value is meant only for
+ * backwards-compatibility and should not be consumed by newer code.
+ */
+ @Deprecated("Use SceneInteractor.currentScene instead.")
+ override val legacyPanelExpansion: Flow<Float> =
+ sceneInteractor.transitionState.flatMapLatest { state ->
+ when (state) {
+ is ObservableTransitionState.Idle ->
+ flowOf(
+ if (state.scene != Scenes.Gone) {
+ // When resting on a non-Gone scene, the panel is fully expanded.
+ 1f
+ } else {
+ // When resting on the Gone scene, the panel is considered fully
+ // collapsed.
+ 0f
+ }
+ )
+ is ObservableTransitionState.Transition ->
+ when {
+ state.fromScene == Scenes.Gone ->
+ if (state.toScene.isExpandable()) {
+ // Moving from Gone to a scene that can animate-expand has a
+ // panel
+ // expansion
+ // that tracks with the transition.
+ state.progress
+ } else {
+ // Moving from Gone to a scene that doesn't animate-expand
+ // immediately makes
+ // the panel fully expanded.
+ flowOf(1f)
+ }
+ state.toScene == Scenes.Gone ->
+ if (state.fromScene.isExpandable()) {
+ // Moving to Gone from a scene that can animate-expand has a
+ // panel
+ // expansion
+ // that tracks with the transition.
+ state.progress.map { 1 - it }
+ } else {
+ // Moving to Gone from a scene that doesn't animate-expand
+ // immediately makes
+ // the panel fully collapsed.
+ flowOf(0f)
+ }
+ else -> flowOf(1f)
+ }
+ }
+ }
+
+ private fun SceneKey.isExpandable(): Boolean {
+ return this == Scenes.Shade || this == Scenes.QuickSettings
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
index 84afbed..3a5c5e1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
@@ -22,7 +22,7 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.qs.QS
-import com.android.systemui.scene.domain.interactor.PanelExpansionInteractor
+import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.PanelState
import com.android.systemui.shade.ShadeExpansionChangeEvent
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index bb81683..4275fc6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -169,7 +169,7 @@
private static final int MSG_TILE_SERVICE_REQUEST_LISTENING_STATE = 68 << MSG_SHIFT;
private static final int MSG_SHOW_REAR_DISPLAY_DIALOG = 69 << MSG_SHIFT;
private static final int MSG_MOVE_FOCUSED_TASK_TO_FULLSCREEN = 70 << MSG_SHIFT;
- private static final int MSG_ENTER_STAGE_SPLIT_FROM_RUNNING_APP = 71 << MSG_SHIFT;
+ private static final int MSG_MOVE_FOCUSED_TASK_TO_STAGE_SPLIT = 71 << MSG_SHIFT;
private static final int MSG_SHOW_MEDIA_OUTPUT_SWITCHER = 72 << MSG_SHIFT;
private static final int MSG_TOGGLE_TASKBAR = 73 << MSG_SHIFT;
private static final int MSG_SETTING_CHANGED = 74 << MSG_SHIFT;
@@ -503,9 +503,9 @@
default void moveFocusedTaskToFullscreen(int displayId) {}
/**
- * @see IStatusBar#enterStageSplitFromRunningApp
+ * @see IStatusBar#moveFocusedTaskToStageSplit
*/
- default void enterStageSplitFromRunningApp(boolean leftOrTop) {}
+ default void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {}
/**
* @see IStatusBar#showMediaOutputSwitcher
@@ -1338,10 +1338,13 @@
}
@Override
- public void enterStageSplitFromRunningApp(boolean leftOrTop) {
+ public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {
synchronized (mLock) {
- mHandler.obtainMessage(MSG_ENTER_STAGE_SPLIT_FROM_RUNNING_APP,
- leftOrTop).sendToTarget();
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = displayId;
+ args.argi2 = leftOrTop ? 1 : 0;
+ mHandler.obtainMessage(MSG_MOVE_FOCUSED_TASK_TO_STAGE_SPLIT,
+ args).sendToTarget();
}
}
@@ -1907,11 +1910,15 @@
}
break;
}
- case MSG_ENTER_STAGE_SPLIT_FROM_RUNNING_APP:
+ case MSG_MOVE_FOCUSED_TASK_TO_STAGE_SPLIT: {
+ args = (SomeArgs) msg.obj;
+ int displayId = args.argi1;
+ boolean leftOrTop = args.argi2 != 0;
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).enterStageSplitFromRunningApp((Boolean) msg.obj);
+ mCallbacks.get(i).moveFocusedTaskToStageSplit(displayId, leftOrTop);
}
break;
+ }
case MSG_SHOW_MEDIA_OUTPUT_SWITCHER:
args = (SomeArgs) msg.obj;
String clientPackageName = (String) args.arg1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 81f644f..4b16126 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -594,6 +594,7 @@
}
}
val cancelHandler = Runnable {
+ statusBarStateController.setLeaveOpenOnKeyguardHide(false)
draggedDownEntry?.apply {
setUserLocked(false)
notifyHeightChanged(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index deaf1d1..dfb0f9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -367,7 +367,8 @@
/* reason = */ reason,
/* showSnooze = */ adjustment.isSnoozeEnabled(),
/* isChildInGroup = */ adjustment.isChildInGroup(),
- /* isGroupSummary = */ adjustment.isGroupSummary()
+ /* isGroupSummary = */ adjustment.isGroupSummary(),
+ /* needsRedaction = */ adjustment.getNeedsRedaction()
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
index f03c313..e4db4c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
@@ -63,9 +63,16 @@
SensitiveContentCoordinator,
DynamicPrivacyController.Listener,
OnBeforeRenderListListener {
+ private val onSensitiveStateChanged = Runnable() {
+ invalidateList("onSensitiveStateChanged")
+ }
override fun attach(pipeline: NotifPipeline) {
dynamicPrivacyController.addListener(this)
+ if (screenshareNotificationHiding()) {
+ sensitiveNotificationProtectionController
+ .registerSensitiveStateListener(onSensitiveStateChanged)
+ }
pipeline.addOnBeforeRenderListListener(this)
pipeline.addPreRenderInvalidator(this)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
index 18460c3..7b8a062 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
@@ -61,5 +61,6 @@
val showSnooze: Boolean,
val isChildInGroup: Boolean = false,
val isGroupSummary: Boolean = false,
+ val needsRedaction: Boolean,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
index 0b9d19d..e0e5a35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
@@ -22,6 +22,7 @@
import android.os.HandlerExecutor
import android.os.UserHandle
import android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE
+import com.android.server.notification.Flags.screenshareNotificationHiding
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.settings.UserTracker
@@ -30,6 +31,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager
+import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController
import com.android.systemui.util.ListenerSet
import com.android.systemui.util.settings.SecureSettings
import javax.inject.Inject
@@ -43,6 +45,7 @@
@Main private val handler: Handler,
private val secureSettings: SecureSettings,
private val lockscreenUserManager: NotificationLockscreenUserManager,
+ private val sensitiveNotifProtectionController: SensitiveNotificationProtectionController,
private val sectionStyleProvider: SectionStyleProvider,
private val userTracker: UserTracker,
private val groupMembershipManager: GroupMembershipManager,
@@ -66,6 +69,11 @@
fun addDirtyListener(listener: Runnable) {
if (dirtyListeners.isEmpty()) {
lockscreenUserManager.addNotificationStateChangedListener(notifStateChangedListener)
+ if (screenshareNotificationHiding()) {
+ sensitiveNotifProtectionController.registerSensitiveStateListener(
+ onSensitiveStateChangedListener
+ )
+ }
updateSnoozeEnabled()
secureSettings.registerContentObserverForUser(
SHOW_NOTIFICATION_SNOOZE,
@@ -80,6 +88,11 @@
dirtyListeners.remove(listener)
if (dirtyListeners.isEmpty()) {
lockscreenUserManager.removeNotificationStateChangedListener(notifStateChangedListener)
+ if (screenshareNotificationHiding()) {
+ sensitiveNotifProtectionController.unregisterSensitiveStateListener(
+ onSensitiveStateChangedListener
+ )
+ }
secureSettings.unregisterContentObserver(settingsObserver)
}
}
@@ -89,6 +102,8 @@
dirtyListeners.forEach(Runnable::run)
}
+ private val onSensitiveStateChangedListener = Runnable { dirtyListeners.forEach(Runnable::run) }
+
private val settingsObserver = object : ContentObserver(handler) {
override fun onChange(selfChange: Boolean) {
updateSnoozeEnabled()
@@ -122,7 +137,10 @@
isConversation = entry.ranking.isConversation,
isSnoozeEnabled = isSnoozeSettingsEnabled && !entry.isCanceled,
isMinimized = isEntryMinimized(entry),
- needsRedaction = lockscreenUserManager.needsRedaction(entry),
+ needsRedaction =
+ lockscreenUserManager.needsRedaction(entry) ||
+ (screenshareNotificationHiding() &&
+ sensitiveNotifProtectionController.shouldProtectNotification(entry)),
isChildInGroup = entry.sbn.isAppOrSystemGroupChild,
isGroupSummary = entry.sbn.isAppOrSystemGroupSummary,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index c5b55c7..6400ff6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -254,11 +254,9 @@
params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
params.setUseLowPriority(isLowPriority);
- // If screenshareNotificationHiding is enabled, both public and private views should be
- // inflated to avoid any latency associated with reinflating all notification views when
- // screen share starts and stops
if (screenshareNotificationHiding()
- || mNotificationLockscreenUserManager.needsRedaction(entry)) {
+ ? inflaterParams.getNeedsRedaction()
+ : mNotificationLockscreenUserManager.needsRedaction(entry)) {
params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC);
} else {
params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
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/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index ab2f664..ac44b3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -262,9 +262,6 @@
return mStackHeight;
}
- /** Tracks the state from HeadsUpManager#hasNotifications() */
- private boolean mHasHeadsUpEntries;
-
@Inject
public AmbientState(
@NonNull Context context,
@@ -547,10 +544,6 @@
mPanelTracking = panelTracking;
}
- public boolean hasPulsingNotifications() {
- return mPulsing && mHasHeadsUpEntries;
- }
-
public void setPulsing(boolean hasPulsing) {
mPulsing = hasPulsing;
}
@@ -701,10 +694,6 @@
return mAppearFraction;
}
- public void setHasHeadsUpEntries(boolean hasHeadsUpEntries) {
- mHasHeadsUpEntries = hasHeadsUpEntries;
- }
-
public void setStackTopMargin(int stackTopMargin) {
mStackTopMargin = stackTopMargin;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index b47b18d..b205071 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -928,12 +928,11 @@
}
void updateSidePadding(int viewWidth) {
- final boolean portrait =
- getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
+ final int orientation = getResources().getConfiguration().orientation;
mLastUpdateSidePaddingDumpString = "viewWidth=" + viewWidth
+ " skinnyNotifsInLandscape=" + mSkinnyNotifsInLandscape
- + " portrait=" + portrait;
+ + " orientation=" + orientation;
if (DEBUG_UPDATE_SIDE_PADDING) {
Log.v(TAG, "updateSidePadding: " + mLastUpdateSidePaddingDumpString);
@@ -945,7 +944,7 @@
}
// Portrait is easy, just use the dimen for paddings
- if (portrait) {
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
mSidePaddings = mMinimumPaddings;
return;
}
@@ -5379,13 +5378,6 @@
mTopHeadsUpRow = topHeadsUpRow;
}
- /**
- * @param numHeadsUp the number of active alerting notifications.
- */
- public void setNumHeadsUp(long numHeadsUp) {
- mAmbientState.setHasHeadsUpEntries(numHeadsUp > 0);
- }
-
public boolean getIsExpanded() {
return mIsExpanded;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 3bdd0e9..382de3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -689,9 +689,7 @@
@Override
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
- long numEntries = mHeadsUpManager.getAllEntries().count();
NotificationEntry topEntry = mHeadsUpManager.getTopEntry();
- mView.setNumHeadsUp(numEntries);
mView.setTopHeadsUpRow(topEntry != null ? topEntry.getRow() : null);
generateHeadsUpAnimation(entry, isHeadsUp);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 48d3157..e2e13a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -301,8 +301,7 @@
if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key.getKeyCode()) {
mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_UP);
- mShadeViewController.collapse(
- false /* delayed */, 1.0f /* speedUpFactor */);
+ mShadeController.animateCollapseShade();
} else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key.getKeyCode()) {
mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_DOWN);
if (mShadeViewController.isFullyCollapsed()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index db15144..d32e88b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -2790,6 +2790,9 @@
|| mKeyguardStateController.isKeyguardGoingAway()
|| mKeyguardViewMediator.requestedShowSurfaceBehindKeyguard()
|| mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
+ boolean dreaming =
+ mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()
+ && !unlocking;
mScrimController.setExpansionAffectsAlpha(!unlocking);
@@ -2834,13 +2837,16 @@
// this as otherwise it can remain pending and leave keyguard in a weird state.
mUnlockScrimCallback.onCancelled();
} else if (mIsIdleOnCommunal) {
- mScrimController.transitionTo(ScrimState.GLANCEABLE_HUB);
+ if (dreaming) {
+ mScrimController.transitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM);
+ } else {
+ mScrimController.transitionTo(ScrimState.GLANCEABLE_HUB);
+ }
} else if (mKeyguardStateController.isShowing()
&& !mKeyguardStateController.isOccluded()
&& !unlocking) {
mScrimController.transitionTo(ScrimState.KEYGUARD);
- } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()
- && !unlocking) {
+ } else if (dreaming) {
mScrimController.transitionTo(ScrimState.DREAMING);
} else {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
@@ -3043,8 +3049,7 @@
if (userSetup != mUserSetup) {
mUserSetup = userSetup;
if (!mUserSetup && mState == StatusBarState.SHADE) {
- mShadeSurface.collapse(true /* animate */, false /* delayed */,
- 1.0f /* speedUpFactor */);
+ mShadeController.animateCollapseShade();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 088f894..02293a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -536,6 +536,16 @@
mAnimateChange = state.getAnimateChange();
mAnimationDuration = state.getAnimationDuration();
+ if (mState == ScrimState.GLANCEABLE_HUB_OVER_DREAM) {
+ // When the device is docked while on GLANCEABLE_HUB, the dream starts underneath the
+ // hub and the ScrimState transitions to GLANCEABLE_HUB_OVER_DREAM. To prevent the
+ // scrims from flickering in during this transition, we set the panel expansion
+ // fraction, which is 1 when idle on GLANCEABLE_HUB, to 0. This only occurs when the hub
+ // is open because the hub lives in the same window as the shade, which is not visible
+ // when transitioning from KEYGUARD to DREAMING.
+ mPanelExpansionFraction = 0f;
+ }
+
applyState();
mScrimInFront.setBlendWithMainColor(state.shouldBlendWithMainColor());
@@ -738,6 +748,7 @@
boolean relevantState = (mState == ScrimState.UNLOCKED
|| mState == ScrimState.KEYGUARD
|| mState == ScrimState.DREAMING
+ || mState == ScrimState.GLANCEABLE_HUB_OVER_DREAM
|| mState == ScrimState.SHADE_LOCKED
|| mState == ScrimState.PULSING);
if (!(relevantState && mExpansionAffectsAlpha) || mAnimatingPanelExpansionOnUnlock) {
@@ -844,7 +855,8 @@
return;
}
mBouncerHiddenFraction = bouncerHiddenAmount;
- if (mState == ScrimState.DREAMING || mState == ScrimState.GLANCEABLE_HUB) {
+ if (mState == ScrimState.DREAMING || mState == ScrimState.GLANCEABLE_HUB
+ || mState == ScrimState.GLANCEABLE_HUB_OVER_DREAM) {
// The dreaming and glanceable hub states requires this for the scrim calculation, so we
// should only trigger an update in those states.
applyAndDispatchState();
@@ -926,7 +938,8 @@
return;
}
- if (mState == ScrimState.UNLOCKED || mState == ScrimState.DREAMING) {
+ if (mState == ScrimState.UNLOCKED || mState == ScrimState.DREAMING
+ || mState == ScrimState.GLANCEABLE_HUB_OVER_DREAM) {
final boolean occluding =
mOccludeAnimationPlaying || mState.mLaunchingAffordanceWithPreview;
// Darken scrim as it's pulled down while unlocked. If we're unlocked but playing the
@@ -954,8 +967,9 @@
mInFrontAlpha = 0;
}
- if (mState == ScrimState.DREAMING
+ if ((mState == ScrimState.DREAMING || mState == ScrimState.GLANCEABLE_HUB_OVER_DREAM)
&& mBouncerHiddenFraction != KeyguardBouncerConstants.EXPANSION_HIDDEN) {
+ // Bouncer is opening over dream or glanceable hub over dream.
final float interpolatedFraction =
BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(
mBouncerHiddenFraction);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index f2a649b..d4960d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -299,9 +299,9 @@
},
/**
- * Device is locked or on dream and user has swiped from the right edge to enter the glanceable
- * hub UI. From this state, the user can swipe from the left edge to go back to the lock screen
- * or dream, as well as swipe down for the notifications and up for the bouncer.
+ * Device is on the lockscreen and user has swiped from the right edge to enter the glanceable
+ * hub UI. From this state, the user can swipe from the left edge to go back to the lock screen,
+ * as well as swipe down for the notifications and up for the bouncer.
*/
GLANCEABLE_HUB {
@Override
@@ -310,6 +310,25 @@
mBehindAlpha = 0;
mNotifAlpha = 0;
mFrontAlpha = 0;
+
+ mFrontTint = Color.TRANSPARENT;
+ mBehindTint = mBackgroundColor;
+ mNotifTint = mClipQsScrim ? mBackgroundColor : Color.TRANSPARENT;
+ }
+ },
+
+ /**
+ * Device is dreaming and user has swiped from the right edge to enter the glanceable hub UI.
+ * From this state, the user can swipe from the left edge to go back to the dream, as well as
+ * swipe down for the notifications and up for the bouncer.
+ *
+ * This is a separate state from {@link #GLANCEABLE_HUB} because the scrims behave differently
+ * when the dream is running.
+ */
+ GLANCEABLE_HUB_OVER_DREAM {
+ @Override
+ public void prepare(ScrimState previousState) {
+ GLANCEABLE_HUB.prepare(previousState);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 223eaf7..88374d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -32,6 +32,7 @@
import com.android.systemui.statusbar.notification.stack.AnimationProperties
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.Flags.lightRevealMigration
import com.android.app.tracing.namedRunnable
import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
@@ -45,7 +46,7 @@
/**
* Duration for the light reveal portion of the animation.
*/
-private const val LIGHT_REVEAL_ANIMATION_DURATION = 750L
+private const val LIGHT_REVEAL_ANIMATION_DURATION = 500L
/**
* Controller for the unlocked screen off animation, which runs when the device is going to sleep
@@ -66,7 +67,7 @@
private val notifShadeWindowControllerLazy: dagger.Lazy<NotificationShadeWindowController>,
private val interactionJankMonitor: InteractionJankMonitor,
private val powerManager: PowerManager,
- private val handler: Handler = Handler(),
+ private val handler: Handler = Handler()
) : WakefulnessLifecycle.Observer, ScreenOffAnimation {
private lateinit var centralSurfaces: CentralSurfaces
private lateinit var shadeViewController: ShadeViewController
@@ -95,6 +96,7 @@
duration = LIGHT_REVEAL_ANIMATION_DURATION
interpolator = Interpolators.LINEAR
addUpdateListener {
+ if (lightRevealMigration()) return@addUpdateListener
if (lightRevealScrim.revealEffect !is CircleReveal) {
lightRevealScrim.revealAmount = it.animatedValue as Float
}
@@ -107,6 +109,7 @@
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationCancel(animation: Animator) {
+ if (lightRevealMigration()) return
if (lightRevealScrim.revealEffect !is CircleReveal) {
lightRevealScrim.revealAmount = 1f
}
@@ -371,7 +374,7 @@
* AOD UI.
*/
override fun isAnimationPlaying(): Boolean {
- return lightRevealAnimationPlaying || aodUiAnimationPlaying
+ return isScreenOffLightRevealAnimationPlaying() || aodUiAnimationPlaying
}
override fun shouldAnimateInKeyguard(): Boolean =
@@ -395,6 +398,9 @@
/**
* Whether the light reveal animation is playing. The second part of the screen off animation,
* where AOD animates in, might still be playing if this returns false.
+ *
+ * Note: This only refers to the specific light reveal animation that is playing during lock
+ * therefore LightRevealScrimInteractor.isAnimating is not the desired response.
*/
fun isScreenOffLightRevealAnimationPlaying(): Boolean {
return lightRevealAnimationPlaying
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 324d723..7674fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -361,12 +361,14 @@
public void enterDesktop(int displayId) {
desktopMode.enterDesktop(displayId);
}
- });
- mCommandQueue.addCallback(new CommandQueue.Callbacks() {
@Override
public void moveFocusedTaskToFullscreen(int displayId) {
desktopMode.moveFocusedTaskToFullscreen(displayId);
}
+ @Override
+ public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {
+ desktopMode.moveFocusedTaskToStageSplit(displayId, leftOrTop);
+ }
});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
index 3862b0f..de795a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
@@ -61,6 +61,7 @@
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.ArraySet;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
@@ -71,6 +72,7 @@
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.test.filters.SmallTest;
+import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.Flags;
@@ -220,6 +222,24 @@
}
@Test
+ @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
+ public void triggerDismissMenuAction_callsA11yManagerEnableShortcutsForTargets() {
+ final List<String> stubShortcutTargets = new ArrayList<>();
+ stubShortcutTargets.add(TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString());
+ when(mStubAccessibilityManager.getAccessibilityShortcutTargets(
+ AccessibilityManager.ACCESSIBILITY_BUTTON)).thenReturn(stubShortcutTargets);
+
+ mMenuViewLayer.mDismissMenuAction.run();
+
+ verify(mStubAccessibilityManager).enableShortcutsForTargets(
+ /* enable= */ false,
+ ShortcutConstants.UserShortcutType.SOFTWARE,
+ new ArraySet<>(stubShortcutTargets),
+ mSecureSettings.getRealUserHandle(UserHandle.USER_CURRENT));
+ }
+
+ @Test
+ @DisableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
public void triggerDismissMenuAction_matchA11yButtonTargetsResult() {
mMenuViewLayer.mDismissMenuAction.run();
verify(mSecureSettings).putStringForUser(
@@ -228,6 +248,7 @@
}
@Test
+ @DisableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
public void triggerDismissMenuAction_matchEnabledA11yServicesResult() {
setupEnabledAccessibilityServiceList();
@@ -239,6 +260,7 @@
}
@Test
+ @DisableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
public void triggerDismissMenuAction_hasHardwareKeyShortcut_keepEnabledStatus() {
setupEnabledAccessibilityServiceList();
final List<String> stubShortcutTargets = new ArrayList<>();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
index 54d6b53..67ca9a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
@@ -20,6 +20,7 @@
import com.android.systemui.SysUITestComponent
import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FakeFeatureFlagsClassicModule
import com.android.systemui.flags.Flags
@@ -45,6 +46,7 @@
[
SysUITestModule::class,
UserDomainLayerModule::class,
+ BiometricsDomainLayerModule::class,
]
)
interface TestComponent : SysUITestComponent<AuthDialogPanelInteractionDetector> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FingerprintRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FingerprintRepositoryImplTest.kt
index dc438d7..7808c41 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FingerprintRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FingerprintRepositoryImplTest.kt
@@ -84,8 +84,8 @@
val sensorType by collectLastValue(repository.sensorType)
val sensorLocations by collectLastValue(repository.sensorLocations)
- // Assert default properties.
- assertThat(sensorId).isEqualTo(-1)
+ // Assert non-initialized properties.
+ assertThat(sensorId).isEqualTo(-2)
assertThat(strength).isEqualTo(SensorStrength.CONVENIENCE)
assertThat(sensorType).isEqualTo(FingerprintSensorType.UNKNOWN)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModelTest.kt
index fa17672..5caa146 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModelTest.kt
@@ -21,6 +21,7 @@
import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
import com.android.systemui.TestMocksModule
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
import com.android.systemui.collectLastValue
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FakeFeatureFlagsClassicModule
@@ -65,6 +66,7 @@
[
SysUITestModule::class,
UserDomainLayerModule::class,
+ BiometricsDomainLayerModule::class,
]
)
interface TestComponent : SysUITestComponent<DefaultUdfpsTouchOverlayViewModel> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorTest.kt
index e8eda80..d5839b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorTest.kt
@@ -21,9 +21,15 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.data.repository.fakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.domain.interactor.fingerprintPropertyInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
+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.runTest
@@ -35,6 +41,8 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class DeviceEntryUdfpsInteractorTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
private lateinit var fingerprintAuthRepository: FakeDeviceEntryFingerprintAuthRepository
private lateinit var biometricsRepository: FakeBiometricSettingsRepository
@@ -43,77 +51,85 @@
@Before
fun setUp() {
- fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
- fingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
- biometricsRepository = FakeBiometricSettingsRepository()
+ fingerprintPropertyRepository = kosmos.fakeFingerprintPropertyRepository
+ fingerprintAuthRepository = kosmos.fakeDeviceEntryFingerprintAuthRepository
+ biometricsRepository = kosmos.fakeBiometricSettingsRepository
underTest =
DeviceEntryUdfpsInteractor(
- fingerprintPropertyRepository = fingerprintPropertyRepository,
+ fingerprintPropertyInteractor = kosmos.fingerprintPropertyInteractor,
fingerprintAuthRepository = fingerprintAuthRepository,
biometricSettingsRepository = biometricsRepository,
)
}
@Test
- fun udfpsSupported_rearFp_false() = runTest {
- val isUdfpsSupported by collectLastValue(underTest.isUdfpsSupported)
- fingerprintPropertyRepository.supportsRearFps()
- assertThat(isUdfpsSupported).isFalse()
- }
+ fun udfpsSupported_rearFp_false() =
+ testScope.runTest {
+ val isUdfpsSupported by collectLastValue(underTest.isUdfpsSupported)
+ fingerprintPropertyRepository.supportsRearFps()
+ assertThat(isUdfpsSupported).isFalse()
+ }
@Test
- fun udfpsSupoprted() = runTest {
- val isUdfpsSupported by collectLastValue(underTest.isUdfpsSupported)
- fingerprintPropertyRepository.supportsUdfps()
- assertThat(isUdfpsSupported).isTrue()
- }
+ fun udfpsSupoprted() =
+ testScope.runTest {
+ val isUdfpsSupported by collectLastValue(underTest.isUdfpsSupported)
+ fingerprintPropertyRepository.supportsUdfps()
+ assertThat(isUdfpsSupported).isTrue()
+ }
@Test
- fun udfpsEnrolledAndEnabled() = runTest {
- val isUdfpsEnrolledAndEnabled by collectLastValue(underTest.isUdfpsEnrolledAndEnabled)
- fingerprintPropertyRepository.supportsUdfps()
- biometricsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
- assertThat(isUdfpsEnrolledAndEnabled).isTrue()
- }
+ fun udfpsEnrolledAndEnabled() =
+ testScope.runTest {
+ val isUdfpsEnrolledAndEnabled by collectLastValue(underTest.isUdfpsEnrolledAndEnabled)
+ fingerprintPropertyRepository.supportsUdfps()
+ biometricsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+ assertThat(isUdfpsEnrolledAndEnabled).isTrue()
+ }
@Test
- fun udfpsEnrolledAndEnabled_rearFp_false() = runTest {
- val isUdfpsEnrolledAndEnabled by collectLastValue(underTest.isUdfpsEnrolledAndEnabled)
- fingerprintPropertyRepository.supportsRearFps()
- biometricsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
- assertThat(isUdfpsEnrolledAndEnabled).isFalse()
- }
+ fun udfpsEnrolledAndEnabled_rearFp_false() =
+ testScope.runTest {
+ val isUdfpsEnrolledAndEnabled by collectLastValue(underTest.isUdfpsEnrolledAndEnabled)
+ fingerprintPropertyRepository.supportsRearFps()
+ biometricsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+ assertThat(isUdfpsEnrolledAndEnabled).isFalse()
+ }
@Test
- fun udfpsEnrolledAndEnabled_notEnrolledOrEnabled_false() = runTest {
- val isUdfpsEnrolledAndEnabled by collectLastValue(underTest.isUdfpsEnrolledAndEnabled)
- fingerprintPropertyRepository.supportsUdfps()
- biometricsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
- assertThat(isUdfpsEnrolledAndEnabled).isFalse()
- }
+ fun udfpsEnrolledAndEnabled_notEnrolledOrEnabled_false() =
+ testScope.runTest {
+ val isUdfpsEnrolledAndEnabled by collectLastValue(underTest.isUdfpsEnrolledAndEnabled)
+ fingerprintPropertyRepository.supportsUdfps()
+ biometricsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
+ assertThat(isUdfpsEnrolledAndEnabled).isFalse()
+ }
@Test
- fun isListeningForUdfps() = runTest {
- val isListeningForUdfps by collectLastValue(underTest.isListeningForUdfps)
- fingerprintPropertyRepository.supportsUdfps()
- fingerprintAuthRepository.setIsRunning(true)
- assertThat(isListeningForUdfps).isTrue()
- }
+ fun isListeningForUdfps() =
+ testScope.runTest {
+ val isListeningForUdfps by collectLastValue(underTest.isListeningForUdfps)
+ fingerprintPropertyRepository.supportsUdfps()
+ fingerprintAuthRepository.setIsRunning(true)
+ assertThat(isListeningForUdfps).isTrue()
+ }
@Test
- fun isListeningForUdfps_rearFp_false() = runTest {
- val isListeningForUdfps by collectLastValue(underTest.isListeningForUdfps)
- fingerprintPropertyRepository.supportsRearFps()
- fingerprintAuthRepository.setIsRunning(true)
- assertThat(isListeningForUdfps).isFalse()
- }
+ fun isListeningForUdfps_rearFp_false() =
+ testScope.runTest {
+ val isListeningForUdfps by collectLastValue(underTest.isListeningForUdfps)
+ fingerprintPropertyRepository.supportsRearFps()
+ fingerprintAuthRepository.setIsRunning(true)
+ assertThat(isListeningForUdfps).isFalse()
+ }
@Test
- fun isListeningForUdfps_notRunning_false() = runTest {
- val isListeningForUdfps by collectLastValue(underTest.isListeningForUdfps)
- fingerprintPropertyRepository.supportsUdfps()
- fingerprintAuthRepository.setIsRunning(false)
- assertThat(isListeningForUdfps).isFalse()
- }
+ fun isListeningForUdfps_notRunning_false() =
+ testScope.runTest {
+ val isListeningForUdfps by collectLastValue(underTest.isListeningForUdfps)
+ fingerprintPropertyRepository.supportsUdfps()
+ fingerprintAuthRepository.setIsRunning(false)
+ assertThat(isListeningForUdfps).isFalse()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt
index 37836a5..bcaad01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt
@@ -62,7 +62,6 @@
whenever(defaultLockscreenBlueprint.id).thenReturn(DEFAULT)
underTest =
KeyguardBlueprintRepository(
- configurationRepository,
setOf(defaultLockscreenBlueprint),
fakeExecutorHandler,
threadAssert,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
index b0d8de3..170d348 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
@@ -21,95 +21,80 @@
import androidx.test.filters.SmallTest
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository
+import com.android.systemui.biometrics.data.repository.fakeFingerprintPropertyRepository
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID
import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint
import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint
-import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition
-import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config
-import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type
+import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.clocks.ClockConfig
import com.android.systemui.plugins.clocks.ClockController
-import com.android.systemui.statusbar.policy.SplitShadeStateController
-import com.android.systemui.util.mockito.any
+import com.android.systemui.res.R
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+@ExperimentalCoroutinesApi
@SmallTest
@RunWith(AndroidJUnit4::class)
class KeyguardBlueprintInteractorTest : SysuiTestCase() {
- private val configurationFlow = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
- private lateinit var underTest: KeyguardBlueprintInteractor
- private lateinit var testScope: TestScope
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val underTest by lazy { kosmos.keyguardBlueprintInteractor }
+ private val clockRepository by lazy { kosmos.fakeKeyguardClockRepository }
+ private val configurationRepository by lazy { kosmos.fakeConfigurationRepository }
+ private val fingerprintPropertyRepository by lazy { kosmos.fakeFingerprintPropertyRepository }
- val refreshTransition: MutableSharedFlow<IntraBlueprintTransition.Config> =
- MutableSharedFlow(extraBufferCapacity = 1)
-
- @Mock private lateinit var splitShadeStateController: SplitShadeStateController
- @Mock private lateinit var keyguardBlueprintRepository: KeyguardBlueprintRepository
- @Mock private lateinit var clockInteractor: KeyguardClockInteractor
@Mock private lateinit var clockController: ClockController
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- testScope = TestScope(StandardTestDispatcher())
- whenever(keyguardBlueprintRepository.configurationChange).thenReturn(configurationFlow)
- whenever(keyguardBlueprintRepository.refreshTransition).thenReturn(refreshTransition)
- whenever(clockInteractor.currentClock).thenReturn(MutableStateFlow(clockController))
- clockInteractor.currentClock
-
- underTest =
- KeyguardBlueprintInteractor(
- keyguardBlueprintRepository,
- testScope.backgroundScope,
- mContext,
- splitShadeStateController,
- clockInteractor,
- )
}
@Test
fun testAppliesDefaultBlueprint() {
testScope.runTest {
- whenever(splitShadeStateController.shouldUseSplitNotificationShade(any()))
- .thenReturn(false)
-
- reset(keyguardBlueprintRepository)
- configurationFlow.tryEmit(Unit)
+ val blueprint by collectLastValue(underTest.blueprint)
+ overrideResource(R.bool.config_use_split_notification_shade, false)
+ configurationRepository.onConfigurationChange()
runCurrent()
- verify(keyguardBlueprintRepository)
- .applyBlueprint(DefaultKeyguardBlueprint.Companion.DEFAULT)
+ assertThat(blueprint?.id).isEqualTo(DefaultKeyguardBlueprint.Companion.DEFAULT)
}
}
@Test
fun testAppliesSplitShadeBlueprint() {
testScope.runTest {
- whenever(splitShadeStateController.shouldUseSplitNotificationShade(any()))
- .thenReturn(true)
-
- reset(keyguardBlueprintRepository)
- configurationFlow.tryEmit(Unit)
+ val blueprint by collectLastValue(underTest.blueprint)
+ overrideResource(R.bool.config_use_split_notification_shade, true)
+ configurationRepository.onConfigurationChange()
runCurrent()
- verify(keyguardBlueprintRepository)
- .applyBlueprint(SplitShadeKeyguardBlueprint.Companion.ID)
+ assertThat(blueprint?.id).isEqualTo(SplitShadeKeyguardBlueprint.Companion.ID)
+ }
+ }
+
+ @Test
+ fun fingerprintPropertyInitialized_updatesBlueprint() {
+ testScope.runTest {
+ val blueprint by collectLastValue(underTest.blueprint)
+ overrideResource(R.bool.config_use_split_notification_shade, true)
+ fingerprintPropertyRepository.supportsUdfps() // initialize properties
+ runCurrent()
+ assertThat(blueprint?.id).isEqualTo(SplitShadeKeyguardBlueprint.Companion.ID)
}
}
@@ -117,6 +102,7 @@
fun composeLockscreenOff_DoesAppliesSplitShadeWeatherClockBlueprint() {
testScope.runTest {
mSetFlagsRule.disableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
+ val blueprint by collectLastValue(underTest.blueprint)
whenever(clockController.config)
.thenReturn(
ClockConfig(
@@ -125,15 +111,12 @@
description = "clock",
)
)
- whenever(splitShadeStateController.shouldUseSplitNotificationShade(any()))
- .thenReturn(true)
-
- reset(keyguardBlueprintRepository)
- configurationFlow.tryEmit(Unit)
+ clockRepository.setCurrentClock(clockController)
+ overrideResource(R.bool.config_use_split_notification_shade, true)
+ configurationRepository.onConfigurationChange()
runCurrent()
- verify(keyguardBlueprintRepository, never())
- .applyBlueprint(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID)
+ assertThat(blueprint?.id).isNotEqualTo(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID)
}
}
@@ -141,6 +124,7 @@
fun testDoesAppliesSplitShadeWeatherClockBlueprint() {
testScope.runTest {
mSetFlagsRule.enableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
+ val blueprint by collectLastValue(underTest.blueprint)
whenever(clockController.config)
.thenReturn(
ClockConfig(
@@ -149,15 +133,12 @@
description = "clock",
)
)
- whenever(splitShadeStateController.shouldUseSplitNotificationShade(any()))
- .thenReturn(true)
-
- reset(keyguardBlueprintRepository)
- configurationFlow.tryEmit(Unit)
+ clockRepository.setCurrentClock(clockController)
+ overrideResource(R.bool.config_use_split_notification_shade, true)
+ configurationRepository.onConfigurationChange()
runCurrent()
- verify(keyguardBlueprintRepository)
- .applyBlueprint(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID)
+ assertThat(blueprint?.id).isEqualTo(SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID)
}
}
@@ -165,6 +146,7 @@
fun testAppliesWeatherClockBlueprint() {
testScope.runTest {
mSetFlagsRule.enableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN)
+ val blueprint by collectLastValue(underTest.blueprint)
whenever(clockController.config)
.thenReturn(
ClockConfig(
@@ -173,33 +155,12 @@
description = "clock",
)
)
- whenever(splitShadeStateController.shouldUseSplitNotificationShade(any()))
- .thenReturn(false)
-
- reset(keyguardBlueprintRepository)
- configurationFlow.tryEmit(Unit)
+ clockRepository.setCurrentClock(clockController)
+ overrideResource(R.bool.config_use_split_notification_shade, false)
+ configurationRepository.onConfigurationChange()
runCurrent()
- verify(keyguardBlueprintRepository).applyBlueprint(WEATHER_CLOCK_BLUEPRINT_ID)
+ assertThat(blueprint?.id).isEqualTo(WEATHER_CLOCK_BLUEPRINT_ID)
}
}
-
- @Test
- fun testRefreshBlueprint() {
- underTest.refreshBlueprint()
- verify(keyguardBlueprintRepository).refreshBlueprint()
- }
-
- @Test
- fun testTransitionToBlueprint() {
- underTest.transitionToBlueprint("abc")
- verify(keyguardBlueprintRepository).applyBlueprint("abc")
- }
-
- @Test
- fun testRefreshBlueprintWithTransition() {
- underTest.refreshBlueprint(Type.DefaultTransition)
- verify(keyguardBlueprintRepository)
- .refreshBlueprint(Config(Type.DefaultTransition, true, true))
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
index 699284e..09c56b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
@@ -22,7 +22,6 @@
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.LockIconViewController
import com.android.systemui.Flags as AConfigFlags
import com.android.systemui.SysuiTestCase
@@ -37,8 +36,10 @@
import com.android.systemui.res.R
import com.android.systemui.shade.NotificationPanelView
import com.android.systemui.statusbar.VibratorHelper
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import org.junit.Before
import org.junit.Test
@@ -53,13 +54,13 @@
@RunWith(JUnit4::class)
@SmallTest
class DefaultDeviceEntrySectionTest : SysuiTestCase() {
- @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var authController: AuthController
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var windowManager: WindowManager
@Mock private lateinit var notificationPanelView: NotificationPanelView
private lateinit var featureFlags: FakeFeatureFlags
@Mock private lateinit var lockIconViewController: LockIconViewController
@Mock private lateinit var falsingManager: FalsingManager
+ @Mock private lateinit var deviceEntryIconViewModel: DeviceEntryIconViewModel
private lateinit var underTest: DefaultDeviceEntrySection
@Before
@@ -73,14 +74,13 @@
underTest =
DefaultDeviceEntrySection(
TestScope().backgroundScope,
- keyguardUpdateMonitor,
authController,
windowManager,
context,
notificationPanelView,
featureFlags,
{ lockIconViewController },
- { mock(DeviceEntryIconViewModel::class.java) },
+ { deviceEntryIconViewModel },
{ mock(DeviceEntryForegroundViewModel::class.java) },
{ mock(DeviceEntryBackgroundViewModel::class.java) },
{ falsingManager },
@@ -129,6 +129,7 @@
@Test
fun applyConstraints_udfps_refactor_on() {
mSetFlagsRule.enableFlags(AConfigFlags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
+ whenever(deviceEntryIconViewModel.isUdfpsSupported).thenReturn(MutableStateFlow(false))
val cs = ConstraintSet()
underTest.applyConstraints(cs)
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 cdff4d1..43fcdf3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -38,6 +38,7 @@
import static org.mockito.Mockito.when;
import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
import android.annotation.IdRes;
import android.content.ContentResolver;
@@ -213,7 +214,6 @@
import java.util.Optional;
import kotlinx.coroutines.CoroutineDispatcher;
-import kotlinx.coroutines.flow.StateFlowKt;
import kotlinx.coroutines.test.TestScope;
public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
@@ -409,10 +409,10 @@
new ShadeAnimationRepository(), mShadeRepository);
mPowerInteractor = keyguardInteractorDeps.getPowerInteractor();
when(mKeyguardTransitionInteractor.isInTransitionToStateWhere(any())).thenReturn(
- StateFlowKt.MutableStateFlow(false));
+ MutableStateFlow(false));
DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
mock(DeviceEntryUdfpsInteractor.class);
- when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(emptyFlow());
+ when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(MutableStateFlow(false));
mShadeInteractor = new ShadeInteractorImpl(
mTestScope.getBackgroundScope(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 3808d30..c31c625 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -36,7 +36,7 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
import android.app.IActivityManager;
import android.content.pm.ActivityInfo;
@@ -205,7 +205,7 @@
DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
mock(DeviceEntryUdfpsInteractor.class);
- when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(emptyFlow());
+ when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(MutableStateFlow(false));
mShadeInteractor = new ShadeInteractorImpl(
mTestScope.getBackgroundScope(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
index 4809a47..a077164 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
@@ -22,7 +22,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
import android.content.res.Resources;
@@ -234,7 +234,8 @@
DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
mock(DeviceEntryUdfpsInteractor.class);
- when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(emptyFlow());
+ when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(
+ MutableStateFlow(false));
mShadeInteractor = new ShadeInteractorImpl(
mTestScope.getBackgroundScope(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
index 2f957b0..0a9541a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
@@ -18,7 +18,7 @@
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testScope
-import com.android.systemui.scene.domain.interactor.PanelExpansionInteractor
+import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.FakeSceneDataSource
@@ -27,8 +27,8 @@
import com.android.systemui.shade.STATE_OPENING
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionStateManager
+import com.android.systemui.shade.domain.interactor.panelExpansionInteractor
import com.android.systemui.statusbar.SysuiStatusBarStateController
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.panelExpansionInteractor
import com.android.systemui.statusbar.policy.FakeConfigurationController
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
import com.android.systemui.testKosmos
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 86116a0..d35c7dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -9,6 +9,7 @@
import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
import com.android.systemui.TestMocksModule
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.dagger.SysUISingleton
@@ -35,6 +36,8 @@
import com.android.systemui.statusbar.policy.FakeConfigurationController
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
import com.android.systemui.user.domain.UserDomainLayerModule
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
import dagger.BindsInstance
import dagger.Component
@@ -55,6 +58,7 @@
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyLong
import org.mockito.ArgumentMatchers.eq
+import org.mockito.ArgumentMatchers.isNull
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.clearInvocations
@@ -310,6 +314,17 @@
}
@Test
+ fun testGoToLockedShadeCancelDoesntLeaveShadeOpenOnKeyguardHide() {
+ whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
+ whenever(lockScreenUserManager.isLockscreenPublicMode(any())).thenReturn(true)
+ transitionController.goToLockedShade(null)
+ val captor = argumentCaptor<Runnable>()
+ verify(centralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(isNull(), captor.capture())
+ captor.value.run()
+ verify(statusbarStateController).setLeaveOpenOnKeyguardHide(false)
+ }
+
+ @Test
fun testDragDownAmountDoesntCallOutInLockedDownShade() {
whenever(nsslController.isInLockedDownShade).thenReturn(true)
transitionController.dragDownAmount = 10f
@@ -611,6 +626,7 @@
[
SysUITestModule::class,
UserDomainLayerModule::class,
+ BiometricsDomainLayerModule::class,
]
)
interface TestComponent {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
index dfbb6ea..103dcb7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
@@ -54,6 +54,7 @@
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.shade.domain.interactor.ShadeInteractor
@@ -69,7 +70,7 @@
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
@@ -85,9 +86,8 @@
import org.mockito.Mockito
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
-import com.android.systemui.scene.shared.model.Scenes
import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -155,7 +155,7 @@
{ kosmos.sceneInteractor },
)
- whenever(deviceEntryUdfpsInteractor.isUdfpsSupported).thenReturn(emptyFlow())
+ whenever(deviceEntryUdfpsInteractor.isUdfpsSupported).thenReturn(MutableStateFlow(false))
shadeInteractor =
ShadeInteractorImpl(
testScope.backgroundScope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
index 4519ba6..419b0fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
@@ -68,6 +68,7 @@
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.collection.render.NotifViewBarn;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
+import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController;
import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
@@ -107,6 +108,7 @@
@Mock private IStatusBarService mService;
@Mock private BindEventManagerImpl mBindEventManagerImpl;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
+ @Mock private SensitiveNotificationProtectionController mSensitiveNotifProtectionController;
@Mock private Handler mHandler;
@Mock private SecureSettings mSecureSettings;
@Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater();
@@ -128,6 +130,7 @@
mHandler,
mSecureSettings,
mLockscreenUserManager,
+ mSensitiveNotifProtectionController,
mSectionStyleProvider,
mUserTracker,
mGroupMembershipManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
index 457d2f0..018a571 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
@@ -94,6 +94,26 @@
}
@Test
+ @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
+ fun onSensitiveStateChanged_invokeInvalidationListener() {
+ coordinator.attach(pipeline)
+ val invalidator =
+ withArgCaptor<Invalidator> { verify(pipeline).addPreRenderInvalidator(capture()) }
+ val onSensitiveStateChangedListener =
+ withArgCaptor<Runnable> {
+ verify(sensitiveNotificationProtectionController)
+ .registerSensitiveStateListener(capture())
+ }
+
+ val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>()
+ invalidator.setInvalidationListener(invalidationListener)
+
+ onSensitiveStateChangedListener.run()
+
+ verify(invalidationListener).onPluggableInvalidated(eq(invalidator), any())
+ }
+
+ @Test
fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction() {
coordinator.attach(pipeline)
val onBeforeRenderListListener =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
index 115a0d3..34eeba0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
@@ -23,6 +23,7 @@
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
+import com.android.server.notification.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.NotificationLockscreenUserManager
@@ -33,6 +34,7 @@
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
+import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
@@ -57,6 +59,8 @@
@RunWithLooper
class NotifUiAdjustmentProviderTest : SysuiTestCase() {
private val lockscreenUserManager: NotificationLockscreenUserManager = mock()
+ private val sensitiveNotifProtectionController: SensitiveNotificationProtectionController =
+ mock()
private val sectionStyleProvider: SectionStyleProvider = mock()
private val handler: Handler = mock()
private val secureSettings: SecureSettings = mock()
@@ -77,6 +81,7 @@
handler,
secureSettings,
lockscreenUserManager,
+ sensitiveNotifProtectionController,
sectionStyleProvider,
userTracker,
groupMembershipManager,
@@ -108,6 +113,19 @@
}
@Test
+ @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
+ fun sensitiveNotifProtectionStateChangeWillNotifDirty() {
+ val dirtyListener = mock<Runnable>()
+ adjustmentProvider.addDirtyListener(dirtyListener)
+ val sensitiveStateChangedListener =
+ withArgCaptor<Runnable> {
+ verify(sensitiveNotifProtectionController).registerSensitiveStateListener(capture())
+ }
+ sensitiveStateChangedListener.run()
+ verify(dirtyListener).run()
+ }
+
+ @Test
fun additionalAddDoesNotRegisterAgain() {
clearInvocations(secureSettings)
adjustmentProvider.addDirtyListener(mock())
@@ -199,4 +217,38 @@
// Then: Need re-inflation
assertTrue(NotifUiAdjustment.needReinflate(oldAdjustment, newAdjustment))
}
+
+ @Test
+ @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
+ fun changeSensitiveNotifProtection_screenshareNotificationHidingEnabled_needReinflate() {
+ whenever(sensitiveNotifProtectionController.shouldProtectNotification(entry))
+ .thenReturn(false)
+ val oldAdjustment: NotifUiAdjustment = adjustmentProvider.calculateAdjustment(entry)
+ assertFalse(oldAdjustment.needsRedaction)
+
+ whenever(sensitiveNotifProtectionController.shouldProtectNotification(entry))
+ .thenReturn(true)
+ val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
+ assertTrue(newAdjustment.needsRedaction)
+
+ // Then: need re-inflation
+ assertTrue(NotifUiAdjustment.needReinflate(oldAdjustment, newAdjustment))
+ }
+
+ @Test
+ @DisableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
+ fun changeSensitiveNotifProtection_screenshareNotificationHidingDisabled_noNeedReinflate() {
+ whenever(sensitiveNotifProtectionController.shouldProtectNotification(entry))
+ .thenReturn(false)
+ val oldAdjustment = adjustmentProvider.calculateAdjustment(entry)
+ assertFalse(oldAdjustment.needsRedaction)
+
+ whenever(sensitiveNotifProtectionController.shouldProtectNotification(entry))
+ .thenReturn(true)
+ val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
+ assertFalse(newAdjustment.needsRedaction)
+
+ // Then: need no re-inflation
+ assertFalse(NotifUiAdjustment.needReinflate(oldAdjustment, newAdjustment))
+ }
}
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/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 84156ee1..c8c54dbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -859,6 +859,29 @@
}
@Test
+ public void testEnteringGlanceableHub_whenDreaming_updatesScrim() {
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mKeyguardStateController.isOccluded()).thenReturn(true);
+ when(mKeyguardUpdateMonitor.isDreaming()).thenReturn(true);
+
+ // Transition to the glanceable hub.
+ mCommunalRepository.setTransitionState(flowOf(new ObservableTransitionState.Idle(
+ CommunalScenes.Communal)));
+ mTestScope.getTestScheduler().runCurrent();
+
+ // ScrimState also transitions.
+ verify(mScrimController).transitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM);
+
+ // Transition away from the glanceable hub.
+ mCommunalRepository.setTransitionState(flowOf(new ObservableTransitionState.Idle(
+ CommunalScenes.Blank)));
+ mTestScope.getTestScheduler().runCurrent();
+
+ // ScrimState goes back to UNLOCKED.
+ verify(mScrimController).transitionTo(eq(ScrimState.DREAMING));
+ }
+
+ @Test
public void testShowKeyguardImplementation_setsState() {
when(mLockscreenUserManager.getCurrentProfiles()).thenReturn(new SparseArray<>());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 99c2dc7..cdbbc93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -794,6 +794,73 @@
}
@Test
+ public void transitionToHubOverDream() {
+ mScrimController.setRawPanelExpansionFraction(0f);
+ mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_HIDDEN);
+ mScrimController.transitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM);
+ finishAnimationsImmediately();
+
+ // All scrims transparent on the hub.
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, TRANSPARENT,
+ mScrimBehind, TRANSPARENT));
+ }
+
+ @Test
+ public void openBouncerOnHubOverDream() {
+ mScrimController.transitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM);
+
+ // Open the bouncer.
+ mScrimController.setRawPanelExpansionFraction(0f);
+ mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_VISIBLE);
+ finishAnimationsImmediately();
+
+ // Only behind widget is visible.
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, TRANSPARENT,
+ mScrimBehind, OPAQUE));
+
+ // Bouncer is closed.
+ mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_HIDDEN);
+ mScrimController.transitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM);
+ finishAnimationsImmediately();
+
+ // All scrims are transparent.
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, TRANSPARENT,
+ mScrimBehind, TRANSPARENT));
+ }
+
+ @Test
+ public void openShadeOnHubOverDream() {
+ mScrimController.transitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM);
+
+ // Open the shade.
+ mScrimController.transitionTo(SHADE_LOCKED);
+ mScrimController.setQsPosition(1f, 0);
+ mScrimController.setRawPanelExpansionFraction(1f);
+ finishAnimationsImmediately();
+
+ // Shade scrims are visible.
+ assertScrimAlpha(Map.of(
+ mNotificationsScrim, OPAQUE,
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
+
+ mScrimController.transitionTo(ScrimState.GLANCEABLE_HUB_OVER_DREAM);
+ finishAnimationsImmediately();
+
+ // All scrims are transparent.
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, TRANSPARENT,
+ mScrimBehind, TRANSPARENT));
+ }
+
+ @Test
public void onThemeChange_bouncerBehindTint_isUpdatedToSurfaceColor() {
assertEquals(BOUNCER.getBehindTint(), 0x112233);
mSurfaceColor = 0x223344;
@@ -1432,7 +1499,8 @@
ScrimState.UNINITIALIZED, ScrimState.KEYGUARD, BOUNCER,
ScrimState.DREAMING, ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR,
ScrimState.UNLOCKED, SHADE_LOCKED, ScrimState.AUTH_SCRIMMED,
- ScrimState.AUTH_SCRIMMED_SHADE, ScrimState.GLANCEABLE_HUB));
+ ScrimState.AUTH_SCRIMMED_SHADE, ScrimState.GLANCEABLE_HUB,
+ ScrimState.GLANCEABLE_HUB_OVER_DREAM));
for (ScrimState state : ScrimState.values()) {
if (!lowPowerModeStates.contains(state) && !regularStates.contains(state)) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
index 6a0375d..3bf54a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
@@ -31,6 +31,7 @@
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.StatusBarStateControllerImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.settings.GlobalSettings
import junit.framework.Assert.assertFalse
@@ -80,6 +81,8 @@
@Mock
private lateinit var handler: Handler
+ val kosmos = testKosmos()
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -87,14 +90,14 @@
context,
wakefulnessLifecycle,
statusBarStateController,
- dagger.Lazy<KeyguardViewMediator> { keyguardViewMediator },
+ { keyguardViewMediator },
keyguardStateController,
- dagger.Lazy<DozeParameters> { dozeParameters },
+ { dozeParameters },
globalSettings,
- dagger.Lazy<NotificationShadeWindowController> { notifShadeWindowController },
+ { notifShadeWindowController },
interactionJankMonitor,
powerManager,
- handler = handler,
+ handler = handler
)
controller.initialize(centralSurfaces, shadeViewController, lightRevealScrim)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
index e499a3c..e4a1c26 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
@@ -30,16 +30,22 @@
assumeTrue("Test should be launched on a foldable device",
foldedDeviceStates.isNotEmpty())
- val folded =
- DeviceState(foldedDeviceStates.maxOrNull()!! /* identifier */,
- "" /* name */,
- emptySet() /* properties */)
- val unfolded =
- DeviceState(folded.identifier + 1 /* identifier */,
- "" /* name */,
- emptySet() /* properties */)
+ val folded = getDeviceState(
+ identifier = foldedDeviceStates.maxOrNull()!!
+ )
+ val unfolded = getDeviceState(
+ identifier = folded.identifier + 1
+ )
return FoldableDeviceStates(folded = folded, unfolded = unfolded)
}
+
+ private fun getDeviceState(identifier: Int): DeviceState {
+ return DeviceState(
+ DeviceState.Configuration.Builder(
+ identifier, "" /* name */
+ ).build()
+ )
+ }
}
data class FoldableDeviceStates(val folded: DeviceState, val unfolded: DeviceState)
\ No newline at end of file
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 c0d3d27..19f31d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -50,7 +50,7 @@
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
import android.app.ActivityManager;
import android.app.IActivityManager;
@@ -452,7 +452,7 @@
DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
mock(DeviceEntryUdfpsInteractor.class);
- when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(emptyFlow());
+ when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(MutableStateFlow(false));
mShadeInteractor =
new ShadeInteractorImpl(
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt
index 1b951d9..9765d53 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt
@@ -19,12 +19,17 @@
import android.util.Size
import com.android.systemui.biometrics.shared.model.DisplayRotation
+import com.android.systemui.dagger.SysUISingleton
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
-class FakeDisplayStateRepository : DisplayStateRepository {
+@SysUISingleton
+class FakeDisplayStateRepository @Inject constructor() : DisplayStateRepository {
private val _isInRearDisplayMode = MutableStateFlow<Boolean>(false)
override val isInRearDisplayMode: StateFlow<Boolean> = _isInRearDisplayMode.asStateFlow()
@@ -51,3 +56,8 @@
_currentDisplaySize.value = size
}
}
+
+@Module
+interface FakeDisplayStateRepositoryModule {
+ @Binds fun bindFake(fake: FakeDisplayStateRepository): DisplayStateRepository
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFingerprintPropertyRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFingerprintPropertyRepository.kt
index 005cac4..bd30fb4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFingerprintPropertyRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFingerprintPropertyRepository.kt
@@ -28,6 +28,7 @@
@SysUISingleton
class FakeFingerprintPropertyRepository @Inject constructor() : FingerprintPropertyRepository {
+ override val propertiesInitialized: MutableStateFlow<Boolean> = MutableStateFlow(false)
private val _sensorId: MutableStateFlow<Int> = MutableStateFlow(-1)
override val sensorId = _sensorId.asStateFlow()
@@ -54,6 +55,7 @@
_strength.value = strength
_sensorType.value = sensorType
_sensorLocations.value = sensorLocations
+ propertiesInitialized.value = true
}
/** setProperties as if the device supports UDFPS_OPTICAL. */
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorKosmos.kt
index e262066..34a9c8a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorKosmos.kt
@@ -21,9 +21,11 @@
import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.applicationCoroutineScope
val Kosmos.fingerprintPropertyInteractor by Fixture {
FingerprintPropertyInteractor(
+ applicationScope = applicationCoroutineScope,
context = applicationContext,
repository = fingerprintPropertyRepository,
configurationInteractor = configurationInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt
index 8ff04a63..1c8190e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt
@@ -15,8 +15,10 @@
package com.android.systemui.deviceentry.data
+import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepositoryModule
import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepositoryModule
import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepositoryModule
+import com.android.systemui.display.data.repository.FakeDisplayRepositoryModule
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepositoryModule
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepositoryModule
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepositoryModule
@@ -30,6 +32,8 @@
FakeDeviceEntryRepositoryModule::class,
FakeDeviceEntryFaceAuthRepositoryModule::class,
FakeDeviceEntryFingerprintAuthRepositoryModule::class,
+ FakeDisplayRepositoryModule::class,
+ FakeDisplayStateRepositoryModule::class,
FakeFingerprintPropertyRepositoryModule::class,
FakeTrustRepositoryModule::class,
]
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorKosmos.kt
index b04161a..81123d0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractorKosmos.kt
@@ -18,7 +18,7 @@
package com.android.systemui.deviceentry.domain.interactor
-import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
+import com.android.systemui.biometrics.domain.interactor.fingerprintPropertyInteractor
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
import com.android.systemui.kosmos.Kosmos
@@ -27,7 +27,7 @@
val Kosmos.deviceEntryUdfpsInteractor by Fixture {
DeviceEntryUdfpsInteractor(
- fingerprintPropertyRepository = fingerprintPropertyRepository,
+ fingerprintPropertyInteractor = fingerprintPropertyInteractor,
fingerprintAuthRepository = deviceEntryFingerprintAuthRepository,
biometricSettingsRepository = biometricSettingsRepository,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
index d8098b7..0fc0a3c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt
@@ -16,7 +16,11 @@
package com.android.systemui.display.data.repository
import android.view.Display
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.util.mockito.mock
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import org.mockito.Mockito.`when` as whenever
@@ -42,8 +46,9 @@
fun createPendingDisplay(id: Int = 0): DisplayRepository.PendingDisplay =
mock<DisplayRepository.PendingDisplay> { whenever(this.id).thenReturn(id) }
+@SysUISingleton
/** Fake [DisplayRepository] implementation for testing. */
-class FakeDisplayRepository : DisplayRepository {
+class FakeDisplayRepository @Inject constructor() : DisplayRepository {
private val flow = MutableSharedFlow<Set<Display>>(replay = 1)
private val pendingDisplayFlow =
MutableSharedFlow<DisplayRepository.PendingDisplay?>(replay = 1)
@@ -71,3 +76,8 @@
override val displayChangeEvent: Flow<Int> = _displayChangeEvent
suspend fun emitDisplayChangeEvent(displayId: Int) = _displayChangeEvent.emit(displayId)
}
+
+@Module
+interface FakeDisplayRepositoryModule {
+ @Binds fun bindFake(fake: FakeDisplayRepository): DisplayRepository
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
index 592fa38..5b642ea 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
@@ -42,7 +42,7 @@
private val _currentClockId = MutableStateFlow(DEFAULT_CLOCK_ID)
override val currentClockId: Flow<ClockId> = _currentClockId
- private val _currentClock = MutableStateFlow(null)
+ private val _currentClock: MutableStateFlow<ClockController?> = MutableStateFlow(null)
override val currentClock = _currentClock
private val _previewClockPair =
@@ -60,6 +60,10 @@
override fun setClockSize(@ClockSize size: Int) {
_clockSize.value = size
}
+
+ fun setCurrentClock(clockController: ClockController) {
+ _currentClock.value = clockController
+ }
}
@Module
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt
index b24b95e..f26bb83 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt
@@ -35,7 +35,10 @@
private val _revealAmount: MutableStateFlow<Float> = MutableStateFlow(0.0f)
override val revealAmount: Flow<Float> = _revealAmount
- override fun startRevealAmountAnimator(reveal: Boolean) {
+ override val isAnimating: Boolean
+ get() = false
+
+ override fun startRevealAmountAnimator(reveal: Boolean, duration: Long) {
if (reveal) {
_revealAmount.value = 1.0f
} else {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
index 8452963..75489b6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
@@ -17,10 +17,12 @@
package com.android.systemui.keyguard.data.repository
import android.os.fakeExecutorHandler
-import com.android.systemui.common.ui.data.repository.configurationRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
+import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor.Companion.WEATHER_CLOCK_BLUEPRINT_ID
import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT
+import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.util.ThreadAssert
import com.android.systemui.util.mockito.mock
@@ -28,8 +30,13 @@
val Kosmos.keyguardBlueprintRepository by
Kosmos.Fixture {
KeyguardBlueprintRepository(
- configurationRepository = configurationRepository,
- blueprints = setOf(defaultBlueprint),
+ blueprints =
+ setOf(
+ defaultBlueprint,
+ splitShadeBlueprint,
+ weatherClockBlueprint,
+ splitShadeWeatherClockBlueprint,
+ ),
handler = fakeExecutorHandler,
assert = mock<ThreadAssert>(),
)
@@ -42,3 +49,27 @@
override val sections: List<KeyguardSection>
get() = listOf()
}
+
+private val weatherClockBlueprint =
+ object : KeyguardBlueprint {
+ override val id: String
+ get() = WEATHER_CLOCK_BLUEPRINT_ID
+ override val sections: List<KeyguardSection>
+ get() = listOf()
+ }
+
+private val splitShadeWeatherClockBlueprint =
+ object : KeyguardBlueprint {
+ override val id: String
+ get() = SPLIT_SHADE_WEATHER_CLOCK_BLUEPRINT_ID
+ override val sections: List<KeyguardSection>
+ get() = listOf()
+ }
+
+private val splitShadeBlueprint =
+ object : KeyguardBlueprint {
+ override val id: String
+ get() = SplitShadeKeyguardBlueprint.Companion.ID
+ override val sections: List<KeyguardSection>
+ get() = listOf()
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt
index 8b0bba1..87d6c17 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt
@@ -17,6 +17,8 @@
package com.android.systemui.keyguard.domain.interactor
import android.content.applicationContext
+import com.android.systemui.biometrics.domain.interactor.fingerprintPropertyInteractor
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.keyguard.data.repository.keyguardBlueprintRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
@@ -30,5 +32,7 @@
context = applicationContext,
splitShadeStateController = splitShadeStateController,
clockInteractor = keyguardClockInteractor,
+ configurationInteractor = configurationInteractor,
+ fingerprintPropertyInteractor = fingerprintPropertyInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorKosmos.kt
index 58e0a3b..d5bdbdb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorKosmos.kt
@@ -29,6 +29,6 @@
lightRevealScrimRepository,
applicationCoroutineScope,
scrimLogger,
- powerInteractor,
+ { powerInteractor },
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/PanelExpansionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorKosmos.kt
similarity index 71%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/PanelExpansionInteractorKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorKosmos.kt
index a025846..2a4dd3a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/PanelExpansionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/PanelExpansionInteractorKosmos.kt
@@ -14,17 +14,15 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.stack.ui.viewmodel
+package com.android.systemui.shade.domain.interactor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.scene.domain.interactor.PanelExpansionInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.shade.data.repository.shadeRepository
-val Kosmos.panelExpansionInteractor by Fixture {
- PanelExpansionInteractor(
+val Kosmos.panelExpansionInteractor by Fixture { panelExpansionInteractorImpl }
+val Kosmos.panelExpansionInteractorImpl by Fixture {
+ PanelExpansionInteractorImpl(
sceneInteractor = sceneInteractor,
- shadeRepository = shadeRepository,
)
}
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
index e0fe88a..10e6ed4 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
@@ -1566,6 +1566,10 @@
private String mCameraId = null;
private IBinder mToken;
+ OutputSurfaceImplStub mOutputPreviewSurfaceImpl;
+ OutputSurfaceImplStub mOutputImageCaptureSurfaceImpl;
+ OutputSurfaceImplStub mOutputPostviewSurfaceImpl;
+
public SessionProcessorImplStub(SessionProcessorImpl sessionProcessor) {
mSessionProcessor = sessionProcessor;
}
@@ -1574,21 +1578,18 @@
public CameraSessionConfig initSession(IBinder token, String cameraId,
Map<String, CameraMetadataNative> charsMapNative, OutputSurface previewSurface,
OutputSurface imageCaptureSurface, OutputSurface postviewSurface) {
- OutputSurfaceImplStub outputPreviewSurfaceImpl =
- new OutputSurfaceImplStub(previewSurface);
- OutputSurfaceImplStub outputImageCaptureSurfaceImpl =
- new OutputSurfaceImplStub(imageCaptureSurface);
- OutputSurfaceImplStub outputPostviewSurfaceImpl =
- new OutputSurfaceImplStub(postviewSurface);
+ mOutputPreviewSurfaceImpl = new OutputSurfaceImplStub(previewSurface);
+ mOutputImageCaptureSurfaceImpl = new OutputSurfaceImplStub(imageCaptureSurface);
+ mOutputPostviewSurfaceImpl = new OutputSurfaceImplStub(postviewSurface);
Camera2SessionConfigImpl sessionConfig;
if (LATENCY_IMPROVEMENTS_SUPPORTED) {
OutputSurfaceConfigurationImplStub outputSurfaceConfigs =
- new OutputSurfaceConfigurationImplStub(outputPreviewSurfaceImpl,
+ new OutputSurfaceConfigurationImplStub(mOutputPreviewSurfaceImpl,
// Image Analysis Output is currently only supported in CameraX
- outputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/,
- outputPostviewSurfaceImpl);
+ mOutputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/,
+ mOutputPostviewSurfaceImpl);
sessionConfig = mSessionProcessor.initSession(cameraId,
getCharacteristicsMap(charsMapNative),
@@ -1596,8 +1597,8 @@
} else {
sessionConfig = mSessionProcessor.initSession(cameraId,
getCharacteristicsMap(charsMapNative),
- getApplicationContext(), outputPreviewSurfaceImpl,
- outputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/);
+ getApplicationContext(), mOutputPreviewSurfaceImpl,
+ mOutputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/);
}
List<Camera2OutputConfigImpl> outputConfigs = sessionConfig.getOutputConfigs();
@@ -1632,6 +1633,18 @@
public void deInitSession(IBinder token) {
CameraExtensionsProxyService.unregisterDeathRecipient(mToken, this);
mSessionProcessor.deInitSession();
+
+ if (Flags.surfaceLeakFix()) {
+ if (mOutputImageCaptureSurfaceImpl.mSurface != null) {
+ mOutputImageCaptureSurfaceImpl.mSurface.release();
+ }
+ if (mOutputPreviewSurfaceImpl.mSurface != null) {
+ mOutputPreviewSurfaceImpl.mSurface.release();
+ }
+ if (mOutputPostviewSurfaceImpl.mSurface != null) {
+ mOutputPostviewSurfaceImpl.mSurface.release();
+ }
+ }
}
@Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index cbb66dc..ff48c9d 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -40,6 +40,7 @@
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
+import static com.android.internal.accessibility.common.ShortcutConstants.USER_SHORTCUT_TYPES;
import static com.android.internal.accessibility.util.AccessibilityStatsLogUtils.logAccessibilityShortcutActivated;
import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -111,6 +112,7 @@
import android.safetycenter.SafetyCenterManager;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.Log;
@@ -145,9 +147,13 @@
import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.internal.accessibility.AccessibilityShortcutController.FrameworkFeatureInfo;
import com.android.internal.accessibility.AccessibilityShortcutController.LaunchableFrameworkFeatureInfo;
+import com.android.internal.accessibility.common.ShortcutConstants;
+import com.android.internal.accessibility.common.ShortcutConstants.FloatingMenuSize;
+import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
import com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity;
import com.android.internal.accessibility.util.AccessibilityUtils;
+import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
@@ -168,6 +174,7 @@
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.pm.UserManagerInternal;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.utils.Slogf;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -191,6 +198,7 @@
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
/**
* This class is instantiated by the system as a system level service and can be
@@ -2334,6 +2342,7 @@
if (!parsedAccessibilityServiceInfos.equals(userState.mInstalledServices)) {
userState.mInstalledServices.clear();
userState.mInstalledServices.addAll(parsedAccessibilityServiceInfos);
+ userState.updateTileServiceMapForAccessibilityServiceLocked();
return true;
}
return false;
@@ -2359,6 +2368,7 @@
if (!parsedAccessibilityShortcutInfos.equals(userState.mInstalledShortcuts)) {
userState.mInstalledShortcuts.clear();
userState.mInstalledShortcuts.addAll(parsedAccessibilityShortcutInfos);
+ userState.updateTileServiceMapForAccessibilityActivityLocked();
return true;
}
return false;
@@ -2621,6 +2631,12 @@
private <T> void persistColonDelimitedSetToSettingLocked(String settingName, int userId,
Set<T> set, Function<T, String> toString) {
+ persistColonDelimitedSetToSettingLocked(settingName, userId, set,
+ toString, /* defaultEmptyString= */ null);
+ }
+
+ private <T> void persistColonDelimitedSetToSettingLocked(String settingName, int userId,
+ Set<T> set, Function<T, String> toString, String defaultEmptyString) {
final StringBuilder builder = new StringBuilder();
for (T item : set) {
final String str = (item != null ? toString.apply(item) : null);
@@ -2636,7 +2652,18 @@
try {
final String settingValue = builder.toString();
Settings.Secure.putStringForUser(mContext.getContentResolver(),
- settingName, TextUtils.isEmpty(settingValue) ? null : settingValue, userId);
+ settingName,
+ TextUtils.isEmpty(settingValue) ? defaultEmptyString : settingValue, userId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private void persistIntToSetting(int userId, String settingName, int settingValue) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putIntForUser(
+ mContext.getContentResolver(), settingName, settingValue, userId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3005,6 +3032,7 @@
scheduleUpdateClientsIfNeededLocked(userState, forceUpdate);
updateAccessibilityShortcutKeyTargetsLocked(userState);
updateAccessibilityButtonTargetsLocked(userState);
+ updateAccessibilityQsTargetsLocked(userState);
// Update the capabilities before the mode because we will check the current mode is
// invalid or not..
updateMagnificationCapabilitiesSettingsChangeLocked(userState);
@@ -3132,6 +3160,7 @@
somethingChanged |= readMagnificationEnabledSettingsLocked(userState);
somethingChanged |= readAutoclickEnabledSettingLocked(userState);
somethingChanged |= readAccessibilityShortcutKeySettingLocked(userState);
+ somethingChanged |= readAccessibilityQsTargetsLocked(userState);
somethingChanged |= readAccessibilityButtonTargetsLocked(userState);
somethingChanged |= readAccessibilityButtonTargetComponentLocked(userState);
somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState);
@@ -3305,6 +3334,21 @@
return true;
}
+ private boolean readAccessibilityQsTargetsLocked(AccessibilityUserState userState) {
+ final Set<String> targetsFromSetting = new ArraySet<>();
+ readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+ userState.mUserId, str -> str, targetsFromSetting);
+
+ final Set<String> currentTargets =
+ userState.getShortcutTargetsLocked(UserShortcutType.QUICK_SETTINGS);
+ if (targetsFromSetting.equals(currentTargets)) {
+ return false;
+ }
+ userState.updateA11yQsTargetLocked(targetsFromSetting);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+ return true;
+ }
+
private boolean readAccessibilityButtonTargetsLocked(AccessibilityUserState userState) {
final Set<String> targetsFromSetting = new ArraySet<>();
readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
@@ -3636,6 +3680,8 @@
final Set<String> shortcutKeyTargets =
userState.getShortcutTargetsLocked(ACCESSIBILITY_SHORTCUT_KEY);
+ final Set<String> qsShortcutTargets =
+ userState.getShortcutTargetsLocked(UserShortcutType.QUICK_SETTINGS);
userState.mEnabledServices.forEach(componentName -> {
if (packageName != null && componentName != null
&& !packageName.equals(componentName.getPackageName())) {
@@ -3657,7 +3703,8 @@
return;
}
if (doesShortcutTargetsStringContain(buttonTargets, serviceName)
- || doesShortcutTargetsStringContain(shortcutKeyTargets, serviceName)) {
+ || doesShortcutTargetsStringContain(shortcutKeyTargets, serviceName)
+ || doesShortcutTargetsStringContain(qsShortcutTargets, serviceName)) {
return;
}
// For enabled a11y services targeting sdk version > Q and requesting a11y button should
@@ -3678,6 +3725,33 @@
}
/**
+ * Update the Settings.Secure.ACCESSIBILITY_QS_TARGETS so that it only contains valid content,
+ * and a side loaded service can't spoof the package name of the default service.
+ */
+ private void updateAccessibilityQsTargetsLocked(AccessibilityUserState userState) {
+ final Set<String> targets =
+ userState.getShortcutTargetsLocked(UserShortcutType.QUICK_SETTINGS);
+ final int lastSize = targets.size();
+ if (lastSize == 0) {
+ return;
+ }
+
+ // Removes the targets that are no longer installed on the device.
+ boolean somethingChanged = targets.removeIf(
+ name -> !userState.isShortcutTargetInstalledLocked(name));
+ if (!somethingChanged) {
+ return;
+ }
+ userState.updateA11yQsTargetLocked(targets);
+
+ // Update setting key with new value.
+ persistColonDelimitedSetToSettingLocked(
+ Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+ userState.mUserId, targets, str -> str);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+ }
+
+ /**
* Remove the shortcut target for the unbound service which is requesting accessibility button
* and targeting sdk > Q from the accessibility button and shortcut.
*
@@ -3691,19 +3765,42 @@
.targetSdkVersion <= Build.VERSION_CODES.Q) {
return;
}
+
+ final List<Pair<Integer, String>> shortcutTypeAndShortcutSetting = List.of(
+ new Pair<>(ACCESSIBILITY_SHORTCUT_KEY,
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE),
+ new Pair<>(ACCESSIBILITY_BUTTON,
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS),
+ new Pair<>(UserShortcutType.QUICK_SETTINGS,
+ Settings.Secure.ACCESSIBILITY_QS_TARGETS)
+ );
+
final ComponentName serviceName = service.getComponentName();
- if (userState.removeShortcutTargetLocked(ACCESSIBILITY_SHORTCUT_KEY, serviceName)) {
- final Set<String> currentTargets = userState.getShortcutTargetsLocked(
- ACCESSIBILITY_SHORTCUT_KEY);
- persistColonDelimitedSetToSettingLocked(
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
- userState.mUserId, currentTargets, str -> str);
- }
- if (userState.removeShortcutTargetLocked(ACCESSIBILITY_BUTTON, serviceName)) {
- final Set<String> currentTargets = userState.getShortcutTargetsLocked(
- ACCESSIBILITY_BUTTON);
- persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
- userState.mUserId, currentTargets, str -> str);
+ for (Pair<Integer, String> shortcutTypePair : shortcutTypeAndShortcutSetting) {
+ int shortcutType = shortcutTypePair.first;
+ String shortcutSettingName = shortcutTypePair.second;
+ if (userState.removeShortcutTargetLocked(shortcutType, serviceName)) {
+ final Set<String> currentTargets = userState.getShortcutTargetsLocked(shortcutType);
+ persistColonDelimitedSetToSettingLocked(
+ shortcutSettingName,
+ userState.mUserId, currentTargets, str -> str);
+
+ if (shortcutType != UserShortcutType.QUICK_SETTINGS) {
+ continue;
+ }
+
+ ComponentName tileService =
+ userState.getA11yFeatureToTileService().getOrDefault(serviceName, null);
+
+ final StatusBarManagerInternal statusBarManagerInternal =
+ LocalServices.getService(StatusBarManagerInternal.class);
+ // In case it's not initialized yet
+ if (statusBarManagerInternal == null || tileService == null) {
+ continue;
+ }
+ mMainHandler.sendMessage(obtainMessage(StatusBarManagerInternal::removeQsTile,
+ statusBarManagerInternal, tileService));
+ }
}
}
@@ -3967,6 +4064,262 @@
}
}
+ /**
+ * Turns on or off a shortcut type of the accessibility features. The {@code shortcutTypes} is a
+ * flag that contains values defined in the
+ * {@link ShortcutConstants.USER_SHORTCUT_TYPES}.
+ *
+ * @hide
+ */
+ @Override
+ public void enableShortcutsForTargets(
+ boolean enable, @UserShortcutType int shortcutTypes,
+ @NonNull List<String> shortcutTargets, @UserIdInt int userId) {
+ mContext.enforceCallingPermission(
+ Manifest.permission.MANAGE_ACCESSIBILITY, "enableShortcutsForTargets");
+ for (int shortcutType : USER_SHORTCUT_TYPES) {
+ if ((shortcutTypes & shortcutType) == shortcutType) {
+ enableShortcutForTargets(enable, shortcutType, shortcutTargets, userId);
+ }
+ }
+ }
+
+ private void enableShortcutForTargets(
+ boolean enable, @UserShortcutType int shortcutType,
+ @NonNull List<String> shortcutTargets, @UserIdInt int userId) {
+ final String shortcutTypeSettingKey = ShortcutUtils.convertToKey(shortcutType);
+ if (shortcutType == UserShortcutType.TRIPLETAP
+ || shortcutType == UserShortcutType.TWOFINGER_DOUBLETAP) {
+ for (String target : shortcutTargets) {
+ if (MAGNIFICATION_CONTROLLER_NAME.equals(target)) {
+ persistIntToSetting(
+ userId,
+ shortcutTypeSettingKey,
+ enable ? AccessibilityUtils.State.ON : AccessibilityUtils.State.OFF);
+ } else {
+ Slog.w(LOG_TAG,
+ "Triple tap or two-fingers double-tap is not supported for " + target);
+ }
+ }
+ return;
+ }
+ Set<String> validNewTargets;
+ Set<String> currentTargets;
+
+ Map<ComponentName, ComponentName> featureToTileMap =
+ getA11yFeatureToTileMapInternal(userId);
+ synchronized (mLock) {
+ AccessibilityUserState userState = getUserStateLocked(userId);
+ currentTargets =
+ ShortcutUtils.getShortcutTargetsFromSettings(mContext, shortcutType, userId);
+
+ Set<String> newTargets = new ArraySet<>(currentTargets);
+ if (enable) {
+ newTargets.addAll(shortcutTargets);
+ } else {
+ newTargets.removeAll(shortcutTargets);
+ }
+ validNewTargets = newTargets;
+
+ // filter out targets that doesn't have qs shortcut
+ if (shortcutType == UserShortcutType.QUICK_SETTINGS) {
+ validNewTargets = newTargets.stream().filter(target -> {
+ ComponentName targetComponent = ComponentName.unflattenFromString(target);
+ return featureToTileMap.containsKey(targetComponent);
+ }).collect(Collectors.toUnmodifiableSet());
+ }
+
+ if (currentTargets.equals(validNewTargets)) {
+ return;
+ }
+ persistColonDelimitedSetToSettingLocked(
+ shortcutTypeSettingKey,
+ userId,
+ validNewTargets,
+ str -> str,
+ /* defaultEmptyString= */ ""
+ );
+
+ if (shortcutType == UserShortcutType.QUICK_SETTINGS) {
+ userState.updateA11yQsTargetLocked(validNewTargets);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+ onUserStateChangedLocked(userState);
+ }
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
+ mContext, new ArraySet<>(shortcutTargets), userId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ // Add or Remove tile in QS Panel
+ if (shortcutType == UserShortcutType.QUICK_SETTINGS) {
+ mMainHandler.sendMessage(obtainMessage(
+ AccessibilityManagerService::updateA11yTileServicesInQuickSettingsPanel,
+ this, validNewTargets, currentTargets, userId));
+ }
+
+ if (!enable) {
+ return;
+ }
+ if (shortcutType == UserShortcutType.HARDWARE) {
+ skipVolumeShortcutDialogTimeoutRestriction(userId);
+ } else if (shortcutType == UserShortcutType.SOFTWARE) {
+ // Update the A11y FAB size to large when the Magnification shortcut is
+ // enabled and the user hasn't changed the floating button size
+ if (shortcutTargets.contains(MAGNIFICATION_CONTROLLER_NAME)
+ && Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
+ FloatingMenuSize.UNKNOWN, userId) == FloatingMenuSize.UNKNOWN) {
+ persistIntToSetting(
+ userId,
+ Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
+ FloatingMenuSize.LARGE);
+ }
+ }
+ }
+
+ /**
+ * Add or remove the TileServices of the a11y features in the Quick Settings panel based on the
+ * changes in the new targets and current targets.
+ *
+ * <p>
+ * The framework tiles implemented in the SysUi are automatically added/removed via the
+ * SystemUI's AutoAddable framework. This method only handles updating the TileServices
+ * provided by AccessibilityService or Accessibility Activity.
+ * </p>
+ *
+ * @see com.android.systemui.qs.pipeline.domain.model.AutoAddable AutoAddable QS Tiles
+ */
+ private void updateA11yTileServicesInQuickSettingsPanel(
+ Set<String> newQsTargets,
+ Set<String> currentQsTargets, @UserIdInt int userId) {
+ // Call StatusBarManager to add/remove tiles
+ final StatusBarManagerInternal statusBarManagerInternal =
+ LocalServices.getService(StatusBarManagerInternal.class);
+ // In case it's not initialized yet
+ if (statusBarManagerInternal == null) {
+ return;
+ }
+
+ Map<ComponentName, ComponentName> a11yFeatureToTileMap =
+ getA11yFeatureToTileMapInternal(userId);
+ Set<String> targetWithNoTile = new ArraySet<>();
+
+ // Add TileServices to QS Panel that are added to the new targets
+ newQsTargets.stream()
+ .filter(target -> !currentQsTargets.contains(target))
+ .forEach(
+ target -> {
+ ComponentName targetComponent =
+ ComponentName.unflattenFromString(target);
+ if (targetComponent == null
+ || !a11yFeatureToTileMap.containsKey(targetComponent)) {
+ targetWithNoTile.add(target);
+ return;
+ }
+
+ if (ShortcutConstants.A11Y_FEATURE_TO_FRAMEWORK_TILE.containsKey(
+ targetComponent)) {
+ // a11y framework tile is handled by the SysUi autoaddable framework
+ return;
+ }
+ statusBarManagerInternal.addQsTileToFrontOrEnd(
+ a11yFeatureToTileMap.get(targetComponent), /* end= */ true);
+ }
+ );
+
+ // Remove TileServices from QS Panel that are no longer in the new targets.
+ currentQsTargets.stream()
+ .filter(target -> !newQsTargets.contains(target))
+ .forEach(
+ target -> {
+ ComponentName targetComponent =
+ ComponentName.unflattenFromString(target);
+ if (targetComponent == null
+ || !a11yFeatureToTileMap.containsKey(targetComponent)) {
+ targetWithNoTile.add(target);
+ return;
+ }
+
+ if (ShortcutConstants.A11Y_FEATURE_TO_FRAMEWORK_TILE.containsKey(
+ targetComponent)) {
+ // a11y framework tile is handled by the SysUi autoaddable framework
+ return;
+ }
+ statusBarManagerInternal.removeQsTile(
+ a11yFeatureToTileMap.get(targetComponent));
+ }
+ );
+
+ if (!targetWithNoTile.isEmpty()) {
+ throw new IllegalArgumentException(
+ "Unable to add/remove Tiles for a11y features: " + targetWithNoTile
+ + "as the Tiles aren't provided");
+ }
+ }
+
+ @Override
+ public Bundle getA11yFeatureToTileMap(@UserIdInt int userId) {
+ mContext.enforceCallingPermission(
+ Manifest.permission.MANAGE_ACCESSIBILITY, "getA11yFeatureToTileMap");
+
+ Bundle bundle = new Bundle();
+ Map<ComponentName, ComponentName> a11yFeatureToTile =
+ getA11yFeatureToTileMapInternal(userId);
+ for (Map.Entry<ComponentName, ComponentName> entry : a11yFeatureToTile.entrySet()) {
+ bundle.putParcelable(entry.getKey().flattenToString(), entry.getValue());
+ }
+ return bundle;
+ }
+
+
+
+ /**
+ * Returns accessibility feature's component and the provided tile map. This includes the
+ * TileService provided by the AccessibilityService or Accessibility Activity and the tile
+ * component provided by the framework's feature.
+ *
+ * @return a map of a feature's component name, and its provided tile's component name. The
+ * returned map's keys and values are not null. If a feature doesn't provide a tile, it won't
+ * have an entry in this map.
+ *
+ * @see ShortcutConstants.A11Y_FEATURE_TO_FRAMEWORK_TILE
+ */
+ @NonNull
+ private Map<ComponentName, ComponentName> getA11yFeatureToTileMapInternal(
+ @UserIdInt int userId) {
+ final Map<ComponentName, ComponentName> a11yFeatureToTileService;
+ Map<ComponentName, ComponentName> a11yFeatureToTile = new ArrayMap<>();
+ final int resolvedUserId;
+
+ synchronized (mLock) {
+ resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(userId);
+ AccessibilityUserState userState = getUserStateLocked(resolvedUserId);
+ a11yFeatureToTileService = userState.getA11yFeatureToTileService();
+ }
+ final boolean shouldFilterAppAccess = Binder.getCallingPid() != OWN_PROCESS_ID;
+ final int callingUid = Binder.getCallingUid();
+ final PackageManagerInternal pm = LocalServices.getService(
+ PackageManagerInternal.class);
+
+ for (Map.Entry<ComponentName, ComponentName> entry :
+ a11yFeatureToTileService.entrySet()) {
+ if (shouldFilterAppAccess
+ && pm.filterAppAccess(
+ entry.getKey().getPackageName(), callingUid, resolvedUserId)) {
+ continue;
+ }
+ a11yFeatureToTile.put(entry.getKey(), entry.getValue());
+ }
+
+ a11yFeatureToTile.putAll(ShortcutConstants.A11Y_FEATURE_TO_FRAMEWORK_TILE);
+ return a11yFeatureToTile;
+ }
+
@Override
public List<String> getAccessibilityShortcutTargets(@ShortcutType int shortcutType) {
if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
@@ -5836,4 +6189,15 @@
}
}
}
+
+
+ /**
+ * Bypasses the timeout restriction if volume key shortcut assigned.
+ */
+ private void skipVolumeShortcutDialogTimeoutRestriction(int userId) {
+ persistIntToSetting(
+ userId,
+ Settings.Secure.SKIP_ACCESSIBILITY_SHORTCUT_DIALOG_TIMEOUT_RESTRICTION,
+ /* true */ 1);
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 68ee780..063eafe 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -38,10 +38,12 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.RemoteCallbackList;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
@@ -51,6 +53,7 @@
import com.android.internal.R;
import com.android.internal.accessibility.AccessibilityShortcutController;
+import com.android.internal.accessibility.common.ShortcutConstants;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -99,6 +102,7 @@
final ArraySet<String> mAccessibilityShortcutKeyTargets = new ArraySet<>();
final ArraySet<String> mAccessibilityButtonTargets = new ArraySet<>();
+ private final ArraySet<String> mAccessibilityQsTargets = new ArraySet<>();
private final ServiceInfoChangeListener mServiceInfoChangeListener;
@@ -146,6 +150,8 @@
private final int mFocusStrokeWidthDefaultValue;
// The default value of the focus color.
private final int mFocusColorDefaultValue;
+ private final Map<ComponentName, ComponentName> mA11yServiceToTileService = new ArrayMap<>();
+ private final Map<ComponentName, ComponentName> mA11yActivityToTileService = new ArrayMap<>();
private Context mContext;
@@ -560,6 +566,8 @@
pw.println("}");
pw.append(" button target:{").append(mTargetAssignedToAccessibilityButton);
pw.println("}");
+ pw.append(" qs shortcut targets:" + mAccessibilityQsTargets);
+ pw.println();
pw.append(" Bound services:{");
final int serviceCount = mBoundServices.size();
for (int j = 0; j < serviceCount; j++) {
@@ -762,6 +770,8 @@
return mAccessibilityShortcutKeyTargets;
} else if (shortcutType == ACCESSIBILITY_BUTTON) {
return mAccessibilityButtonTargets;
+ } else if (shortcutType == ShortcutConstants.UserShortcutType.QUICK_SETTINGS) {
+ return getA11yQsTargets();
}
return null;
}
@@ -808,7 +818,8 @@
*/
public boolean removeShortcutTargetLocked(@ShortcutType int shortcutType,
ComponentName target) {
- return getShortcutTargetsLocked(shortcutType).removeIf(name -> {
+ Set<String> targets = getShortcutTargetsLocked(shortcutType);
+ boolean result = targets.removeIf(name -> {
ComponentName componentName;
if (name == null
|| (componentName = ComponentName.unflattenFromString(name)) == null) {
@@ -816,6 +827,11 @@
}
return componentName.equals(target);
});
+ if (shortcutType == ShortcutConstants.UserShortcutType.QUICK_SETTINGS) {
+ updateA11yQsTargetLocked(targets);
+ }
+
+ return result;
}
/**
@@ -1034,4 +1050,60 @@
}
return false;
}
+
+ public void updateTileServiceMapForAccessibilityServiceLocked() {
+ mA11yServiceToTileService.clear();
+ mInstalledServices.forEach(
+ a11yServiceInfo -> {
+ String tileServiceName = a11yServiceInfo.getTileServiceName();
+ if (!TextUtils.isEmpty(tileServiceName)) {
+ ResolveInfo resolveInfo = a11yServiceInfo.getResolveInfo();
+ ComponentName a11yFeature = new ComponentName(
+ resolveInfo.serviceInfo.packageName,
+ resolveInfo.serviceInfo.name
+ );
+ ComponentName tileService = new ComponentName(
+ a11yFeature.getPackageName(),
+ tileServiceName
+ );
+ mA11yServiceToTileService.put(a11yFeature, tileService);
+ }
+ }
+ );
+ }
+
+ public void updateTileServiceMapForAccessibilityActivityLocked() {
+ mA11yActivityToTileService.clear();
+ mInstalledShortcuts.forEach(
+ a11yShortcutInfo -> {
+ String tileServiceName = a11yShortcutInfo.getTileServiceName();
+ if (!TextUtils.isEmpty(tileServiceName)) {
+ ComponentName a11yFeature = a11yShortcutInfo.getComponentName();
+ ComponentName tileService = new ComponentName(
+ a11yFeature.getPackageName(),
+ tileServiceName);
+ mA11yActivityToTileService.put(a11yFeature, tileService);
+ }
+ }
+ );
+ }
+
+ public void updateA11yQsTargetLocked(Set<String> targets) {
+ mAccessibilityQsTargets.clear();
+ mAccessibilityQsTargets.addAll(targets);
+ }
+
+ /**
+ * Returns a copy of the targets which has qs shortcut turned on
+ */
+ public ArraySet<String> getA11yQsTargets() {
+ return new ArraySet<>(mAccessibilityQsTargets);
+ }
+
+ public Map<ComponentName, ComponentName> getA11yFeatureToTileService() {
+ Map<ComponentName, ComponentName> featureToTileServiceMap = new ArrayMap<>();
+ featureToTileServiceMap.putAll(mA11yServiceToTileService);
+ featureToTileServiceMap.putAll(mA11yActivityToTileService);
+ return featureToTileServiceMap;
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 7afb780..13bc772 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -1246,7 +1246,8 @@
@GuardedBy("mLock")
private void requestNewFillResponseLocked(@NonNull ViewState viewState, int newState,
int flags) {
- final FillResponse existingResponse = shouldRequestSecondaryProvider(flags)
+ boolean isSecondary = shouldRequestSecondaryProvider(flags);
+ final FillResponse existingResponse = isSecondary
? viewState.getSecondaryResponse() : viewState.getResponse();
mFillRequestEventLogger.startLogForNewRequest();
mRequestCount++;
@@ -1283,12 +1284,7 @@
}
viewState.setState(newState);
-
- int requestId;
- // TODO(b/158623971): Update this to prevent possible overflow
- do {
- requestId = sIdCounter.getAndIncrement();
- } while (requestId == INVALID_REQUEST_ID);
+ int requestId = getRequestId(isSecondary);
// Create a metrics log for the request
final int ordinal = mRequestLogs.size() + 1;
@@ -1367,6 +1363,25 @@
requestAssistStructureLocked(requestId, flags);
}
+ private static int getRequestId(boolean isSecondary) {
+ // For authentication flows, there needs to be a way to know whether to retrieve the Fill
+ // Response from the primary provider or the secondary provider from the requestId. A simple
+ // way to achieve this is by assigning odd number request ids to secondary provider and
+ // even numbers to primary provider.
+ int requestId;
+ // TODO(b/158623971): Update this to prevent possible overflow
+ if (isSecondary) {
+ do {
+ requestId = sIdCounter.getAndIncrement();
+ } while (!isSecondaryProviderRequestId(requestId));
+ } else {
+ do {
+ requestId = sIdCounter.getAndIncrement();
+ } while (requestId == INVALID_REQUEST_ID || isSecondaryProviderRequestId(requestId));
+ }
+ return requestId;
+ }
+
private boolean isRequestSupportFillDialog(int flags) {
return (flags & FLAG_SUPPORTS_FILL_DIALOG) != 0;
}
@@ -2790,7 +2805,9 @@
removeFromService();
return;
}
- final FillResponse authenticatedResponse = mResponses.get(requestId);
+ final FillResponse authenticatedResponse = isSecondaryProviderRequestId(requestId)
+ ? mSecondaryResponses.get(requestId)
+ : mResponses.get(requestId);
if (authenticatedResponse == null || data == null) {
Slog.w(TAG, "no authenticated response");
mPresentationStatsEventLogger.maybeSetAuthenticationResult(
@@ -2915,6 +2932,10 @@
}
}
+ private static boolean isSecondaryProviderRequestId(int requestId) {
+ return requestId % 2 == 1;
+ }
+
private Dataset getDatasetFromCredentialResponse(GetCredentialResponse result) {
if (result == null) {
return null;
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index 6e98e68..1f8736b 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,7 @@
import android.os.ParcelFileDescriptor;
import android.util.Slog;
-import com.android.server.LocalServices;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.backup.utils.BackupEligibilityRules;
import java.io.BufferedInputStream;
@@ -49,16 +48,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";
@@ -66,7 +63,7 @@
// key under which we store global metadata (individual app metadata
// is stored using the package name as a key)
- private static final String GLOBAL_METADATA_KEY = "@meta@";
+ @VisibleForTesting static final String GLOBAL_METADATA_KEY = "@meta@";
// key under which we store the identity of the user's chosen default home app
private static final String DEFAULT_HOME_KEY = "@home@";
@@ -76,19 +73,19 @@
// ANCESTRAL_RECORD_VERSION=1 (introduced Android P).
// Should the ANCESTRAL_RECORD_VERSION be bumped up in the future, STATE_FILE_VERSION will also
// need bumping up, assuming more data needs saving to the state file.
- private static final String STATE_FILE_HEADER = "=state=";
- private static final int STATE_FILE_VERSION = 2;
+ @VisibleForTesting static final String STATE_FILE_HEADER = "=state=";
+ @VisibleForTesting static final int STATE_FILE_VERSION = 2;
// key under which we store the saved ancestral-dataset format (starting from Android P)
// IMPORTANT: this key needs to come first in the restore data stream (to find out
// whether this version of Android knows how to restore the incoming data set), so it needs
// to be always the first one in alphabetical order of all the keys
- private static final String ANCESTRAL_RECORD_KEY = "@ancestral_record@";
+ @VisibleForTesting static final String ANCESTRAL_RECORD_KEY = "@ancestral_record@";
// Current version of the saved ancestral-dataset format
// Note that this constant was not used until Android P, and started being used
// to version @pm@ data for forwards-compatibility.
- private static final int ANCESTRAL_RECORD_VERSION = 1;
+ @VisibleForTesting static final int ANCESTRAL_RECORD_VERSION = 1;
// Undefined version of the saved ancestral-dataset file format means that the restore data
// is coming from pre-Android P device.
@@ -134,8 +131,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 +156,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 +201,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 +217,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 +275,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 +299,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 +325,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 +376,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 +395,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 +460,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 +523,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();
@@ -574,7 +594,8 @@
}
// Util: write out our new backup state file
- private void writeStateFile(List<PackageInfo> pkgs, ParcelFileDescriptor stateFile) {
+ @VisibleForTesting
+ static void writeStateFile(List<PackageInfo> pkgs, ParcelFileDescriptor stateFile) {
FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor());
BufferedOutputStream outbuf = new BufferedOutputStream(outstream);
DataOutputStream out = new DataOutputStream(outbuf);
@@ -640,10 +661,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 +680,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 +702,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 +731,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 +773,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 +794,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 +816,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 b339631..e98e1ba 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;
@@ -239,6 +240,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);
@@ -256,6 +262,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
@@ -392,8 +413,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 {
@@ -401,8 +422,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 {
@@ -410,6 +431,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>
@@ -788,6 +818,10 @@
return mActiveIndex;
}
+ public boolean isOutgoingEmpty() {
+ return mOutgoingBroadcasts.isEmpty();
+ }
+
public boolean isEmpty() {
return mPending.isEmpty() && mPendingUrgent.isEmpty() && mPendingOffload.isEmpty();
}
@@ -1457,7 +1491,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(" ");
@@ -1468,6 +1502,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);
}
@@ -1539,6 +1579,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 98a1ea5..5521381 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -93,6 +93,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;
@@ -285,6 +286,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);
@@ -333,9 +337,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: {
@@ -436,7 +438,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);
}
}
@@ -760,6 +763,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");
@@ -1638,6 +1656,8 @@
"mBroadcastConsumerDeferClear");
};
+ final BroadcastRecordConsumer mBroadcastRecordConsumerEnqueue = this::enqueueBroadcastLocked;
+
/**
* Verify that all known {@link #mProcessQueues} are in the state tested by
* the given {@link Predicate}.
@@ -1934,8 +1954,9 @@
}
}
+ @VisibleForTesting
@GuardedBy("mService")
- private boolean isProcessFreezable(@Nullable ProcessRecord app) {
+ boolean isProcessFreezable(@Nullable ProcessRecord app) {
if (app == null) {
return false;
}
@@ -1960,16 +1981,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/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 982076d..91b64f8 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -80,6 +80,7 @@
sSecureSettingToTypeMap.put(Settings.Secure.MULTI_PRESS_TIMEOUT, int.class);
sSecureSettingToTypeMap.put(Settings.Secure.KEY_REPEAT_TIMEOUT_MS, int.class);
sSecureSettingToTypeMap.put(Settings.Secure.KEY_REPEAT_DELAY_MS, int.class);
+ sSecureSettingToTypeMap.put(Settings.Secure.STYLUS_POINTER_ICON_ENABLED, int.class);
// add other secure settings here...
sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class);
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 38051c1..177c345 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -19,8 +19,9 @@
import static android.Manifest.permission.CONTROL_DEVICE_STATE;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.hardware.devicestate.DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
-import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
@@ -75,6 +76,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
@@ -109,6 +111,12 @@
private static final String TAG = "DeviceStateManagerService";
private static final boolean DEBUG = false;
+ /** {@link DeviceState} to model an invalid device state */
+ // TODO(b/328314031): Investigate how we can remove this constant
+ private static final DeviceState INVALID_DEVICE_STATE = new DeviceState(
+ new DeviceState.Configuration.Builder(INVALID_DEVICE_STATE_IDENTIFIER,
+ "INVALID").build());
+
private final Object mLock = new Object();
// Handler on the {@link DisplayThread} used to dispatch calls to the policy and to registered
// callbacks though its handler (mHandler). Provides a guarantee of callback order when
@@ -354,16 +362,22 @@
}
/** Returns the list of currently supported device states. */
- DeviceState[] getSupportedStates() {
+ List<DeviceState> getSupportedStates() {
synchronized (mLock) {
- DeviceState[] supportedStates = new DeviceState[mDeviceStates.size()];
- for (int i = 0; i < supportedStates.length; i++) {
- supportedStates[i] = mDeviceStates.valueAt(i);
- }
- return supportedStates;
+ return getSupportedStatesLocked();
}
}
+ /** Returns the list of currently supported device states */
+ @GuardedBy("mLock")
+ private List<DeviceState> getSupportedStatesLocked() {
+ List<DeviceState> supportedStates = new ArrayList<>(mDeviceStates.size());
+ for (int i = 0; i < mDeviceStates.size(); i++) {
+ supportedStates.add(i, mDeviceStates.valueAt(i));
+ }
+ return supportedStates;
+ }
+
/** Returns the list of currently supported device state identifiers. */
private int[] getSupportedStateIdentifiersLocked() {
int[] supportedStates = new int[mDeviceStates.size()];
@@ -375,20 +389,46 @@
/**
* Returns the current {@link DeviceStateInfo} of the device. If there has been no base state
- * or committed state provided, {@link DeviceStateManager#INVALID_DEVICE_STATE} will be returned
+ * or committed state provided, {@link #INVALID_DEVICE_STATE} will be returned
* respectively. The supported states will always be included.
*
*/
@GuardedBy("mLock")
@NonNull
private DeviceStateInfo getDeviceStateInfoLocked() {
- final int[] supportedStates = getSupportedStateIdentifiersLocked();
- final int baseState =
- mBaseState.isPresent() ? mBaseState.get().getIdentifier() : INVALID_DEVICE_STATE;
- final int currentState = mCommittedState.isPresent() ? mCommittedState.get().getIdentifier()
- : INVALID_DEVICE_STATE;
+ final List<DeviceState> supportedStates = getSupportedStatesLocked();
+ final DeviceState baseState = mBaseState.orElse(null);
+ final DeviceState currentState = mCommittedState.orElse(null);
- return new DeviceStateInfo(supportedStates, baseState, currentState);
+ return new DeviceStateInfo(supportedStates,
+ baseState != null ? baseState : INVALID_DEVICE_STATE,
+ createMergedDeviceState(currentState, baseState));
+ }
+
+ /**
+ * Returns a {@link DeviceState} with the combined properties of the current system state, as
+ * well as the physical property that corresponds to the base state (physical hardware state) of
+ * the device.
+ */
+ private DeviceState createMergedDeviceState(@Nullable DeviceState committedState,
+ @Nullable DeviceState baseState) {
+ if (committedState == null) {
+ return INVALID_DEVICE_STATE;
+ }
+
+ Set<@DeviceState.DeviceStateProperties Integer> systemProperties =
+ committedState.getConfiguration().getSystemProperties();
+
+ Set<@DeviceState.DeviceStateProperties Integer> physicalProperties =
+ baseState != null ? baseState.getConfiguration().getPhysicalProperties()
+ : Collections.emptySet();
+
+ DeviceState.Configuration deviceStateConfiguration = new DeviceState.Configuration.Builder(
+ committedState.getIdentifier(), committedState.getName())
+ .setSystemProperties(systemProperties)
+ .setPhysicalProperties(physicalProperties)
+ .build();
+ return new DeviceState(deviceStateConfiguration);
}
@VisibleForTesting
@@ -408,7 +448,7 @@
mDeviceStates.clear();
for (int i = 0; i < supportedDeviceStates.length; i++) {
DeviceState state = supportedDeviceStates[i];
- if (state.hasFlag(FLAG_CANCEL_OVERRIDE_REQUESTS)) {
+ if (state.hasProperty(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS)) {
hasTerminalDeviceState = true;
}
mDeviceStates.put(state.getIdentifier(), state);
@@ -436,7 +476,7 @@
private void setRearDisplayStateLocked() {
int rearDisplayIdentifier = getContext().getResources().getInteger(
R.integer.config_deviceStateRearDisplay);
- if (rearDisplayIdentifier != INVALID_DEVICE_STATE) {
+ if (rearDisplayIdentifier != INVALID_DEVICE_STATE_IDENTIFIER) {
mRearDisplayState = mDeviceStates.get(rearDisplayIdentifier);
}
}
@@ -453,7 +493,7 @@
* Returns the {@link DeviceState} with the supplied {@code identifier}, or {@code null} if
* there is no device state with the identifier.
*/
- @Nullable
+ @NonNull
private Optional<DeviceState> getStateLocked(int identifier) {
return Optional.ofNullable(mDeviceStates.get(identifier));
}
@@ -468,7 +508,7 @@
private void setBaseState(int identifier) {
synchronized (mLock) {
final Optional<DeviceState> baseStateOptional = getStateLocked(identifier);
- if (!baseStateOptional.isPresent()) {
+ if (baseStateOptional.isEmpty()) {
throw new IllegalArgumentException("Base state is not supported");
}
@@ -484,7 +524,7 @@
}
mBaseState = Optional.of(baseState);
- if (baseState.hasFlag(FLAG_CANCEL_OVERRIDE_REQUESTS)) {
+ if (baseState.hasProperty(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS)) {
mOverrideRequestController.cancelOverrideRequest();
}
mOverrideRequestController.handleBaseStateChanged(identifier);
@@ -1023,7 +1063,7 @@
}
private Set<Integer> readFoldedStates() {
- Set<Integer> foldedStates = new HashSet();
+ Set<Integer> foldedStates = new HashSet<>();
int[] mFoldedStatesArray = getContext().getResources().getIntArray(
com.android.internal.R.array.config_foldedDeviceStates);
for (int i = 0; i < mFoldedStatesArray.length; i++) {
@@ -1338,7 +1378,7 @@
}
int identifier = mActiveOverride.get().getRequestedStateIdentifier();
DeviceState deviceState = mDeviceStates.get(identifier);
- return deviceState.hasFlag(DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
+ return deviceState.hasProperty(PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
}
private class OverrideRequestScreenObserver implements
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
index 02c9bb3..97913de3 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
@@ -25,7 +25,7 @@
import android.os.ShellCommand;
import java.io.PrintWriter;
-import java.util.Arrays;
+import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -177,17 +177,18 @@
}
private int runPrintStates(PrintWriter pw) {
- DeviceState[] states = mService.getSupportedStates();
+ List<DeviceState> states = mService.getSupportedStates();
pw.print("Supported states: [\n");
- for (int i = 0; i < states.length; i++) {
- pw.print(" " + states[i] + ",\n");
+ for (int i = 0; i < states.size(); i++) {
+ pw.print(" " + states.get(i) + ",\n");
}
pw.println("]");
return 0;
}
private int runPrintStatesSimple(PrintWriter pw) {
- pw.print(Arrays.stream(mService.getSupportedStates())
+ pw.print(mService.getSupportedStates()
+ .stream()
.map(DeviceState::getIdentifier)
.map(Object::toString)
.collect(Collectors.joining(",")));
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateNotificationController.java b/services/core/java/com/android/server/devicestate/DeviceStateNotificationController.java
index f9aefd0..46478c1 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateNotificationController.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateNotificationController.java
@@ -323,7 +323,7 @@
for (int i = 0; i < stateIdentifiers.length; i++) {
int identifier = stateIdentifiers[i];
- if (identifier == DeviceStateManager.INVALID_DEVICE_STATE) {
+ if (identifier == DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER) {
continue;
}
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
index b865c1d9..8d07609 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
@@ -28,8 +28,8 @@
import java.lang.annotation.RetentionPolicy;
/**
- * Responsible for providing the set of supported {@link DeviceState device states} as well as the
- * current device state.
+ * Responsible for providing the set of supported {@link DeviceState.Configuration device states} as
+ * well as the current device state.
*
* @see DeviceStatePolicy
*/
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequest.java b/services/core/java/com/android/server/devicestate/OverrideRequest.java
index d92629f..df7301e 100644
--- a/services/core/java/com/android/server/devicestate/OverrideRequest.java
+++ b/services/core/java/com/android/server/devicestate/OverrideRequest.java
@@ -72,8 +72,9 @@
@Retention(RetentionPolicy.SOURCE)
public @interface OverrideRequestType {}
- OverrideRequest(IBinder token, int pid, int uid, @NonNull DeviceState requestedState,
- @DeviceStateRequest.RequestFlags int flags, @OverrideRequestType int requestType) {
+ OverrideRequest(IBinder token, int pid, int uid,
+ @NonNull DeviceState requestedState, @DeviceStateRequest.RequestFlags int flags,
+ @OverrideRequestType int requestType) {
mToken = token;
mPid = pid;
mUid = uid;
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequestController.java b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
index 6c3fd83d..041ab3a 100644
--- a/services/core/java/com/android/server/devicestate/OverrideRequestController.java
+++ b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
@@ -205,8 +205,8 @@
}
if (mRequest != null && mRequest.getPid() == pid) {
- if (mRequest.getRequestedDeviceState().hasFlag(
- DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)) {
+ if (mRequest.getRequestedDeviceState().hasProperty(
+ DeviceState.PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)) {
cancelCurrentRequestLocked();
return;
}
diff --git a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
index e54f30f..146810f 100644
--- a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
+++ b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
@@ -51,7 +51,7 @@
class DeviceStateToLayoutMap {
private static final String TAG = "DeviceStateToLayoutMap";
- public static final int STATE_DEFAULT = DeviceStateManager.INVALID_DEVICE_STATE;
+ public static final int STATE_DEFAULT = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
// Direction of the display relative to the default display, whilst in this state
private static final int POSITION_UNKNOWN = Layout.Display.POSITION_UNKNOWN;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index ad89444..4ef3393 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -5021,7 +5021,7 @@
*/
class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
// Base state corresponds to the physical state of the device
- private int mBaseState = DeviceStateManager.INVALID_DEVICE_STATE;
+ private int mBaseState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
@Override
public void onStateChanged(int deviceState) {
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 2e8de31..3452e0f 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -192,9 +192,10 @@
private final DisplayIdProducer mIdProducer = (isDefault) ->
isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++;
private Layout mCurrentLayout = null;
- private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
- private int mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
- private int mDeviceStateToBeAppliedAfterBoot = DeviceStateManager.INVALID_DEVICE_STATE;
+ private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
+ private int mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
+ private int mDeviceStateToBeAppliedAfterBoot =
+ DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
private boolean mBootCompleted = false;
private boolean mInteractive;
private final DisplayManagerFlags mFlags;
@@ -460,7 +461,7 @@
// temporarily turned off.
resetLayoutLocked(mDeviceState, state, /* transitionValue= */ true);
mPendingDeviceState = state;
- mDeviceStateToBeAppliedAfterBoot = DeviceStateManager.INVALID_DEVICE_STATE;
+ mDeviceStateToBeAppliedAfterBoot = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
final boolean wakeDevice = shouldDeviceBeWoken(mPendingDeviceState, mDeviceState,
mInteractive, mBootCompleted);
final boolean sleepDevice = shouldDeviceBePutToSleep(mPendingDeviceState, mDeviceState,
@@ -510,7 +511,8 @@
void onBootCompleted() {
synchronized (mSyncRoot) {
mBootCompleted = true;
- if (mDeviceStateToBeAppliedAfterBoot != DeviceStateManager.INVALID_DEVICE_STATE) {
+ if (mDeviceStateToBeAppliedAfterBoot
+ != DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER) {
setDeviceStateLocked(mDeviceStateToBeAppliedAfterBoot,
/* isOverrideActive= */ false);
}
@@ -568,7 +570,7 @@
@VisibleForTesting
boolean shouldDeviceBePutToSleep(int pendingState, int currentState, boolean isOverrideActive,
boolean isInteractive, boolean isBootCompleted) {
- return currentState != DeviceStateManager.INVALID_DEVICE_STATE
+ return currentState != DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER
&& mDeviceStatesOnWhichToSleep.get(pendingState)
&& !mDeviceStatesOnWhichToSleep.get(currentState)
&& !isOverrideActive
@@ -598,13 +600,13 @@
private void transitionToPendingStateLocked() {
resetLayoutLocked(mDeviceState, mPendingDeviceState, /* transitionValue= */ false);
mDeviceState = mPendingDeviceState;
- mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
+ mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
applyLayoutLocked();
updateLogicalDisplaysLocked();
}
private void finishStateTransitionLocked(boolean force) {
- if (mPendingDeviceState == DeviceStateManager.INVALID_DEVICE_STATE) {
+ if (mPendingDeviceState == DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER) {
return;
}
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index c02d524..a1341b7 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -258,6 +258,7 @@
}
private void updateStylusPointerIconEnabled() {
- mNative.setStylusPointerIconEnabled(InputSettings.isStylusPointerIconEnabled(mContext));
+ mNative.setStylusPointerIconEnabled(
+ InputSettings.isStylusPointerIconEnabled(mContext, true /* forceReloadSetting */));
}
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 251e69f..996477d 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1247,6 +1247,14 @@
*/
private boolean mImePackageAppeared = false;
+ /**
+ * Remembers package names passed to {@link #onPackageDataCleared(String, int)}.
+ *
+ * <p>This field must be accessed only from callback methods in {@link PackageMonitor},
+ * which should be bound to {@link #getRegisteredHandler()}.</p>
+ */
+ private ArrayList<String> mDataClearedPackages = new ArrayList<>();
+
@GuardedBy("ImfLock.class")
void clearKnownImePackageNamesLocked() {
mKnownImePackageNames.clear();
@@ -1350,36 +1358,8 @@
@Override
public void onPackageDataCleared(String packageName, int uid) {
- final int userId = getChangingUserId();
- synchronized (ImfLock.class) {
- final boolean isCurrentUser = (userId == mSettings.getUserId());
- final AdditionalSubtypeMap additionalSubtypeMap =
- AdditionalSubtypeMapRepository.get(userId);
- final InputMethodSettings settings;
- if (isCurrentUser) {
- settings = mSettings;
- } else {
- settings = queryInputMethodServicesInternal(mContext, userId,
- additionalSubtypeMap, DirectBootAwareness.AUTO);
- }
-
- // Note that one package may implement multiple IMEs.
- final ArrayList<String> changedImes = new ArrayList<>();
- for (InputMethodInfo imi : settings.getMethodList()) {
- if (imi.getPackageName().equals(packageName)) {
- changedImes.add(imi.getId());
- }
- }
- final AdditionalSubtypeMap newMap =
- additionalSubtypeMap.cloneWithRemoveOrSelf(changedImes);
- if (newMap != additionalSubtypeMap) {
- AdditionalSubtypeMapRepository.putAndSave(userId, newMap,
- settings.getMethodMap());
- }
- if (!changedImes.isEmpty()) {
- mChangedPackages.add(packageName);
- }
- }
+ mChangedPackages.add(packageName);
+ mDataClearedPackages.add(packageName);
}
@Override
@@ -1391,6 +1371,7 @@
private void clearPackageChangeState() {
// No need to lock them because we access these fields only on getRegisteredHandler().
mChangedPackages.clear();
+ mDataClearedPackages.clear();
mImePackageAppeared = false;
}
@@ -1421,7 +1402,7 @@
synchronized (ImfLock.class) {
final int userId = getChangingUserId();
final boolean isCurrentUser = (userId == mSettings.getUserId());
- AdditionalSubtypeMap additionalSubtypeMap =
+ final AdditionalSubtypeMap additionalSubtypeMap =
AdditionalSubtypeMapRepository.get(userId);
final InputMethodSettings settings;
if (isCurrentUser) {
@@ -1434,6 +1415,8 @@
InputMethodInfo curIm = null;
String curInputMethodId = settings.getSelectedInputMethod();
final List<InputMethodInfo> methodList = settings.getMethodList();
+
+ final ArrayList<String> imesToClearAdditionalSubtypes = new ArrayList<>();
final int numImes = methodList.size();
for (int i = 0; i < numImes; i++) {
InputMethodInfo imi = methodList.get(i);
@@ -1441,6 +1424,9 @@
if (imiId.equals(curInputMethodId)) {
curIm = imi;
}
+ if (mDataClearedPackages.contains(imi.getPackageName())) {
+ imesToClearAdditionalSubtypes.add(imiId);
+ }
int change = isPackageDisappearing(imi.getPackageName());
if (change == PACKAGE_TEMPORARY_CHANGE || change == PACKAGE_PERMANENT_CHANGE) {
Slog.i(TAG, "Input method uninstalled, disabling: " + imi.getComponent());
@@ -1455,14 +1441,22 @@
} else if (change == PACKAGE_UPDATING) {
Slog.i(TAG, "Input method reinstalling, clearing additional subtypes: "
+ imi.getComponent());
- additionalSubtypeMap =
- additionalSubtypeMap.cloneWithRemoveOrSelf(imi.getId());
- AdditionalSubtypeMapRepository.putAndSave(userId,
- additionalSubtypeMap, settings.getMethodMap());
+ imesToClearAdditionalSubtypes.add(imiId);
}
}
- if (!isCurrentUser || !shouldRebuildInputMethodListLocked()) {
+ // Clear additional subtypes as a batch operation.
+ final AdditionalSubtypeMap newAdditionalSubtypeMap =
+ additionalSubtypeMap.cloneWithRemoveOrSelf(imesToClearAdditionalSubtypes);
+ final boolean additionalSubtypeChanged =
+ (newAdditionalSubtypeMap != additionalSubtypeMap);
+ if (additionalSubtypeChanged) {
+ AdditionalSubtypeMapRepository.putAndSave(userId, newAdditionalSubtypeMap,
+ settings.getMethodMap());
+ }
+
+ if (!isCurrentUser
+ || !(additionalSubtypeChanged || shouldRebuildInputMethodListLocked())) {
return;
}
@@ -1932,7 +1926,7 @@
}
}, "Lazily initialize IMMS#mImeDrawsImeNavBarRes");
- mMyPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
+ mMyPackageMonitor.register(mContext, UserHandle.ALL, mHandler);
mSettingsObserver.registerContentObserverLocked(currentUserId);
final IntentFilter broadcastFilterForAllUsers = new IntentFilter();
@@ -5023,6 +5017,14 @@
.getSortedInputMethodAndSubtypeList(
showAuxSubtypes, isScreenLocked, true /* forImeMenu */,
mContext, mSettings.getMethodMap(), mSettings.getUserId());
+ if (imList.isEmpty()) {
+ Slog.w(TAG, "Show switching menu failed, imList is empty,"
+ + " showAuxSubtypes: " + showAuxSubtypes
+ + " isScreenLocked: " + isScreenLocked
+ + " userId: " + mSettings.getUserId());
+ return false;
+ }
+
mMenuController.showInputMethodMenuLocked(showAuxSubtypes, displayId,
lastInputMethodId, lastInputMethodSubtypeId, imList);
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 6ed4848..3bd0a9f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -80,10 +80,6 @@
final int userId = mService.getCurrentImeUserIdLocked();
- if (imList.isEmpty()) {
- return;
- }
-
hideInputMethodMenuLocked();
if (preferredInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
index 1379d16..1c958a9 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -167,6 +167,7 @@
final ArrayList<InputMethodInfo> imis = settings.getEnabledInputMethodList();
if (imis.isEmpty()) {
+ Slog.w(TAG, "Enabled input method list is empty.");
return new ArrayList<>();
}
if (isScreenLocked && includeAuxiliarySubtypes) {
diff --git a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
index 9caf5cf..396192e 100644
--- a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
+++ b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
@@ -101,7 +101,6 @@
}
private void offloadInner(Runnable r) {
- boolean useThrowingRunnable = r instanceof ThrowingRunnable;
final long identity = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> {
@@ -110,14 +109,9 @@
Binder.restoreCallingIdentity(identity);
try {
try {
- if (useThrowingRunnable) {
- ((ThrowingRunnable) r).runOrThrow();
- } else {
- r.run();
- }
+ r.run();
} catch (Exception e) {
- Slog.e(TAG, "Error in async call", e);
- throw ExceptionUtils.propagate(e);
+ Slog.e(TAG, "Error in async IMMS call", e);
}
} finally {
Binder.restoreCallingIdentity(inner);
diff --git a/services/core/java/com/android/server/location/contexthub/OWNERS b/services/core/java/com/android/server/location/contexthub/OWNERS
index 90c2330..c62e323 100644
--- a/services/core/java/com/android/server/location/contexthub/OWNERS
+++ b/services/core/java/com/android/server/location/contexthub/OWNERS
@@ -1,3 +1,3 @@
-arthuri@google.com
bduddie@google.com
+matthewsedam@google.com
stange@google.com
diff --git a/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java b/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
index f60f55c..7acc3ef 100644
--- a/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
+++ b/services/core/java/com/android/server/media/metrics/MediaMetricsManagerService.java
@@ -374,6 +374,7 @@
event.getInputMediaItemInfos().isEmpty()
? EMPTY_MEDIA_ITEM_INFO
: event.getInputMediaItemInfos().get(0);
+ @MediaItemInfo.DataType long inputDataTypes = inputMediaItemInfo.getDataTypes();
String inputAudioSampleMimeType =
getFilteredFirstMimeType(
inputMediaItemInfo.getSampleMimeTypes(), AUDIO_MIME_TYPE_PREFIX);
@@ -396,6 +397,7 @@
event.getOutputMediaItemInfo() == null
? EMPTY_MEDIA_ITEM_INFO
: event.getOutputMediaItemInfo();
+ @MediaItemInfo.DataType long outputDataTypes = outputMediaItemInfo.getDataTypes();
String outputAudioSampleMimeType =
getFilteredFirstMimeType(
outputMediaItemInfo.getSampleMimeTypes(), AUDIO_MIME_TYPE_PREFIX);
@@ -415,6 +417,7 @@
!outputCodecNames.isEmpty() ? outputCodecNames.get(0) : "";
String outputSecondCodecName =
outputCodecNames.size() > 1 ? outputCodecNames.get(1) : "";
+ @EditingEndedEvent.OperationType long operationTypes = event.getOperationTypes();
StatsEvent statsEvent =
StatsEvent.newBuilder()
.setAtomId(798)
@@ -423,11 +426,63 @@
.writeFloat(event.getFinalProgressPercent())
.writeInt(event.getErrorCode())
.writeLong(event.getTimeSinceCreatedMillis())
+ .writeBoolean(
+ (operationTypes
+ & EditingEndedEvent
+ .OPERATION_TYPE_VIDEO_TRANSCODE)
+ != 0)
+ .writeBoolean(
+ (operationTypes
+ & EditingEndedEvent
+ .OPERATION_TYPE_AUDIO_TRANSCODE)
+ != 0)
+ .writeBoolean(
+ (operationTypes & EditingEndedEvent.OPERATION_TYPE_VIDEO_EDIT)
+ != 0)
+ .writeBoolean(
+ (operationTypes & EditingEndedEvent.OPERATION_TYPE_AUDIO_EDIT)
+ != 0)
+ .writeBoolean(
+ (operationTypes
+ & EditingEndedEvent
+ .OPERATION_TYPE_VIDEO_TRANSMUX)
+ != 0)
+ .writeBoolean(
+ (operationTypes
+ & EditingEndedEvent
+ .OPERATION_TYPE_AUDIO_TRANSMUX)
+ != 0)
+ .writeBoolean(
+ (operationTypes & EditingEndedEvent.OPERATION_TYPE_PAUSED) != 0)
+ .writeBoolean(
+ (operationTypes & EditingEndedEvent.OPERATION_TYPE_RESUMED)
+ != 0)
.writeString(getFilteredLibraryName(event.getExporterName()))
.writeString(getFilteredLibraryName(event.getMuxerName()))
.writeInt(getThroughputFps(event))
.writeInt(event.getInputMediaItemInfos().size())
.writeInt(inputMediaItemInfo.getSourceType())
+ .writeBoolean((inputDataTypes & MediaItemInfo.DATA_TYPE_IMAGE) != 0)
+ .writeBoolean((inputDataTypes & MediaItemInfo.DATA_TYPE_VIDEO) != 0)
+ .writeBoolean((inputDataTypes & MediaItemInfo.DATA_TYPE_AUDIO) != 0)
+ .writeBoolean((inputDataTypes & MediaItemInfo.DATA_TYPE_METADATA) != 0)
+ .writeBoolean((inputDataTypes & MediaItemInfo.DATA_TYPE_DEPTH) != 0)
+ .writeBoolean((inputDataTypes & MediaItemInfo.DATA_TYPE_GAIN_MAP) != 0)
+ .writeBoolean(
+ (inputDataTypes & MediaItemInfo.DATA_TYPE_HIGH_FRAME_RATE) != 0)
+ .writeBoolean(
+ (inputDataTypes
+ & MediaItemInfo
+ .DATA_TYPE_SPEED_SETTING_CUE_POINTS)
+ != 0)
+ .writeBoolean((inputDataTypes & MediaItemInfo.DATA_TYPE_GAPLESS) != 0)
+ .writeBoolean(
+ (inputDataTypes & MediaItemInfo.DATA_TYPE_SPATIAL_AUDIO) != 0)
+ .writeBoolean(
+ (inputDataTypes
+ & MediaItemInfo
+ .DATA_TYPE_HIGH_DYNAMIC_RANGE_VIDEO)
+ != 0)
.writeLong(
getBucketedDurationMillis(
inputMediaItemInfo.getDurationMillis()))
@@ -443,6 +498,7 @@
getFilteredAudioSampleRateHz(
inputMediaItemInfo.getAudioSampleRateHz()))
.writeInt(inputMediaItemInfo.getAudioChannelCount())
+ .writeLong(inputMediaItemInfo.getAudioSampleCount())
.writeInt(inputVideoSize.getWidth())
.writeInt(inputVideoSize.getHeight())
.writeInt(inputVideoResolution)
@@ -456,6 +512,28 @@
.writeInt(getVideoFrameRateEnum(inputMediaItemInfo.getVideoFrameRate()))
.writeString(inputFirstCodecName)
.writeString(inputSecondCodecName)
+ .writeBoolean((outputDataTypes & MediaItemInfo.DATA_TYPE_IMAGE) != 0)
+ .writeBoolean((outputDataTypes & MediaItemInfo.DATA_TYPE_VIDEO) != 0)
+ .writeBoolean((outputDataTypes & MediaItemInfo.DATA_TYPE_AUDIO) != 0)
+ .writeBoolean((outputDataTypes & MediaItemInfo.DATA_TYPE_METADATA) != 0)
+ .writeBoolean((outputDataTypes & MediaItemInfo.DATA_TYPE_DEPTH) != 0)
+ .writeBoolean((outputDataTypes & MediaItemInfo.DATA_TYPE_GAIN_MAP) != 0)
+ .writeBoolean(
+ (outputDataTypes & MediaItemInfo.DATA_TYPE_HIGH_FRAME_RATE)
+ != 0)
+ .writeBoolean(
+ (outputDataTypes
+ & MediaItemInfo
+ .DATA_TYPE_SPEED_SETTING_CUE_POINTS)
+ != 0)
+ .writeBoolean((outputDataTypes & MediaItemInfo.DATA_TYPE_GAPLESS) != 0)
+ .writeBoolean(
+ (outputDataTypes & MediaItemInfo.DATA_TYPE_SPATIAL_AUDIO) != 0)
+ .writeBoolean(
+ (outputDataTypes
+ & MediaItemInfo
+ .DATA_TYPE_HIGH_DYNAMIC_RANGE_VIDEO)
+ != 0)
.writeLong(
getBucketedDurationMillis(
outputMediaItemInfo.getDurationMillis()))
@@ -471,6 +549,7 @@
getFilteredAudioSampleRateHz(
outputMediaItemInfo.getAudioSampleRateHz()))
.writeInt(outputMediaItemInfo.getAudioChannelCount())
+ .writeLong(outputMediaItemInfo.getAudioSampleCount())
.writeInt(outputVideoSize.getWidth())
.writeInt(outputVideoSize.getHeight())
.writeInt(outputVideoResolution)
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 18b495b..97ce77c 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -340,6 +340,8 @@
static final String TAG = NetworkPolicyLogger.TAG;
private static final boolean LOGD = NetworkPolicyLogger.LOGD;
private static final boolean LOGV = NetworkPolicyLogger.LOGV;
+ // TODO: b/304347838 - Remove once the feature is in staging.
+ private static final boolean ALWAYS_RESTRICT_BACKGROUND_NETWORK = false;
/**
* No opportunistic quota could be calculated from user data plan or data settings.
@@ -1068,7 +1070,8 @@
}
// The flag is boot-stable.
- mBackgroundNetworkRestricted = Flags.networkBlockedForTopSleepingAndAbove();
+ mBackgroundNetworkRestricted = ALWAYS_RESTRICT_BACKGROUND_NETWORK
+ && Flags.networkBlockedForTopSleepingAndAbove();
if (mBackgroundNetworkRestricted) {
// Firewall rules and UidBlockedState will get updated in
// updateRulesForGlobalChangeAL below.
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 59d6219..e35a169 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2710,7 +2710,8 @@
} catch (java.io.IOException e) {
mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
+ PackageManagerService.reportSettingsProblem(Log.ERROR,
+ "Error reading stopped packages: " + e);
Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
e);
diff --git a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
index 1b220a0..453c6ef 100644
--- a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
+++ b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
@@ -16,7 +16,7 @@
package com.android.server.policy;
-import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
import android.annotation.NonNull;
@@ -45,9 +45,9 @@
import com.android.server.input.InputManagerInternal;
import com.android.server.policy.devicestate.config.Conditions;
import com.android.server.policy.devicestate.config.DeviceStateConfig;
-import com.android.server.policy.devicestate.config.Flags;
import com.android.server.policy.devicestate.config.LidSwitchCondition;
import com.android.server.policy.devicestate.config.NumericRange;
+import com.android.server.policy.devicestate.config.Properties;
import com.android.server.policy.devicestate.config.SensorCondition;
import com.android.server.policy.devicestate.config.XmlParser;
@@ -63,8 +63,10 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.BooleanSupplier;
import javax.xml.datatype.DatatypeConfigurationException;
@@ -94,21 +96,49 @@
private static final BooleanSupplier FALSE_BOOLEAN_SUPPLIER = () -> false;
@VisibleForTesting
- static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(MINIMUM_DEVICE_STATE_IDENTIFIER,
- "DEFAULT", 0 /* flags */);
+ static final DeviceState DEFAULT_DEVICE_STATE =
+ new DeviceState(new DeviceState.Configuration.Builder(MINIMUM_DEVICE_STATE_IDENTIFIER,
+ "DEFAULT").build());
private static final String VENDOR_CONFIG_FILE_PATH = "etc/devicestate/";
private static final String DATA_CONFIG_FILE_PATH = "system/devicestate/";
private static final String CONFIG_FILE_NAME = "device_state_configuration.xml";
- private static final String FLAG_CANCEL_OVERRIDE_REQUESTS = "FLAG_CANCEL_OVERRIDE_REQUESTS";
- private static final String FLAG_APP_INACCESSIBLE = "FLAG_APP_INACCESSIBLE";
- private static final String FLAG_EMULATED_ONLY = "FLAG_EMULATED_ONLY";
- private static final String FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP =
- "FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP";
- private static final String FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL =
- "FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL";
- private static final String FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE =
- "FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE";
+ private static final String PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED =
+ "com.android.server.policy.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED";
+ private static final String PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN =
+ "com.android.server.policy.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN";
+ private static final String PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN =
+ "com.android.server.policy.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN";
+ private static final String PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS =
+ "com.android.server.policy.PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS";
+ private static final String PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP =
+ "com.android.server.policy.PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP";
+ private static final String PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL =
+ "com.android.server.policy.PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL";
+ private static final String PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE =
+ "com.android.server.policy.PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE";
+ private static final String PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST =
+ "com.android.server.policy.PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST";
+ private static final String PROPERTY_APP_INACCESSIBLE =
+ "com.android.server.policy.PROPERTY_APP_INACCESSIBLE";
+ private static final String PROPERTY_EMULATED_ONLY =
+ "com.android.server.policy.PROPERTY_EMULATED_ONLY";
+ private static final String PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY =
+ "com.android.server.policy.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY";
+ private static final String PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY =
+ "com.android.server.policy.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY";
+ private static final String PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP =
+ "com.android.server.policy.PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP";
+ private static final String PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE =
+ "com.android.server.policy.PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE";
+ private static final String PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY =
+ "com.android.server.policy.PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY";
+ private static final String PROPERTY_FEATURE_REAR_DISPLAY =
+ "com.android.server.policy.PROPERTY_FEATURE_REAR_DISPLAY";
+ private static final String PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT =
+ "com.android.server.policy.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT";
+
+
/** Interface that allows reading the device state configuration. */
interface ReadableConfig {
@@ -149,40 +179,25 @@
final int state = stateConfig.getIdentifier().intValue();
final String name = stateConfig.getName() == null ? "" : stateConfig.getName();
- int flags = 0;
- final Flags configFlags = stateConfig.getFlags();
+ Set<@DeviceState.DeviceStateProperties Integer> systemProperties =
+ new HashSet<>();
+ Set<@DeviceState.DeviceStateProperties Integer> physicalProperties =
+ new HashSet<>();
+ final Properties configFlags = stateConfig.getProperties();
if (configFlags != null) {
- List<String> configFlagStrings = configFlags.getFlag();
- for (int i = 0; i < configFlagStrings.size(); i++) {
- final String configFlagString = configFlagStrings.get(i);
- switch (configFlagString) {
- case FLAG_CANCEL_OVERRIDE_REQUESTS:
- flags |= DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
- break;
- case FLAG_APP_INACCESSIBLE:
- flags |= DeviceState.FLAG_APP_INACCESSIBLE;
- break;
- case FLAG_EMULATED_ONLY:
- flags |= DeviceState.FLAG_EMULATED_ONLY;
- break;
- case FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP:
- flags |= DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP;
- break;
- case FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL:
- flags |= DeviceState
- .FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL;
- break;
- case FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE:
- flags |= DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE;
- default:
- Slog.w(TAG, "Parsed unknown flag with name: "
- + configFlagString);
- break;
- }
+ List<String> configPropertyStrings = configFlags.getProperty();
+ for (int i = 0; i < configPropertyStrings.size(); i++) {
+ final String configPropertyString = configPropertyStrings.get(i);
+ addPropertyByString(configPropertyString, systemProperties,
+ physicalProperties);
}
}
-
- deviceStateList.add(new DeviceState(state, name, flags));
+ DeviceState.Configuration deviceStateConfiguration =
+ new DeviceState.Configuration.Builder(state, name)
+ .setSystemProperties(systemProperties)
+ .setPhysicalProperties(physicalProperties)
+ .build();
+ deviceStateList.add(new DeviceState(deviceStateConfiguration));
final Conditions condition = stateConfig.getConditions();
conditionsList.add(condition);
@@ -190,13 +205,88 @@
}
}
- if (deviceStateList.size() == 0) {
+ if (deviceStateList.isEmpty()) {
deviceStateList.add(DEFAULT_DEVICE_STATE);
conditionsList.add(null);
}
return new DeviceStateProviderImpl(context, deviceStateList, conditionsList);
}
+ private static void addPropertyByString(String propertyString,
+ Set<@DeviceState.SystemDeviceStateProperties Integer> systemProperties,
+ Set<@DeviceState.PhysicalDeviceStateProperties Integer> physicalProperties) {
+ switch (propertyString) {
+ // Look for the physical hardware properties first
+ case PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED:
+ physicalProperties.add(
+ DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED);
+ break;
+ case PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN:
+ physicalProperties.add(
+ DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN);
+ break;
+ case PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN:
+ physicalProperties.add(
+ DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN);
+ break;
+ case PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS:
+ systemProperties.add(
+ DeviceState.PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS);
+ break;
+ case PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP:
+ systemProperties.add(
+ DeviceState.PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
+ break;
+ case PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL:
+ systemProperties.add(
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL);
+ break;
+ case PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE:
+ systemProperties.add(
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE);
+ break;
+ case PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST:
+ systemProperties.add(
+ DeviceState.PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST);
+ break;
+ case PROPERTY_APP_INACCESSIBLE:
+ systemProperties.add(DeviceState.PROPERTY_APP_INACCESSIBLE);
+ break;
+ case PROPERTY_EMULATED_ONLY:
+ systemProperties.add(DeviceState.PROPERTY_EMULATED_ONLY);
+ break;
+ case PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY:
+ systemProperties.add(
+ DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY);
+ break;
+ case PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY:
+ systemProperties.add(
+ DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY);
+ break;
+ case PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP:
+ systemProperties.add(
+ DeviceState.PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP);
+ break;
+ case PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE:
+ systemProperties.add(
+ DeviceState.PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE);
+ break;
+ case PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY:
+ systemProperties.add(
+ DeviceState.PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY);
+ break;
+ case PROPERTY_FEATURE_REAR_DISPLAY:
+ systemProperties.add(DeviceState.PROPERTY_FEATURE_REAR_DISPLAY);
+ break;
+ case PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT:
+ systemProperties.add(DeviceState.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT);
+ break;
+ default:
+ Slog.w(TAG, "Parsed unknown flag with name: " + propertyString);
+ break;
+ }
+ }
+
// Lock for internal state.
private final Object mLock = new Object();
private final Context mContext;
@@ -210,7 +300,7 @@
@GuardedBy("mLock")
private Listener mListener = null;
@GuardedBy("mLock")
- private int mLastReportedState = INVALID_DEVICE_STATE;
+ private int mLastReportedState = INVALID_DEVICE_STATE_IDENTIFIER;
@GuardedBy("mLock")
private Boolean mIsLidOpen;
@@ -285,7 +375,7 @@
if (conditions == null) {
// If this state has the FLAG_EMULATED_ONLY flag on it, it should never be triggered
// by a physical hardware change, and should always return false for it's conditions
- if (deviceStates.get(i).hasFlag(DeviceState.FLAG_EMULATED_ONLY)) {
+ if (deviceStates.get(i).hasProperty(DeviceState.PROPERTY_EMULATED_ONLY)) {
mStateConditions.put(state, FALSE_BOOLEAN_SUPPLIER);
} else {
mStateConditions.put(state, TRUE_BOOLEAN_SUPPLIER);
@@ -410,13 +500,13 @@
}
listener = mListener;
for (DeviceState deviceState : mOrderedStates) {
- if (isThermalStatusCriticalOrAbove(mThermalStatus)
- && deviceState.hasFlag(
- DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL)) {
+ if (isThermalStatusCriticalOrAbove(mThermalStatus) && deviceState.hasProperty(
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
+ )) {
continue;
}
- if (mPowerSaveModeEnabled && deviceState.hasFlag(
- DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE)) {
+ if (mPowerSaveModeEnabled && deviceState.hasProperty(
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE)) {
continue;
}
supportedStates.add(deviceState);
@@ -424,18 +514,19 @@
}
listener.onSupportedDeviceStatesChanged(
- supportedStates.toArray(new DeviceState[supportedStates.size()]), reason);
+ supportedStates.toArray(new DeviceState[supportedStates.size()]),
+ reason);
}
/** Computes the current device state and notifies the listener of a change, if needed. */
void notifyDeviceStateChangedIfNeeded() {
- int stateToReport = INVALID_DEVICE_STATE;
+ int stateToReport = INVALID_DEVICE_STATE_IDENTIFIER;
synchronized (mLock) {
if (mListener == null) {
return;
}
- int newState = INVALID_DEVICE_STATE;
+ int newState = INVALID_DEVICE_STATE_IDENTIFIER;
for (int i = 0; i < mOrderedStates.length; i++) {
int state = mOrderedStates[i].getIdentifier();
if (DEBUG) {
@@ -464,18 +555,18 @@
break;
}
}
- if (newState == INVALID_DEVICE_STATE) {
+ if (newState == INVALID_DEVICE_STATE_IDENTIFIER) {
Slog.e(TAG, "No declared device states match any of the required conditions.");
dumpSensorValues();
}
- if (newState != INVALID_DEVICE_STATE && newState != mLastReportedState) {
+ if (newState != INVALID_DEVICE_STATE_IDENTIFIER && newState != mLastReportedState) {
mLastReportedState = newState;
stateToReport = newState;
}
}
- if (stateToReport != INVALID_DEVICE_STATE) {
+ if (stateToReport != INVALID_DEVICE_STATE_IDENTIFIER) {
mListener.onStateChanged(stateToReport);
}
}
@@ -774,8 +865,9 @@
}
private static boolean hasThermalSensitiveState(List<DeviceState> deviceStates) {
- for (DeviceState state : deviceStates) {
- if (state.hasFlag(DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL)) {
+ for (int i = 0; i < deviceStates.size(); i++) {
+ if (deviceStates.get(i).hasProperty(
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL)) {
return true;
}
}
@@ -784,7 +876,8 @@
private static boolean hasPowerSaveSensitiveState(List<DeviceState> deviceStates) {
for (int i = 0; i < deviceStates.size(); i++) {
- if (deviceStates.get(i).hasFlag(DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE)) {
+ if (deviceStates.get(i).hasProperty(
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE)) {
return true;
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ec4b38b..5974ac8 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3523,7 +3523,8 @@
case KeyEvent.KEYCODE_DPAD_LEFT:
if (firstDown && event.isMetaPressed()) {
if (event.isCtrlPressed()) {
- enterStageSplitFromRunningApp(true /* leftOrTop */);
+ moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event),
+ true /* leftOrTop */);
logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
} else {
logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
@@ -3534,7 +3535,8 @@
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
- enterStageSplitFromRunningApp(false /* leftOrTop */);
+ moveFocusedTaskToStageSplit(getTargetDisplayIdForKeyEvent(event),
+ false /* leftOrTop */);
logKeyboardSystemsEvent(event, KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION);
return true;
}
@@ -4387,10 +4389,10 @@
}
}
- private void enterStageSplitFromRunningApp(boolean leftOrTop) {
+ private void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
if (statusbar != null) {
- statusbar.enterStageSplitFromRunningApp(leftOrTop);
+ statusbar.moveFocusedTaskToStageSplit(displayId, leftOrTop);
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a172de0..b50e2bf 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -7149,7 +7149,7 @@
* Any changes to the device state are treated as user interactions.
*/
class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
- private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
+ private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
@Override
public void onStateChanged(int deviceState) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 14e0ce1..c73f89c 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -233,9 +233,9 @@
/**
* Enters stage split from a current running app.
*
- * @see com.android.internal.statusbar.IStatusBar#enterStageSplitFromRunningApp
+ * @see com.android.internal.statusbar.IStatusBar#moveFocusedTaskToStageSplit
*/
- void enterStageSplitFromRunningApp(boolean leftOrTop);
+ void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop);
/**
* Shows the media output switcher dialog.
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 0b48a75..214dbe0 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -820,11 +820,11 @@
}
@Override
- public void enterStageSplitFromRunningApp(boolean leftOrTop) {
+ public void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop) {
IStatusBar bar = mBar;
if (bar != null) {
try {
- bar.enterStageSplitFromRunningApp(leftOrTop);
+ bar.moveFocusedTaskToStageSplit(displayId, leftOrTop);
} catch (RemoteException ex) { }
}
}
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/CompleteEffectVibratorStep.java b/services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java
index fb5140d..48dd992 100644
--- a/services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/CompleteEffectVibratorStep.java
@@ -51,8 +51,8 @@
public List<Step> cancel() {
if (mCancelled) {
// Double cancelling will just turn off the vibrator right away.
- return Arrays.asList(
- new TurnOffVibratorStep(conductor, SystemClock.uptimeMillis(), controller));
+ return Arrays.asList(new TurnOffVibratorStep(conductor, SystemClock.uptimeMillis(),
+ controller, /* isCleanUp= */ true));
}
return super.cancel();
}
@@ -92,8 +92,8 @@
} else {
// Vibration is completing normally, turn off after the deadline in case we
// don't receive the callback in time (callback also triggers it right away).
- return Arrays.asList(new TurnOffVibratorStep(
- conductor, mPendingVibratorOffDeadline, controller));
+ return Arrays.asList(new TurnOffVibratorStep(conductor,
+ mPendingVibratorOffDeadline, controller, /* isCleanUp= */ false));
}
}
diff --git a/services/core/java/com/android/server/vibrator/RampOffVibratorStep.java b/services/core/java/com/android/server/vibrator/RampOffVibratorStep.java
index 84da9f2..f40c994 100644
--- a/services/core/java/com/android/server/vibrator/RampOffVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/RampOffVibratorStep.java
@@ -44,8 +44,8 @@
@Override
public List<Step> cancel() {
- return Arrays.asList(
- new TurnOffVibratorStep(conductor, SystemClock.uptimeMillis(), controller));
+ return Arrays.asList(new TurnOffVibratorStep(conductor, SystemClock.uptimeMillis(),
+ controller, /* isCleanUp= */ true));
}
@Override
@@ -71,8 +71,8 @@
// Vibrator amplitude cannot go further down, just turn it off with the configured
// deadline that has been adjusted for the scenario when this was triggered by a
// cancelled vibration.
- return Arrays.asList(new TurnOffVibratorStep(
- conductor, mPendingVibratorOffDeadline, controller));
+ return Arrays.asList(new TurnOffVibratorStep(conductor, mPendingVibratorOffDeadline,
+ controller, /* isCleanUp= */ true));
}
return Arrays.asList(new RampOffVibratorStep(
conductor,
diff --git a/services/core/java/com/android/server/vibrator/TurnOffVibratorStep.java b/services/core/java/com/android/server/vibrator/TurnOffVibratorStep.java
index 297ef56..065ce11 100644
--- a/services/core/java/com/android/server/vibrator/TurnOffVibratorStep.java
+++ b/services/core/java/com/android/server/vibrator/TurnOffVibratorStep.java
@@ -32,20 +32,23 @@
*/
final class TurnOffVibratorStep extends AbstractVibratorStep {
+ private final boolean mIsCleanUp;
+
TurnOffVibratorStep(VibrationStepConductor conductor, long startTime,
- VibratorController controller) {
+ VibratorController controller, boolean isCleanUp) {
super(conductor, startTime, controller, /* effect= */ null, /* index= */ -1, startTime);
+ mIsCleanUp = isCleanUp;
}
@Override
public boolean isCleanUp() {
- return true;
+ return mIsCleanUp;
}
@Override
public List<Step> cancel() {
- return Arrays.asList(
- new TurnOffVibratorStep(conductor, SystemClock.uptimeMillis(), controller));
+ return Arrays.asList(new TurnOffVibratorStep(conductor, SystemClock.uptimeMillis(),
+ controller, /* isCleanUp= */ true));
}
@Override
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index af494a3..9e9025e 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -2097,6 +2097,7 @@
/** Provide limited functionality from {@link VibratorManagerService} as shell commands. */
private final class VibratorManagerShellCommand extends ShellCommand {
public static final String SHELL_PACKAGE_NAME = "com.android.shell";
+ public static final long VIBRATION_END_TIMEOUT_MS = 500; // Clean up shouldn't be too long.
private final class CommonOptions {
public boolean force = false;
@@ -2472,6 +2473,9 @@
// Waits for the client vibration to finish, but the VibrationThread may still
// do cleanup after this.
vib.waitForEnd();
+ // Wait for vibration clean up and possible ramp down before ending.
+ mVibrationThread.waitForThreadIdle(
+ mVibrationSettings.getRampDownDuration() + VIBRATION_END_TIMEOUT_MS);
} catch (InterruptedException e) {
}
}
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/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index a75d3b6..445a5c8 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2327,7 +2327,7 @@
}
/**
- * Finish the topmost activities in all root tasks that belong to the crashed app.
+ * Finish the topmost activities in all leaf tasks that belong to the crashed app.
*
* @param app The app that crashed.
* @param reason Reason to perform this action.
@@ -2338,14 +2338,14 @@
Task finishTopCrashedActivities(WindowProcessController app, String reason) {
Task focusedRootTask = getTopDisplayFocusedRootTask();
final Task[] finishedTask = new Task[1];
- forAllRootTasks(rootTask -> {
+ forAllLeafTasks(leafTask -> {
final boolean recordTopOrVisible = finishedTask[0] == null
- && (focusedRootTask == rootTask || rootTask.isVisibleRequested());
- final Task t = rootTask.finishTopCrashedActivityLocked(app, reason);
+ && (focusedRootTask == leafTask.getRootTask() || leafTask.isVisibleRequested());
+ final Task t = leafTask.finishTopCrashedActivityLocked(app, reason);
if (recordTopOrVisible) {
finishedTask[0] = t;
}
- });
+ }, true);
return finishedTask[0];
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 9b19a70..3fb5998 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -157,13 +157,21 @@
mFindResults.setUseTopWallpaperAsTarget(true);
}
- if (mService.mPolicy.isKeyguardLocked() && w.canShowWhenLocked()) {
- if (mService.mPolicy.isKeyguardOccluded() || (useShellTransition
- ? w.inTransition() : mService.mPolicy.isKeyguardUnoccluding())) {
- // The lowest show when locked window decides whether we need to put the wallpaper
- // behind.
- mFindResults.mNeedsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
- || (w.mActivityRecord != null && !w.mActivityRecord.fillsParent());
+ if (mService.mPolicy.isKeyguardLocked()) {
+ if (w.canShowWhenLocked()) {
+ if (mService.mPolicy.isKeyguardOccluded() || (useShellTransition
+ ? w.inTransition() : mService.mPolicy.isKeyguardUnoccluding())) {
+ // The lowest show-when-locked window decides whether to show wallpaper.
+ mFindResults.mNeedsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
+ || (w.mActivityRecord != null && !w.mActivityRecord.fillsParent());
+ }
+ } else if (w.hasWallpaper() && mService.mPolicy.isKeyguardHostWindow(w.mAttrs)
+ && w.mTransitionController.isTransitionOnDisplay(mDisplayContent)) {
+ // If we have no candidates at all, notification shade is allowed to be the target
+ // of last resort even if it has not been made visible yet.
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Found keyguard as wallpaper target: " + w);
+ mFindResults.setWallpaperTarget(w);
+ return false;
}
}
@@ -200,14 +208,7 @@
private boolean isRecentsTransitionTarget(WindowState w) {
if (w.mTransitionController.isShellTransitionsEnabled()) {
- // Because the recents activity is invisible in background while keyguard is occluded
- // (the activity window is on screen while keyguard is locked) with recents animation,
- // the task animating by recents needs to be wallpaper target to make wallpaper visible.
- // While for unlocked case, because recents activity will be moved to top, it can be
- // the wallpaper target naturally.
- return w.mActivityRecord != null && w.mAttrs.type == TYPE_BASE_APPLICATION
- && mDisplayContent.isKeyguardLocked()
- && w.mTransitionController.isTransientHide(w.getTask());
+ return false;
}
// The window is either the recents activity or is in the task animating by the recents.
final RecentsAnimationController controller = mService.getRecentsAnimationController();
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 4403bce..95e7b19 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -393,6 +393,7 @@
++pageoutVmaIndex;
break;
}
+ return true;
};
meminfo.ForEachVmaFromMaps(vmaCollectorCb, mapsBuffer);
ATRACE_END();
diff --git a/services/core/xsd/device-state-config/device-state-config.xsd b/services/core/xsd/device-state-config/device-state-config.xsd
index 86f4176..4a94732 100644
--- a/services/core/xsd/device-state-config/device-state-config.xsd
+++ b/services/core/xsd/device-state-config/device-state-config.xsd
@@ -40,14 +40,14 @@
<xs:element name="name" type="xs:string" minOccurs="0">
<xs:annotation name="nullable" />
</xs:element>
- <xs:element name="flags" type="flags" />
+ <xs:element name="properties" type="properties" />
<xs:element name="conditions" type="conditions" />
</xs:sequence>
</xs:complexType>
- <xs:complexType name="flags">
+ <xs:complexType name="properties">
<xs:sequence>
- <xs:element name="flag" type="xs:string" minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="property" type="xs:string" minOccurs="0" maxOccurs="unbounded">
<xs:annotation name="nullable" />
</xs:element>
</xs:sequence>
diff --git a/services/core/xsd/device-state-config/schema/current.txt b/services/core/xsd/device-state-config/schema/current.txt
index a98d4e5..5bb216e 100644
--- a/services/core/xsd/device-state-config/schema/current.txt
+++ b/services/core/xsd/device-state-config/schema/current.txt
@@ -11,13 +11,13 @@
public class DeviceState {
ctor public DeviceState();
method public com.android.server.policy.devicestate.config.Conditions getConditions();
- method public com.android.server.policy.devicestate.config.Flags getFlags();
method public java.math.BigInteger getIdentifier();
method @Nullable public String getName();
+ method public com.android.server.policy.devicestate.config.Properties getProperties();
method public void setConditions(com.android.server.policy.devicestate.config.Conditions);
- method public void setFlags(com.android.server.policy.devicestate.config.Flags);
method public void setIdentifier(java.math.BigInteger);
method public void setName(@Nullable String);
+ method public void setProperties(com.android.server.policy.devicestate.config.Properties);
}
public class DeviceStateConfig {
@@ -25,11 +25,6 @@
method public java.util.List<com.android.server.policy.devicestate.config.DeviceState> getDeviceState();
}
- public class Flags {
- ctor public Flags();
- method @Nullable public java.util.List<java.lang.String> getFlag();
- }
-
public class LidSwitchCondition {
ctor public LidSwitchCondition();
method public boolean getOpen();
@@ -48,6 +43,11 @@
method public void setMin_optional(@Nullable java.math.BigDecimal);
}
+ public class Properties {
+ ctor public Properties();
+ method @Nullable public java.util.List<java.lang.String> getProperty();
+ }
+
public class SensorCondition {
ctor public SensorCondition();
method public String getName();
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleClosedStatePredicate.java b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleClosedStatePredicate.java
index 209107e..ce4126a 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleClosedStatePredicate.java
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleClosedStatePredicate.java
@@ -177,8 +177,11 @@
*/
private static class PostureEstimator implements SensorEventListener, Dumpable {
+ private static final String FLAT_INCLINATION_THRESHOLD_DEGREES_PROPERTY
+ = "persist.foldable_postures.wedge_inclination_threshold_degrees";
- private static final int FLAT_INCLINATION_THRESHOLD_DEGREES = 8;
+ private static final int FLAT_INCLINATION_THRESHOLD_DEGREES = Integer.parseInt(
+ System.getProperty(FLAT_INCLINATION_THRESHOLD_DEGREES_PROPERTY, "25"));
/**
* Alpha parameter of the accelerometer low pass filter: the lower the value, the less high
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java
index bc264a4..95c4407 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java
@@ -16,29 +16,43 @@
package com.android.server.policy;
-import static android.hardware.devicestate.DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
-import static android.hardware.devicestate.DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP;
-import static android.hardware.devicestate.DeviceState.FLAG_EMULATED_ONLY;
-import static android.hardware.devicestate.DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE;
-import static android.hardware.devicestate.DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL;
+import static android.hardware.devicestate.DeviceState.PROPERTY_EMULATED_ONLY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE;
import static com.android.server.policy.BookStyleStateTransitions.DEFAULT_STATE_TRANSITIONS;
-import static com.android.server.policy.FoldableDeviceStateProvider.DeviceStateConfiguration.createConfig;
-import static com.android.server.policy.FoldableDeviceStateProvider.DeviceStateConfiguration.createTentModeClosedState;
+import static com.android.server.policy.FoldableDeviceStateProvider.DeviceStatePredicateWrapper.createConfig;
+import static com.android.server.policy.FoldableDeviceStateProvider.DeviceStatePredicateWrapper.createTentModeClosedState;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
+import android.hardware.devicestate.DeviceState;
import android.hardware.display.DisplayManager;
import com.android.server.devicestate.DeviceStatePolicy;
import com.android.server.devicestate.DeviceStateProvider;
-import com.android.server.policy.FoldableDeviceStateProvider.DeviceStateConfiguration;
+import com.android.server.policy.FoldableDeviceStateProvider.DeviceStatePredicateWrapper;
import com.android.server.policy.feature.flags.FeatureFlags;
import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.function.Predicate;
/**
@@ -55,9 +69,8 @@
private static final int DEVICE_STATE_CLOSED = 0;
private static final int DEVICE_STATE_HALF_OPENED = 1;
private static final int DEVICE_STATE_OPENED = 2;
- private static final int DEVICE_STATE_REAR_DISPLAY_STATE = 3;
+ private static final int DEVICE_STATE_REAR_DISPLAY = 3;
private static final int DEVICE_STATE_CONCURRENT_INNER_DEFAULT = 4;
-
private static final int TENT_MODE_SWITCH_ANGLE_DEGREES = 90;
private static final int TABLE_TOP_MODE_SWITCH_ANGLE_DEGREES = 125;
private static final int MIN_CLOSED_ANGLE_DEGREES = 0;
@@ -92,81 +105,60 @@
mEnablePostureBasedClosedState = featureFlags.enableFoldablesPostureBasedClosedState();
mIsDualDisplayBlockingEnabled = featureFlags.enableDualDisplayBlocking();
- final DeviceStateConfiguration[] configuration = createConfiguration(
+ final DeviceStatePredicateWrapper[] configuration = createConfiguration(
leftAccelerometerSensor, rightAccelerometerSensor, closeAngleDegrees);
- mProvider = new FoldableDeviceStateProvider(mContext, sensorManager,
- hingeAngleSensor, hallSensor, displayManager, configuration);
+ mProvider = new FoldableDeviceStateProvider(mContext, sensorManager, hingeAngleSensor,
+ hallSensor, displayManager, configuration);
}
- private DeviceStateConfiguration[] createConfiguration(@Nullable Sensor leftAccelerometerSensor,
- @Nullable Sensor rightAccelerometerSensor, Integer closeAngleDegrees) {
- return new DeviceStateConfiguration[]{
+ private DeviceStatePredicateWrapper[] createConfiguration(
+ @Nullable Sensor leftAccelerometerSensor, @Nullable Sensor rightAccelerometerSensor,
+ Integer closeAngleDegrees) {
+ return new DeviceStatePredicateWrapper[]{
createClosedConfiguration(leftAccelerometerSensor, rightAccelerometerSensor,
closeAngleDegrees),
- createConfig(DEVICE_STATE_HALF_OPENED,
- /* name= */ "HALF_OPENED",
- /* activeStatePredicate= */ (provider) -> {
+ createConfig(getHalfOpenedDeviceState(), /* activeStatePredicate= */
+ (provider) -> {
final float hingeAngle = provider.getHingeAngle();
return hingeAngle >= MAX_CLOSED_ANGLE_DEGREES
&& hingeAngle <= TABLE_TOP_MODE_SWITCH_ANGLE_DEGREES;
}),
- createConfig(DEVICE_STATE_OPENED,
- /* name= */ "OPENED",
- /* activeStatePredicate= */ ALLOWED),
- createConfig(DEVICE_STATE_REAR_DISPLAY_STATE,
- /* name= */ "REAR_DISPLAY_STATE",
- /* flags= */ FLAG_EMULATED_ONLY,
- /* activeStatePredicate= */ NOT_ALLOWED),
- createConfig(DEVICE_STATE_CONCURRENT_INNER_DEFAULT,
- /* name= */ "CONCURRENT_INNER_DEFAULT",
- /* flags= */ FLAG_EMULATED_ONLY | FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP
- | FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
- /* activeStatePredicate= */ NOT_ALLOWED,
- /* availabilityPredicate= */
+ createConfig(getOpenedDeviceState(), /* activeStatePredicate= */
+ ALLOWED),
+ createConfig(getRearDisplayDeviceState(), /* activeStatePredicate= */
+ NOT_ALLOWED),
+ createConfig(getDualDisplayDeviceState(), /* activeStatePredicate= */
+ NOT_ALLOWED, /* availabilityPredicate= */
provider -> !mIsDualDisplayBlockingEnabled
- || provider.hasNoConnectedExternalDisplay())
- };
+ || provider.hasNoConnectedExternalDisplay())};
}
- private DeviceStateConfiguration createClosedConfiguration(
+ private DeviceStatePredicateWrapper createClosedConfiguration(
@Nullable Sensor leftAccelerometerSensor, @Nullable Sensor rightAccelerometerSensor,
@Nullable Integer closeAngleDegrees) {
+
if (closeAngleDegrees != null) {
// Switch displays at closeAngleDegrees in both ways (folding and unfolding)
- return createConfig(
- DEVICE_STATE_CLOSED,
- /* name= */ "CLOSED",
- /* flags= */ FLAG_CANCEL_OVERRIDE_REQUESTS,
- /* activeStatePredicate= */ (provider) -> {
+ return createConfig(getClosedDeviceState(), /* activeStatePredicate= */
+ (provider) -> {
final float hingeAngle = provider.getHingeAngle();
return hingeAngle <= closeAngleDegrees;
- }
- );
+ });
}
if (mEnablePostureBasedClosedState) {
// Use smart closed state predicate that will use different switch angles
// based on the device posture (e.g. wedge mode, tent mode, reverse wedge mode)
- return createConfig(
- DEVICE_STATE_CLOSED,
- /* name= */ "CLOSED",
- /* flags= */ FLAG_CANCEL_OVERRIDE_REQUESTS,
- /* activeStatePredicate= */ new BookStyleClosedStatePredicate(mContext,
- this, leftAccelerometerSensor, rightAccelerometerSensor,
- DEFAULT_STATE_TRANSITIONS)
- );
+ return createConfig(getClosedDeviceState(), /* activeStatePredicate= */
+ new BookStyleClosedStatePredicate(mContext, this, leftAccelerometerSensor,
+ rightAccelerometerSensor, DEFAULT_STATE_TRANSITIONS));
}
// Switch to the outer display only at 0 degrees but use TENT_MODE_SWITCH_ANGLE_DEGREES
// angle when switching to the inner display
- return createTentModeClosedState(DEVICE_STATE_CLOSED,
- /* name= */ "CLOSED",
- /* flags= */ FLAG_CANCEL_OVERRIDE_REQUESTS,
- MIN_CLOSED_ANGLE_DEGREES,
- MAX_CLOSED_ANGLE_DEGREES,
- TENT_MODE_SWITCH_ANGLE_DEGREES);
+ return createTentModeClosedState(getClosedDeviceState(),
+ MIN_CLOSED_ANGLE_DEGREES, MAX_CLOSED_ANGLE_DEGREES, TENT_MODE_SWITCH_ANGLE_DEGREES);
}
@Override
@@ -188,4 +180,84 @@
public void dump(@NonNull PrintWriter writer, @Nullable String[] args) {
mProvider.dump(writer, args);
}
+
+ /** Returns the {@link DeviceState.Configuration} that represents the closed state. */
+ @NonNull
+ private DeviceState getClosedDeviceState() {
+ Set<@DeviceState.SystemDeviceStateProperties Integer> systemProperties = new HashSet<>(
+ List.of(PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS,
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY,
+ PROPERTY_POWER_CONFIGURATION_TRIGGER_SLEEP));
+
+ Set<@DeviceState.PhysicalDeviceStateProperties Integer> physicalProperties = new HashSet<>(
+ List.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED));
+
+ return new DeviceState(new DeviceState.Configuration.Builder(DEVICE_STATE_CLOSED, "CLOSED")
+ .setSystemProperties(systemProperties)
+ .setPhysicalProperties(physicalProperties)
+ .build());
+ }
+
+ /** Returns the {@link DeviceState.Configuration} that represents the half_opened state. */
+ @NonNull
+ private DeviceState getHalfOpenedDeviceState() {
+ Set<@DeviceState.SystemDeviceStateProperties Integer> systemProperties = new HashSet<>(
+ List.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
+ PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE));
+
+ Set<@DeviceState.PhysicalDeviceStateProperties Integer> physicalProperties = new HashSet<>(
+ List.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN));
+
+ return new DeviceState(new DeviceState.Configuration.Builder(DEVICE_STATE_HALF_OPENED,
+ "HALF_OPENED")
+ .setSystemProperties(systemProperties)
+ .setPhysicalProperties(physicalProperties)
+ .build());
+ }
+
+ /** Returns the {@link DeviceState.Configuration} that represents the opened state */
+ @NonNull
+ private DeviceState getOpenedDeviceState() {
+ Set<@DeviceState.SystemDeviceStateProperties Integer> systemProperties = new HashSet<>(
+ List.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
+ PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE));
+ Set<@DeviceState.PhysicalDeviceStateProperties Integer> physicalProperties = new HashSet<>(
+ List.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN));
+
+ return new DeviceState(new DeviceState.Configuration.Builder(DEVICE_STATE_OPENED, "OPENED")
+ .setSystemProperties(systemProperties)
+ .setPhysicalProperties(physicalProperties)
+ .build());
+ }
+
+ /** Returns the {@link DeviceState.Configuration} that represents the rear display state. */
+ @NonNull
+ private DeviceState getRearDisplayDeviceState() {
+ Set<@DeviceState.SystemDeviceStateProperties Integer> systemProperties = new HashSet<>(
+ List.of(PROPERTY_EMULATED_ONLY,
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY,
+ PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST, PROPERTY_FEATURE_REAR_DISPLAY));
+
+ return new DeviceState(new DeviceState.Configuration.Builder(DEVICE_STATE_REAR_DISPLAY,
+ "REAR_DISPLAY_STATE")
+ .setSystemProperties(systemProperties)
+ .build());
+ }
+
+ /** Returns the {@link DeviceState.Configuration} that represents the dual display state. */
+ @NonNull
+ private DeviceState getDualDisplayDeviceState() {
+ Set<@DeviceState.SystemDeviceStateProperties Integer> systemProperties = new HashSet<>(
+ List.of(PROPERTY_EMULATED_ONLY, PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
+ PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST,
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY,
+ PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT));
+
+ return new DeviceState(new DeviceState.Configuration.Builder(
+ DEVICE_STATE_CONCURRENT_INNER_DEFAULT, "CONCURRENT_INNER_DEFAULT")
+ .setSystemProperties(systemProperties)
+ .build());
+ }
}
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java b/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
index 42e41d5..bc8643f 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/FoldableDeviceStateProvider.java
@@ -17,13 +17,12 @@
package com.android.server.policy;
import static android.hardware.SensorManager.SENSOR_DELAY_FASTEST;
-import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
-import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE_IDENTIFIER;
-import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE_IDENTIFIER;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE;
+import static android.hardware.devicestate.DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.TYPE_EXTERNAL;
-import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
@@ -89,7 +88,7 @@
// the conditions needed for availability.
private final SparseArray<BooleanSupplier> mStateAvailabilityConditions = new SparseArray<>();
- private final DeviceStateConfiguration[] mConfigurations;
+ private final DeviceStatePredicateWrapper[] mConfigurations;
@GuardedBy("mLock")
private final SparseBooleanArray mExternalDisplaysConnected = new SparseBooleanArray();
@@ -103,7 +102,7 @@
@GuardedBy("mLock")
private Listener mListener = null;
@GuardedBy("mLock")
- private int mLastReportedState = INVALID_DEVICE_STATE;
+ private int mLastReportedState = INVALID_DEVICE_STATE_IDENTIFIER;
@GuardedBy("mLock")
private SensorEvent mLastHingeAngleSensorEvent = null;
@GuardedBy("mLock")
@@ -125,9 +124,9 @@
@NonNull Sensor hingeAngleSensor,
@NonNull Sensor hallSensor,
@NonNull DisplayManager displayManager,
- @NonNull DeviceStateConfiguration[] deviceStateConfigurations) {
+ @NonNull DeviceStatePredicateWrapper[] deviceStatePredicateWrappers) {
this(new FeatureFlagsImpl(), context, sensorManager, hingeAngleSensor, hallSensor,
- displayManager, deviceStateConfigurations);
+ displayManager, deviceStatePredicateWrappers);
}
@VisibleForTesting
@@ -138,23 +137,23 @@
@NonNull Sensor hingeAngleSensor,
@NonNull Sensor hallSensor,
@NonNull DisplayManager displayManager,
- @NonNull DeviceStateConfiguration[] deviceStateConfigurations) {
+ @NonNull DeviceStatePredicateWrapper[] deviceStatePredicateWrappers) {
- Preconditions.checkArgument(deviceStateConfigurations.length > 0,
+ Preconditions.checkArgument(deviceStatePredicateWrappers.length > 0,
"Device state configurations array must not be empty");
mHingeAngleSensor = hingeAngleSensor;
mHallSensor = hallSensor;
mDisplayManager = displayManager;
- mConfigurations = deviceStateConfigurations;
+ mConfigurations = deviceStatePredicateWrappers;
mIsDualDisplayBlockingEnabled = featureFlags.enableDualDisplayBlocking();
sensorManager.registerListener(this, mHingeAngleSensor, SENSOR_DELAY_FASTEST);
sensorManager.registerListener(this, mHallSensor, SENSOR_DELAY_FASTEST);
- mOrderedStates = new DeviceState[deviceStateConfigurations.length];
- for (int i = 0; i < deviceStateConfigurations.length; i++) {
- final DeviceStateConfiguration configuration = deviceStateConfigurations[i];
+ mOrderedStates = new DeviceState[deviceStatePredicateWrappers.length];
+ for (int i = 0; i < deviceStatePredicateWrappers.length; i++) {
+ final DeviceStatePredicateWrapper configuration = deviceStatePredicateWrappers[i];
mOrderedStates[i] = configuration.mDeviceState;
assertUniqueDeviceStateIdentifier(configuration);
@@ -174,14 +173,14 @@
// If any of the device states are thermal sensitive, i.e. it should be disabled when
// the device is overheating, then we will update the list of supported states when
// thermal status changes.
- if (hasThermalSensitiveState(deviceStateConfigurations)) {
+ if (hasThermalSensitiveState(deviceStatePredicateWrappers)) {
powerManager.addThermalStatusListener(this);
}
// If any of the device states are power sensitive, i.e. it should be disabled when
// power save mode is enabled, then we will update the list of supported states when
// power save mode is toggled.
- if (hasPowerSaveSensitiveState(deviceStateConfigurations)) {
+ if (hasPowerSaveSensitiveState(deviceStatePredicateWrappers)) {
IntentFilter filter = new IntentFilter(
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL);
BroadcastReceiver receiver = new BroadcastReceiver() {
@@ -198,7 +197,7 @@
}
}
- private void assertUniqueDeviceStateIdentifier(DeviceStateConfiguration configuration) {
+ private void assertUniqueDeviceStateIdentifier(DeviceStatePredicateWrapper configuration) {
if (mStateConditions.get(configuration.mDeviceState.getIdentifier()) != null) {
throw new IllegalArgumentException("Device state configurations must have unique"
+ " device state identifiers, found duplicated identifier: "
@@ -206,12 +205,12 @@
}
}
- private void initialiseStateConditions(DeviceStateConfiguration configuration) {
+ private void initialiseStateConditions(DeviceStatePredicateWrapper configuration) {
mStateConditions.put(configuration.mDeviceState.getIdentifier(), () ->
configuration.mActiveStatePredicate.test(this));
}
- private void initialiseStateAvailabilityConditions(DeviceStateConfiguration configuration) {
+ private void initialiseStateAvailabilityConditions(DeviceStatePredicateWrapper configuration) {
mStateAvailabilityConditions.put(configuration.mDeviceState.getIdentifier(), () ->
configuration.mAvailabilityPredicate.test(this));
}
@@ -250,13 +249,12 @@
@GuardedBy("mLock")
private boolean isStateSupported(DeviceState deviceState) {
- if (isThermalStatusCriticalOrAbove(mThermalStatus)
- && deviceState.hasFlag(
- DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL)) {
+ if (isThermalStatusCriticalOrAbove(mThermalStatus) && deviceState.hasProperty(
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL)) {
return false;
}
- if (mPowerSaveModeEnabled && deviceState.hasFlag(
- DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE)) {
+ if (mPowerSaveModeEnabled && deviceState.hasProperty(
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE)) {
return false;
}
if (mIsDualDisplayBlockingEnabled
@@ -270,7 +268,7 @@
/** Computes the current device state and notifies the listener of a change, if needed. */
void notifyDeviceStateChangedIfNeeded() {
- int stateToReport = INVALID_DEVICE_STATE;
+ int stateToReport = INVALID_DEVICE_STATE_IDENTIFIER;
Listener listener;
synchronized (mLock) {
if (mListener == null) {
@@ -279,7 +277,7 @@
listener = mListener;
- int newState = INVALID_DEVICE_STATE;
+ int newState = INVALID_DEVICE_STATE_IDENTIFIER;
for (int i = 0; i < mOrderedStates.length; i++) {
int state = mOrderedStates[i].getIdentifier();
if (DEBUG) {
@@ -307,18 +305,18 @@
break;
}
}
- if (newState == INVALID_DEVICE_STATE) {
+ if (newState == INVALID_DEVICE_STATE_IDENTIFIER) {
Slog.e(TAG, "No declared device states match any of the required conditions.");
dumpSensorValues();
}
- if (newState != INVALID_DEVICE_STATE && newState != mLastReportedState) {
+ if (newState != INVALID_DEVICE_STATE_IDENTIFIER && newState != mLastReportedState) {
mLastReportedState = newState;
stateToReport = newState;
}
}
- if (stateToReport != INVALID_DEVICE_STATE) {
+ if (stateToReport != INVALID_DEVICE_STATE_IDENTIFIER) {
listener.onStateChanged(stateToReport);
}
}
@@ -441,7 +439,7 @@
writer.println(" Predicates:");
for (int i = 0; i < mConfigurations.length; i++) {
- final DeviceStateConfiguration configuration = mConfigurations[i];
+ final DeviceStatePredicateWrapper configuration = mConfigurations[i];
final Predicate<FoldableDeviceStateProvider> predicate =
configuration.mActiveStatePredicate;
@@ -452,22 +450,23 @@
}
/**
- * Configuration for a single device state, contains information about the state like
+ * Configuration wrapper for a single device state, contains information about the state like
* identifier, name, flags and a predicate that should return true if the state should
* be selected.
*/
- public static class DeviceStateConfiguration {
+ public static class DeviceStatePredicateWrapper {
private final DeviceState mDeviceState;
private final Predicate<FoldableDeviceStateProvider> mActiveStatePredicate;
private final Predicate<FoldableDeviceStateProvider> mAvailabilityPredicate;
- private DeviceStateConfiguration(
+ private DeviceStatePredicateWrapper(
@NonNull DeviceState deviceState,
@NonNull Predicate<FoldableDeviceStateProvider> predicate) {
this(deviceState, predicate, ALLOWED);
}
- private DeviceStateConfiguration(
+ /** Create a configuration with availability and availability predicate **/
+ private DeviceStatePredicateWrapper(
@NonNull DeviceState deviceState,
@NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate,
@NonNull Predicate<FoldableDeviceStateProvider> availabilityPredicate) {
@@ -477,38 +476,22 @@
mAvailabilityPredicate = availabilityPredicate;
}
- public static DeviceStateConfiguration createConfig(
- @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
- MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
- @NonNull String name,
- @DeviceState.DeviceStateFlags int flags,
+ /** Create a configuration with an active state predicate **/
+ public static DeviceStatePredicateWrapper createConfig(
+ @NonNull DeviceState deviceState,
@NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate
) {
- return new DeviceStateConfiguration(new DeviceState(identifier, name, flags),
- activeStatePredicate);
+ return new DeviceStatePredicateWrapper(deviceState, activeStatePredicate);
}
- public static DeviceStateConfiguration createConfig(
- @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
- MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
- @NonNull String name,
- @NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate
- ) {
- return new DeviceStateConfiguration(new DeviceState(identifier, name, /* flags= */ 0),
- activeStatePredicate);
- }
-
- /** Create a configuration with availability predicate **/
- public static DeviceStateConfiguration createConfig(
- @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
- MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
- @NonNull String name,
- @DeviceState.DeviceStateFlags int flags,
+ /** Create a configuration with availability and active state predicate **/
+ public static DeviceStatePredicateWrapper createConfig(
+ @NonNull DeviceState deviceState,
@NonNull Predicate<FoldableDeviceStateProvider> activeStatePredicate,
@NonNull Predicate<FoldableDeviceStateProvider> availabilityPredicate
) {
- return new DeviceStateConfiguration(new DeviceState(identifier, name, flags),
- activeStatePredicate, availabilityPredicate);
+ return new DeviceStatePredicateWrapper(deviceState, activeStatePredicate,
+ availabilityPredicate);
}
/**
@@ -536,25 +519,20 @@
* so the switch from the inner display to the outer will become only when the device
* is fully closed.
*
- * @param identifier state identifier
- * @param name state name
- * @param flags state flags
+ * @param deviceState {@link DeviceState} that corresponds to this state.
* @param minClosedAngleDegrees minimum (inclusive) hinge angle value for the closed state
* @param maxClosedAngleDegrees maximum (non-inclusive) hinge angle value for the closed
* state
* @param tentModeSwitchAngleDegrees the angle when this state should switch when unfolding
* @return device state configuration
*/
- public static DeviceStateConfiguration createTentModeClosedState(
- @IntRange(from = MINIMUM_DEVICE_STATE_IDENTIFIER, to =
- MAXIMUM_DEVICE_STATE_IDENTIFIER) int identifier,
- @NonNull String name,
- @DeviceState.DeviceStateFlags int flags,
+ public static DeviceStatePredicateWrapper createTentModeClosedState(
+ @NonNull DeviceState deviceState,
int minClosedAngleDegrees,
int maxClosedAngleDegrees,
int tentModeSwitchAngleDegrees
) {
- return new DeviceStateConfiguration(new DeviceState(identifier, name, flags),
+ return new DeviceStatePredicateWrapper(deviceState,
(stateContext) -> {
final boolean hallSensorClosed = stateContext.isHallSensorClosed();
final float hingeAngle = stateContext.getHingeAngle();
@@ -564,9 +542,9 @@
final int switchingDegrees =
isScreenOn ? tentModeSwitchAngleDegrees : maxClosedAngleDegrees;
- final int closedDeviceState = identifier;
+ final int closedDeviceState = deviceState.getIdentifier();
final boolean isLastStateClosed = lastState == closedDeviceState
- || lastState == INVALID_DEVICE_STATE;
+ || lastState == INVALID_DEVICE_STATE_IDENTIFIER;
final boolean shouldBeClosedBecauseTentMode = isLastStateClosed
&& hingeAngle >= minClosedAngleDegrees
@@ -671,21 +649,21 @@
}
}
- private static boolean hasThermalSensitiveState(DeviceStateConfiguration[] deviceStates) {
+ private static boolean hasThermalSensitiveState(DeviceStatePredicateWrapper[] deviceStates) {
for (int i = 0; i < deviceStates.length; i++) {
- DeviceStateConfiguration state = deviceStates[i];
- if (state.mDeviceState
- .hasFlag(DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL)) {
+ DeviceStatePredicateWrapper state = deviceStates[i];
+ if (state.mDeviceState.hasProperty(
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL)) {
return true;
}
}
return false;
}
- private static boolean hasPowerSaveSensitiveState(DeviceStateConfiguration[] deviceStates) {
+ private static boolean hasPowerSaveSensitiveState(DeviceStatePredicateWrapper[] deviceStates) {
for (int i = 0; i < deviceStates.length; i++) {
- if (deviceStates[i].mDeviceState
- .hasFlag(DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE)) {
+ if (deviceStates[i].mDeviceState.hasProperty(
+ PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE)) {
return true;
}
}
diff --git a/services/foldables/devicestateprovider/tests/src/com/android/server/policy/FoldableDeviceStateProviderTest.java b/services/foldables/devicestateprovider/tests/src/com/android/server/policy/FoldableDeviceStateProviderTest.java
index 930f4a6..c9bbfee 100644
--- a/services/foldables/devicestateprovider/tests/src/com/android/server/policy/FoldableDeviceStateProviderTest.java
+++ b/services/foldables/devicestateprovider/tests/src/com/android/server/policy/FoldableDeviceStateProviderTest.java
@@ -30,7 +30,7 @@
import static com.android.server.devicestate.DeviceStateProvider.SUPPORTED_DEVICE_STATES_CHANGED_POWER_SAVE_ENABLED;
import static com.android.server.devicestate.DeviceStateProvider.SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_CRITICAL;
import static com.android.server.devicestate.DeviceStateProvider.SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_NORMAL;
-import static com.android.server.policy.FoldableDeviceStateProvider.DeviceStateConfiguration.createConfig;
+import static com.android.server.policy.FoldableDeviceStateProvider.DeviceStatePredicateWrapper.createConfig;
import static com.google.common.truth.Truth.assertThat;
@@ -59,8 +59,10 @@
import android.testing.AndroidTestingRunner;
import android.view.Display;
+import androidx.annotation.NonNull;
+
import com.android.server.devicestate.DeviceStateProvider.Listener;
-import com.android.server.policy.FoldableDeviceStateProvider.DeviceStateConfiguration;
+import com.android.server.policy.FoldableDeviceStateProvider.DeviceStatePredicateWrapper;
import com.android.server.policy.feature.flags.FakeFeatureFlagsImpl;
import com.android.server.policy.feature.flags.Flags;
@@ -73,6 +75,11 @@
import org.mockito.MockitoAnnotations;
import org.mockito.internal.util.reflection.FieldSetter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
/**
* Unit tests for {@link FoldableDeviceStateProvider}.
* <p/>
@@ -81,8 +88,14 @@
@RunWith(AndroidTestingRunner.class)
public final class FoldableDeviceStateProviderTest {
- private final ArgumentCaptor<DeviceState[]> mDeviceStateArrayCaptor = ArgumentCaptor.forClass(
- DeviceState[].class);
+ private static final Set<Integer> EMPTY_PROPERTY_SET = new HashSet<>();
+ private static final Set<Integer> THERMAL_PROPERTY_SET = new HashSet<>(
+ Arrays.asList(DeviceState.PROPERTY_EMULATED_ONLY,
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE));
+
+ private final ArgumentCaptor<DeviceState[]> mDeviceStateArrayCaptor =
+ ArgumentCaptor.forClass(DeviceState[].class);
@Captor
private ArgumentCaptor<Integer> mIntegerCaptor;
@Captor
@@ -122,22 +135,17 @@
public void create_duplicatedDeviceStateIdentifiers_throwsException() {
assertThrows(IllegalArgumentException.class,
() -> createProvider(
- createConfig(
- /* identifier= */ 0, /* name= */ "ONE", (c) -> true),
- createConfig(
- /* identifier= */ 0, /* name= */ "TWO", (c) -> true)
+ createConfig(createDeviceState(0, "ONE"), (c) -> true),
+ createConfig(createDeviceState(0, "TWO"), (c) -> true)
));
}
@Test
public void create_allMatchingStatesDefaultsToTheFirstIdentifier() {
createProvider(
- createConfig(
- /* identifier= */ 1, /* name= */ "ONE", (c) -> true),
- createConfig(
- /* identifier= */ 2, /* name= */ "TWO", (c) -> true),
- createConfig(
- /* identifier= */ 3, /* name= */ "THREE", (c) -> true)
+ createConfig(createDeviceState(1, "ONE"), (c) -> true),
+ createConfig(createDeviceState(2, "TWO"), (c) -> true),
+ createConfig(createDeviceState(3, "THREE"), (c) -> true)
);
Listener listener = mock(Listener.class);
@@ -146,9 +154,9 @@
verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
final DeviceState[] expectedStates = new DeviceState[]{
- new DeviceState(1, "ONE", /* flags= */ 0),
- new DeviceState(2, "TWO", /* flags= */ 0),
- new DeviceState(3, "THREE", /* flags= */ 0),
+ createDeviceState(1, "ONE", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "TWO", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "THREE", EMPTY_PROPERTY_SET)
};
assertArrayEquals(expectedStates, mDeviceStateArrayCaptor.getValue());
@@ -159,14 +167,10 @@
@Test
public void create_multipleMatchingStatesDefaultsToTheLowestIdentifier() {
createProvider(
- createConfig(
- /* identifier= */ 1, /* name= */ "ONE", (c) -> false),
- createConfig(
- /* identifier= */ 3, /* name= */ "THREE", (c) -> false),
- createConfig(
- /* identifier= */ 4, /* name= */ "FOUR", (c) -> true),
- createConfig(
- /* identifier= */ 2, /* name= */ "TWO", (c) -> true)
+ createConfig(createDeviceState(1, "ONE"), (c) -> false),
+ createConfig(createDeviceState(3, "THREE"), (c) -> false),
+ createConfig(createDeviceState(4, "FOUR"), (c) -> true),
+ createConfig(createDeviceState(2, "TWO"), (c) -> true)
);
Listener listener = mock(Listener.class);
@@ -178,9 +182,9 @@
@Test
public void test_hingeAngleUpdatedFirstTime_switchesToMatchingState() throws Exception {
- createProvider(createConfig(/* identifier= */ 1, /* name= */ "ONE",
+ createProvider(createConfig(createDeviceState(1, "ONE"),
(c) -> c.getHingeAngle() < 90f),
- createConfig(/* identifier= */ 2, /* name= */ "TWO",
+ createConfig(createDeviceState(2, "TWO"),
(c) -> c.getHingeAngle() >= 90f));
Listener listener = mock(Listener.class);
mProvider.setListener(listener);
@@ -195,9 +199,9 @@
@Test
public void test_hallSensorUpdatedFirstTime_switchesToMatchingState() throws Exception {
- createProvider(createConfig(/* identifier= */ 1, /* name= */ "ONE",
+ createProvider(createConfig(createDeviceState(1, "ONE"),
(c) -> !c.isHallSensorClosed()),
- createConfig(/* identifier= */ 2, /* name= */ "TWO",
+ createConfig(createDeviceState(2, "TWO"),
FoldableDeviceStateProvider::isHallSensorClosed));
Listener listener = mock(Listener.class);
mProvider.setListener(listener);
@@ -213,9 +217,9 @@
@Test
public void test_hingeAngleUpdatedSecondTime_switchesToMatchingState() throws Exception {
- createProvider(createConfig(/* identifier= */ 1, /* name= */ "ONE",
+ createProvider(createConfig(createDeviceState(1, "ONE"),
(c) -> c.getHingeAngle() < 90f),
- createConfig(/* identifier= */ 2, /* name= */ "TWO",
+ createConfig(createDeviceState(2, "TWO"),
(c) -> c.getHingeAngle() >= 90f));
sendSensorEvent(mHingeAngleSensor, /* value= */ 30f);
Listener listener = mock(Listener.class);
@@ -232,9 +236,9 @@
@Test
public void test_hallSensorUpdatedSecondTime_switchesToMatchingState() throws Exception {
- createProvider(createConfig(/* identifier= */ 1, /* name= */ "ONE",
+ createProvider(createConfig(createDeviceState(1, "ONE"),
(c) -> !c.isHallSensorClosed()),
- createConfig(/* identifier= */ 2, /* name= */ "TWO",
+ createConfig(createDeviceState(2, "TWO"),
FoldableDeviceStateProvider::isHallSensorClosed));
sendSensorEvent(mHallSensor, /* value= */ 0f);
Listener listener = mock(Listener.class);
@@ -252,9 +256,9 @@
@Test
public void test_invalidSensorValues_onStateChangedIsNotTriggered() throws Exception {
- createProvider(createConfig(/* identifier= */ 1, /* name= */ "ONE",
+ createProvider(createConfig(createDeviceState(1, "ONE"),
(c) -> c.getHingeAngle() < 90f),
- createConfig(/* identifier= */ 2, /* name= */ "TWO",
+ createConfig(createDeviceState(2, "TWO"),
(c) -> c.getHingeAngle() >= 90f));
Listener listener = mock(Listener.class);
mProvider.setListener(listener);
@@ -277,23 +281,21 @@
@Test
public void test_nullSensorValues_noExceptionThrown() throws Exception {
- createProvider(createConfig( /* identifier= */ 1, /* name= */ "ONE",
- (c) -> c.getHingeAngle() < 90f));
+ createProvider(createConfig(createDeviceState(1, "ONE"),
+ (c) -> c.getHingeAngle() < 90f));
sendInvalidSensorEvent(null);
}
@Test
public void test_flagDisableWhenThermalStatusCritical() throws Exception {
- createProvider(createConfig(/* identifier= */ 1, /* name= */ "CLOSED",
+ createProvider(createConfig(createDeviceState(1, "CLOSED"),
(c) -> c.getHingeAngle() < 5f),
- createConfig(/* identifier= */ 2, /* name= */ "HALF_OPENED",
+ createConfig(createDeviceState(2, "HALF_OPENED"),
(c) -> c.getHingeAngle() < 90f),
- createConfig(/* identifier= */ 3, /* name= */ "OPENED",
+ createConfig(createDeviceState(3, "OPENED"),
(c) -> c.getHingeAngle() < 180f),
- createConfig(/* identifier= */ 4, /* name= */ "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
+ createConfig(
+ createDeviceState(4, "THERMAL_TEST", THERMAL_PROPERTY_SET),
(c) -> true));
Listener listener = mock(Listener.class);
mProvider.setListener(listener);
@@ -301,13 +303,10 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE)},
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "THERMAL_TEST", THERMAL_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
clearInvocations(listener);
@@ -322,9 +321,9 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_CRITICAL));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */)},
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
clearInvocations(listener);
@@ -334,28 +333,23 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_NORMAL));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE)},
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "THERMAL_TEST", THERMAL_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
}
@Test
public void test_flagDisableWhenPowerSaveEnabled() throws Exception {
- createProvider(createConfig(/* identifier= */ 1, /* name= */ "CLOSED",
+ createProvider(createConfig(createDeviceState(1, "CLOSED"),
(c) -> c.getHingeAngle() < 5f),
- createConfig(/* identifier= */ 2, /* name= */ "HALF_OPENED",
+ createConfig(createDeviceState(2, "HALF_OPENED"),
(c) -> c.getHingeAngle() < 90f),
- createConfig(/* identifier= */ 3, /* name= */ "OPENED",
+ createConfig(createDeviceState(3, "OPENED"),
(c) -> c.getHingeAngle() < 180f),
- createConfig(/* identifier= */ 4, /* name= */ "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE,
+ createConfig(
+ createDeviceState(4, "THERMAL_TEST", THERMAL_PROPERTY_SET),
(c) -> true));
mProvider.onPowerSaveModeChanged(false /* isPowerSaveModeEnabled */);
Listener listener = mock(Listener.class);
@@ -365,13 +359,10 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "THERMAL_TEST", THERMAL_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
clearInvocations(listener);
@@ -386,9 +377,9 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_POWER_SAVE_ENABLED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
clearInvocations(listener);
@@ -398,13 +389,10 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_POWER_SAVE_DISABLED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "THERMAL_TEST", THERMAL_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
}
@@ -413,13 +401,11 @@
// Create a configuration where state TWO could be matched only if
// the previous state was 'THREE'
createProvider(
- createConfig(
- /* identifier= */ 1, /* name= */ "ONE", (c) -> c.getHingeAngle() < 30f),
- createConfig(
- /* identifier= */ 2, /* name= */ "TWO",
+ createConfig(createDeviceState(1, "ONE"),
+ (c) -> c.getHingeAngle() < 30f),
+ createConfig(createDeviceState(2, "TWO"),
(c) -> c.getLastReportedDeviceState() == 3 && c.getHingeAngle() > 120f),
- createConfig(
- /* identifier= */ 3, /* name= */ "THREE",
+ createConfig(createDeviceState(3, "THREE"),
(c) -> c.getHingeAngle() > 90f)
);
sendSensorEvent(mHingeAngleSensor, /* value= */ 0f);
@@ -448,8 +434,7 @@
@Test
public void isScreenOn_afterDisplayChangedToOn_returnsTrue() {
createProvider(
- createConfig(
- /* identifier= */ 1, /* name= */ "ONE", (c) -> true)
+ createConfig(createDeviceState(1, "ONE"), (c) -> true)
);
setScreenOn(true);
@@ -460,8 +445,7 @@
@Test
public void isScreenOn_afterDisplayChangedToOff_returnsFalse() {
createProvider(
- createConfig(
- /* identifier= */ 1, /* name= */ "ONE", (c) -> true)
+ createConfig(createDeviceState(1, "ONE"), (c) -> true)
);
setScreenOn(false);
@@ -472,8 +456,7 @@
@Test
public void isScreenOn_afterDisplayChangedToOnThenOff_returnsFalse() {
createProvider(
- createConfig(
- /* identifier= */ 1, /* name= */ "ONE", (c) -> true)
+ createConfig(createDeviceState(1, "ONE"), (c) -> true)
);
setScreenOn(true);
@@ -487,14 +470,14 @@
when(mDisplayManager.getDisplays()).thenReturn(new Display[]{mDefaultDisplay});
when(mDefaultDisplay.getType()).thenReturn(TYPE_INTERNAL);
- createProvider(createConfig(/* identifier= */ 1, /* name= */ "CLOSED",
+ createProvider(createConfig(createDeviceState(1, "CLOSED"),
(c) -> c.getHingeAngle() < 5f),
- createConfig(/* identifier= */ 2, /* name= */ "HALF_OPENED",
+ createConfig(createDeviceState(2, "HALF_OPENED"),
(c) -> c.getHingeAngle() < 90f),
- createConfig(/* identifier= */ 3, /* name= */ "OPENED",
+ createConfig(createDeviceState(3, "OPENED"),
(c) -> c.getHingeAngle() < 180f),
- createConfig(/* identifier= */ 4, /* name= */ "DUAL_DISPLAY", /* flags */ 0,
- (c) -> false, FoldableDeviceStateProvider::hasNoConnectedExternalDisplay));
+ createConfig(createDeviceState(4, "DUAL_DISPLAY"), (c) -> false,
+ FoldableDeviceStateProvider::hasNoConnectedExternalDisplay));
Listener listener = mock(Listener.class);
mProvider.setListener(listener);
@@ -502,10 +485,11 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
assertThat(mDeviceStateArrayCaptor.getValue()).asList().containsExactly(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "DUAL_DISPLAY", 0 /* flags */)}).inOrder();
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "DUAL_DISPLAY",
+ EMPTY_PROPERTY_SET)}).inOrder();
clearInvocations(listener);
@@ -520,9 +504,9 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_EXTERNAL_DISPLAY_ADDED));
assertThat(mDeviceStateArrayCaptor.getValue()).asList().containsExactly(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */)}).inOrder();
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET)}).inOrder();
clearInvocations(listener);
// The DUAL_DISPLAY state should be re-enabled.
@@ -532,10 +516,11 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_EXTERNAL_DISPLAY_REMOVED));
assertThat(mDeviceStateArrayCaptor.getValue()).asList().containsExactly(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "DUAL_DISPLAY", 0 /* flags */)}).inOrder();
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "DUAL_DISPLAY",
+ EMPTY_PROPERTY_SET)}).inOrder();
}
@Test
@@ -543,14 +528,14 @@
when(mDisplayManager.getDisplays()).thenReturn(new Display[]{mDefaultDisplay});
when(mDefaultDisplay.getType()).thenReturn(TYPE_INTERNAL);
- createProvider(createConfig(/* identifier= */ 1, /* name= */ "CLOSED",
+ createProvider(createConfig(createDeviceState(1, "CLOSED"),
(c) -> c.getHingeAngle() < 5f),
- createConfig(/* identifier= */ 2, /* name= */ "HALF_OPENED",
+ createConfig(createDeviceState(2, "HALF_OPENED"),
(c) -> c.getHingeAngle() < 90f),
- createConfig(/* identifier= */ 3, /* name= */ "OPENED",
+ createConfig(createDeviceState(3, "OPENED"),
(c) -> c.getHingeAngle() < 180f),
- createConfig(/* identifier= */ 4, /* name= */ "DUAL_DISPLAY", /* flags */ 0,
- (c) -> false, FoldableDeviceStateProvider::hasNoConnectedExternalDisplay));
+ createConfig(createDeviceState(4, "DUAL_DISPLAY"),
+ FoldableDeviceStateProvider::hasNoConnectedExternalDisplay));
Listener listener = mock(Listener.class);
mProvider.setListener(listener);
@@ -558,10 +543,11 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
assertThat(mDeviceStateArrayCaptor.getValue()).asList().containsExactly(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "DUAL_DISPLAY", 0 /* flags */)}).inOrder();
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "DUAL_DISPLAY",
+ EMPTY_PROPERTY_SET)}).inOrder();
clearInvocations(listener);
@@ -579,10 +565,8 @@
@Test
public void hasNoConnectedDisplay_afterExternalDisplayAdded_returnsFalse() {
createProvider(
- createConfig(
- /* identifier= */ 1, /* name= */ "ONE",
- /* flags= */0, (c) -> true,
- FoldableDeviceStateProvider::hasNoConnectedExternalDisplay)
+ createConfig(createDeviceState(1, "ONE", Collections.emptySet()),
+ (c) -> true, FoldableDeviceStateProvider::hasNoConnectedExternalDisplay)
);
addExternalDisplay(/* displayId */ 1);
@@ -594,9 +578,8 @@
public void testOnDisplayAddedWithNullDisplayDoesNotThrowNPE() {
createProvider(
createConfig(
- /* identifier= */ 1, /* name= */ "ONE",
- /* flags= */0, (c) -> true,
- FoldableDeviceStateProvider::hasNoConnectedExternalDisplay)
+ createDeviceState(1, "ONE", Collections.emptySet()),
+ (c) -> true, FoldableDeviceStateProvider::hasNoConnectedExternalDisplay)
);
when(mDisplayManager.getDisplay(1)).thenReturn(null);
@@ -608,9 +591,8 @@
public void hasNoConnectedDisplay_afterExternalDisplayAddedAndRemoved_returnsTrue() {
createProvider(
createConfig(
- /* identifier= */ 1, /* name= */ "ONE",
- /* flags= */0, (c) -> true,
- FoldableDeviceStateProvider::hasNoConnectedExternalDisplay)
+ createDeviceState(1, "ONE", Collections.emptySet()),
+ (c) -> true, FoldableDeviceStateProvider::hasNoConnectedExternalDisplay)
);
addExternalDisplay(/* displayId */ 1);
@@ -657,7 +639,7 @@
mProvider.onSensorChanged(event);
}
- private void createProvider(DeviceStateConfiguration... configurations) {
+ private void createProvider(DeviceStatePredicateWrapper... configurations) {
mProvider = new FoldableDeviceStateProvider(mFakeFeatureFlags, mContext, mSensorManager,
mHingeAngleSensor, mHallSensor, mDisplayManager, configurations);
verify(mDisplayManager)
@@ -665,4 +647,23 @@
mDisplayListenerCaptor.capture(),
nullable(Handler.class));
}
+
+ /**
+ * Returns a new {@link DeviceState} object
+ */
+ private DeviceState createDeviceState(int identifier,
+ @NonNull String name,
+ @NonNull Set<@DeviceState.DeviceStateProperties Integer> systemProperties) {
+ return new DeviceState(new DeviceState.Configuration.Builder(identifier, name)
+ .setSystemProperties(systemProperties)
+ .build());
+ }
+
+ /**
+ * Returns a new {@link DeviceState} object
+ */
+ private DeviceState createDeviceState(int identifier,
+ @NonNull String name) {
+ return createDeviceState(identifier, name, Collections.emptySet());
+ }
}
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
index c5c921d..7c75138 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionFlags.kt
@@ -477,9 +477,7 @@
if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT)) {
flags = flags or UPGRADE_EXEMPT
}
- // We ignore whether FLAG_PERMISSION_APPLY_RESTRICTION is set here because previously
- // platform may be relying on the old restorePermissionState() to get it correct later.
- if (!flags.hasAnyBit(MASK_EXEMPT)) {
+ if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION)) {
if (permission.isHardRestricted) {
flags = flags or RESTRICTION_REVOKED
}
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/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
index bed6f92..2939192 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -16,7 +16,7 @@
package com.android.server.display;
-import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY_GROUP;
import static android.view.Display.FLAG_REAR;
@@ -674,7 +674,7 @@
/* isInteractive= */true,
/* isBootCompleted= */true));
assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
- INVALID_DEVICE_STATE,
+ INVALID_DEVICE_STATE_IDENTIFIER,
/* isOverrideActive= */false,
/* isInteractive= */true,
/* isBootCompleted= */true));
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 fff08c4..a2756ff 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -100,7 +100,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;
@@ -127,6 +127,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
@@ -1748,6 +1751,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/backup/PackageManagerBackupAgentTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/PackageManagerBackupAgentTest.java
new file mode 100644
index 0000000..d1b6de0
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/PackageManagerBackupAgentTest.java
@@ -0,0 +1,288 @@
+/*
+ * 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.backup;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.ParcelFileDescriptor;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.nio.ByteBuffer;
+import java.util.Optional;
+
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class PackageManagerBackupAgentTest {
+
+ private static final String EXISTING_PACKAGE_NAME = "com.android.wallpaperbackup";
+ private static final int USER_ID = 0;
+
+ @Rule public TemporaryFolder folder = new TemporaryFolder();
+
+ private PackageManagerBackupAgent mPackageManagerBackupAgent;
+ private ImmutableList<PackageInfo> mPackages;
+ private File mBackupData, mOldState, mNewState;
+
+ @Before
+ public void setUp() throws Exception {
+ PackageManager packageManager = getApplicationContext().getPackageManager();
+
+ PackageInfo existingPackageInfo =
+ packageManager.getPackageInfoAsUser(
+ EXISTING_PACKAGE_NAME, PackageManager.GET_SIGNING_CERTIFICATES, USER_ID);
+ mPackages = ImmutableList.of(existingPackageInfo);
+ mPackageManagerBackupAgent =
+ new PackageManagerBackupAgent(packageManager, mPackages, USER_ID);
+
+ mBackupData = folder.newFile("backup_data");
+ mOldState = folder.newFile("old_state");
+ mNewState = folder.newFile("new_state");
+ }
+
+ @Test
+ public void onBackup_noState_backsUpEverything() throws Exception {
+ // no setup needed
+
+ runBackupAgentOnBackup();
+
+ // key/values should be written to backup data
+ ImmutableMap<String, Optional<ByteBuffer>> keyValues = getKeyValues(mBackupData);
+ assertThat(keyValues.keySet())
+ .containsExactly(
+ PackageManagerBackupAgent.ANCESTRAL_RECORD_KEY,
+ PackageManagerBackupAgent.GLOBAL_METADATA_KEY,
+ EXISTING_PACKAGE_NAME)
+ .inOrder();
+ // new state must not be empty
+ assertThat(mNewState.length()).isGreaterThan(0);
+ }
+
+ @Test
+ public void onBackup_recentState_backsUpNothing() throws Exception {
+ try (ParcelFileDescriptor oldStateDescriptor = openForWriting(mOldState)) {
+ PackageManagerBackupAgent.writeStateFile(mPackages, oldStateDescriptor);
+ }
+
+ runBackupAgentOnBackup();
+
+ // We shouldn't have written anything, but a known issue is that we always write the
+ // ancestral record version.
+ ImmutableMap<String, Optional<ByteBuffer>> keyValues = getKeyValues(mBackupData);
+ assertThat(keyValues.keySet())
+ .containsExactly(PackageManagerBackupAgent.ANCESTRAL_RECORD_KEY);
+ assertThat(mNewState.length()).isGreaterThan(0);
+ assertThat(mNewState.length()).isEqualTo(mOldState.length());
+ }
+
+ @Test
+ public void onBackup_oldState_backsUpChanges() throws Exception {
+ String uninstalledPackageName = "does.not.exist";
+ try (ParcelFileDescriptor oldStateDescriptor = openForWriting(mOldState)) {
+ PackageManagerBackupAgent.writeStateFile(
+ ImmutableList.of(createPackage(uninstalledPackageName, 1)), oldStateDescriptor);
+ }
+
+ runBackupAgentOnBackup();
+
+ // Note that uninstalledPackageName should not exist, i.e. it did not get deleted.
+ ImmutableMap<String, Optional<ByteBuffer>> keyValues = getKeyValues(mBackupData);
+ assertThat(keyValues.keySet())
+ .containsExactly(
+ PackageManagerBackupAgent.ANCESTRAL_RECORD_KEY, EXISTING_PACKAGE_NAME);
+ assertThat(mNewState.length()).isGreaterThan(0);
+ }
+
+ @Test
+ public void onBackup_legacyState_backsUpEverything() throws Exception {
+ String uninstalledPackageName = "does.not.exist";
+ writeLegacyStateFile(
+ mOldState,
+ ImmutableList.of(createPackage(uninstalledPackageName, 1), mPackages.getFirst()));
+
+ runBackupAgentOnBackup();
+
+ ImmutableMap<String, Optional<ByteBuffer>> keyValues = getKeyValues(mBackupData);
+ assertThat(keyValues.keySet())
+ .containsExactly(
+ PackageManagerBackupAgent.ANCESTRAL_RECORD_KEY,
+ PackageManagerBackupAgent.GLOBAL_METADATA_KEY,
+ EXISTING_PACKAGE_NAME);
+ assertThat(mNewState.length()).isGreaterThan(0);
+ }
+
+ @Test
+ public void onRestore_recentBackup_restoresBackup() throws Exception {
+ runBackupAgentOnBackup();
+
+ runBackupAgentOnRestore();
+
+ assertThat(mPackageManagerBackupAgent.getRestoredPackages())
+ .containsExactly(EXISTING_PACKAGE_NAME);
+ // onRestore does not write to newState
+ assertThat(mNewState.length()).isEqualTo(0);
+ }
+
+ @Test
+ public void onRestore_legacyBackup_restoresBackup() throws Exception {
+ // A legacy backup is one without an ancestral record version. Ancestral record versions
+ // are always written however, so we'll need to delete it from the backup data before
+ // restoring.
+ runBackupAgentOnBackup();
+ deleteKeyFromBackupData(mBackupData, PackageManagerBackupAgent.ANCESTRAL_RECORD_KEY);
+
+ runBackupAgentOnRestore();
+
+ assertThat(mPackageManagerBackupAgent.getRestoredPackages())
+ .containsExactly(EXISTING_PACKAGE_NAME);
+ // onRestore does not write to newState
+ assertThat(mNewState.length()).isEqualTo(0);
+ }
+
+ private void runBackupAgentOnBackup() throws Exception {
+ try (ParcelFileDescriptor oldStateDescriptor = openForReading(mOldState);
+ ParcelFileDescriptor backupDataDescriptor = openForWriting(mBackupData);
+ ParcelFileDescriptor newStateDescriptor = openForWriting(mNewState)) {
+ mPackageManagerBackupAgent.onBackup(
+ oldStateDescriptor,
+ new BackupDataOutput(backupDataDescriptor.getFileDescriptor()),
+ newStateDescriptor);
+ }
+ }
+
+ private void runBackupAgentOnRestore() throws Exception {
+ try (ParcelFileDescriptor backupDataDescriptor = openForReading(mBackupData);
+ ParcelFileDescriptor newStateDescriptor = openForWriting(mNewState)) {
+ mPackageManagerBackupAgent.onRestore(
+ new BackupDataInput(backupDataDescriptor.getFileDescriptor()),
+ /* appVersionCode= */ 0,
+ newStateDescriptor);
+ }
+ }
+
+ private void deleteKeyFromBackupData(File backupData, String key) throws Exception {
+ File temporaryBackupData = folder.newFile("backup_data.tmp");
+ try (ParcelFileDescriptor inputDescriptor = openForReading(backupData);
+ ParcelFileDescriptor outputDescriptor = openForWriting(temporaryBackupData); ) {
+ BackupDataInput input = new BackupDataInput(inputDescriptor.getFileDescriptor());
+ BackupDataOutput output = new BackupDataOutput(outputDescriptor.getFileDescriptor());
+ while (input.readNextHeader()) {
+ if (input.getKey().equals(key)) {
+ if (input.getDataSize() > 0) {
+ input.skipEntityData();
+ }
+ continue;
+ }
+ output.writeEntityHeader(input.getKey(), input.getDataSize());
+ if (input.getDataSize() < 0) {
+ input.skipEntityData();
+ } else {
+ byte[] buf = new byte[input.getDataSize()];
+ input.readEntityData(buf, 0, buf.length);
+ output.writeEntityData(buf, buf.length);
+ }
+ }
+ }
+ assertThat(temporaryBackupData.renameTo(backupData)).isTrue();
+ }
+
+ private static PackageInfo createPackage(String name, int versionCode) {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = name;
+ packageInfo.versionCodeMajor = versionCode;
+ return packageInfo;
+ }
+
+ /** This creates a legacy state file in which {@code STATE_FILE_HEADER} was not yet present. */
+ private static void writeLegacyStateFile(File stateFile, ImmutableList<PackageInfo> packages)
+ throws Exception {
+ try (ParcelFileDescriptor stateFileDescriptor = openForWriting(stateFile);
+ DataOutputStream out =
+ new DataOutputStream(
+ new BufferedOutputStream(
+ new FileOutputStream(
+ stateFileDescriptor.getFileDescriptor())))) {
+ out.writeUTF(PackageManagerBackupAgent.GLOBAL_METADATA_KEY);
+ out.writeInt(Build.VERSION.SDK_INT);
+ out.writeUTF(Build.VERSION.INCREMENTAL);
+
+ // now write all the app names + versions
+ for (PackageInfo pkg : packages) {
+ out.writeUTF(pkg.packageName);
+ out.writeInt(pkg.versionCode);
+ }
+ out.flush();
+ }
+ }
+
+ /**
+ * Reads the given backup data file and returns a map of key-value pairs. The value is a {@link
+ * ByteBuffer} wrapped in an {@link Optional}, where the empty {@link Optional} represents a key
+ * deletion.
+ */
+ private static ImmutableMap<String, Optional<ByteBuffer>> getKeyValues(File backupData)
+ throws Exception {
+ ImmutableMap.Builder<String, Optional<ByteBuffer>> builder = ImmutableMap.builder();
+ try (ParcelFileDescriptor backupDataDescriptor = openForReading(backupData)) {
+ BackupDataInput backupDataInput =
+ new BackupDataInput(backupDataDescriptor.getFileDescriptor());
+ while (backupDataInput.readNextHeader()) {
+ ByteBuffer value = null;
+ if (backupDataInput.getDataSize() >= 0) {
+ byte[] val = new byte[backupDataInput.getDataSize()];
+ backupDataInput.readEntityData(val, 0, val.length);
+ value = ByteBuffer.wrap(val);
+ }
+ builder.put(backupDataInput.getKey(), Optional.ofNullable(value));
+ }
+ }
+ return builder.build();
+ }
+
+ private static ParcelFileDescriptor openForWriting(File file) throws Exception {
+ return ParcelFileDescriptor.open(
+ file,
+ ParcelFileDescriptor.MODE_CREATE
+ | ParcelFileDescriptor.MODE_TRUNCATE
+ | ParcelFileDescriptor.MODE_WRITE_ONLY);
+ }
+
+ private static ParcelFileDescriptor openForReading(File file) throws Exception {
+ return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 95cfc2a..7ea722b 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -61,7 +61,9 @@
import android.graphics.drawable.Icon;
import android.hardware.display.DisplayManagerGlobal;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
import android.os.LocaleList;
import android.os.UserHandle;
@@ -70,20 +72,28 @@
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
+import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
+import android.testing.TestableLooper;
import android.util.ArraySet;
import android.view.Display;
import android.view.DisplayAdjustments;
import android.view.DisplayInfo;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityWindowAttributes;
+import android.view.accessibility.IAccessibilityManager;
-import androidx.test.InstrumentationRegistry;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.TestUtils;
import com.android.internal.R;
+import com.android.internal.accessibility.common.ShortcutConstants;
+import com.android.internal.accessibility.common.ShortcutConstants.FloatingMenuSize;
+import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
+import com.android.internal.accessibility.util.AccessibilityUtils;
+import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.internal.compat.IPlatformCompat;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService.AccessibilityDisplayListener;
@@ -91,31 +101,38 @@
import com.android.server.accessibility.magnification.MagnificationConnectionManager;
import com.android.server.accessibility.magnification.MagnificationController;
import com.android.server.accessibility.magnification.MagnificationProcessor;
-import com.android.server.accessibility.test.MessageCapturingHandler;
import com.android.server.pm.UserManagerInternal;
+import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import org.mockito.internal.util.reflection.FieldReader;
+import org.mockito.internal.util.reflection.FieldSetter;
import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
* APCT tests for {@link AccessibilityManagerService}.
*/
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
public class AccessibilityManagerServiceTest {
@Rule
public final A11yTestableContext mTestableContext = new A11yTestableContext(
@@ -140,6 +157,12 @@
TEST_PENDING_INTENT);
private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY + 1;
+ private static final String TARGET_MAGNIFICATION = MAGNIFICATION_CONTROLLER_NAME;
+ private static final ComponentName TARGET_ALWAYS_ON_A11Y_SERVICE =
+ new ComponentName("FakePackage", "AlwaysOnA11yService");
+ private static final String TARGET_ALWAYS_ON_A11Y_SERVICE_TILE_CLASS = "TileService";
+ private static final ComponentName TARGET_STANDARD_A11Y_SERVICE =
+ new ComponentName("FakePackage", "StandardA11yService");
static final ComponentName COMPONENT_NAME = new ComponentName(
"com.android.server.accessibility", "AccessibilityManagerServiceTest");
@@ -163,24 +186,33 @@
@Mock private MagnificationController mMockMagnificationController;
@Mock private FullScreenMagnificationController mMockFullScreenMagnificationController;
@Mock private ProxyManager mProxyManager;
+ @Mock private StatusBarManagerInternal mStatusBarManagerInternal;
@Captor private ArgumentCaptor<Intent> mIntentArgumentCaptor;
- private MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
+ private IAccessibilityManager mA11yManagerServiceOnDevice;
private AccessibilityServiceConnection mAccessibilityServiceConnection;
private AccessibilityInputFilter mInputFilter;
private AccessibilityManagerService mA11yms;
+ private TestableLooper mTestableLooper;
+ private Handler mHandler;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mTestableLooper = TestableLooper.get(this);
+ mHandler = new Handler(mTestableLooper.getLooper());
+
LocalServices.removeServiceForTest(WindowManagerInternal.class);
LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class);
LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
LocalServices.addService(
WindowManagerInternal.class, mMockWindowManagerService);
LocalServices.addService(
ActivityTaskManagerInternal.class, mMockActivityTaskManagerInternal);
LocalServices.addService(
UserManagerInternal.class, mMockUserManagerInternal);
+ LocalServices.addService(
+ StatusBarManagerInternal.class, mStatusBarManagerInternal);
mInputFilter = Mockito.mock(FakeInputFilter.class);
when(mMockMagnificationController.getMagnificationConnectionManager()).thenReturn(
@@ -218,6 +250,19 @@
final AccessibilityUserState userState = new AccessibilityUserState(
mA11yms.getCurrentUserIdLocked(), mTestableContext, mA11yms);
mA11yms.mUserStates.put(mA11yms.getCurrentUserIdLocked(), userState);
+ AccessibilityManager am = mTestableContext.getSystemService(AccessibilityManager.class);
+ mA11yManagerServiceOnDevice = (IAccessibilityManager) new FieldReader(am,
+ AccessibilityManager.class.getDeclaredField("mService")).read();
+ FieldSetter.setField(am, AccessibilityManager.class.getDeclaredField("mService"), mA11yms);
+ }
+
+ @After
+ public void cleanUp() throws Exception {
+ mTestableLooper.processAllMessages();
+ AccessibilityManager am = mTestableContext.getSystemService(AccessibilityManager.class);
+ FieldSetter.setField(
+ am, AccessibilityManager.class.getDeclaredField("mService"),
+ mA11yManagerServiceOnDevice);
}
private void setupAccessibilityServiceConnection(int serviceInfoFlag) {
@@ -297,7 +342,8 @@
mA11yms.getCurrentUserIdLocked());
mA11yms.notifySystemActionsChangedLocked(userState);
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ mTestableLooper.processAllMessages();
+
verify(mMockServiceClient).onSystemActionsChanged();
}
@@ -415,7 +461,7 @@
);
mA11yms.onMagnificationTransitionEndedLocked(Display.DEFAULT_DISPLAY, true);
- mHandler.sendAllMessages();
+ mTestableLooper.processAllMessages();
ArgumentCaptor<Display> displayCaptor = ArgumentCaptor.forClass(Display.class);
verify(mInputFilter, timeout(100)).refreshMagnificationMode(displayCaptor.capture());
@@ -730,7 +776,7 @@
mA11yms.performAccessibilityShortcut(
ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString());
- mHandler.sendAllMessages();
+ mTestableLooper.processAllMessages();
assertStartActivityWithExpectedComponentName(mTestableContext.getMockContext(),
ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString());
@@ -907,11 +953,14 @@
public void testIsAccessibilityServiceWarningRequired_notRequiredIfAllowlisted() {
mockManageAccessibilityGranted(mTestableContext);
final AccessibilityServiceInfo info_a = mockAccessibilityServiceInfo(
- new ComponentName("package_a", "class_a"), true);
+ new ComponentName("package_a", "class_a"),
+ /* isSystemApp= */ true, /* isAlwaysOnService= */ false);
final AccessibilityServiceInfo info_b = mockAccessibilityServiceInfo(
- new ComponentName("package_b", "class_b"), false);
+ new ComponentName("package_b", "class_b"),
+ /* isSystemApp= */ false, /* isAlwaysOnService= */ false);
final AccessibilityServiceInfo info_c = mockAccessibilityServiceInfo(
- new ComponentName("package_c", "class_c"), true);
+ new ComponentName("package_c", "class_c"),
+ /* isSystemApp= */ true, /* isAlwaysOnService= */ false);
mTestableContext.getOrCreateTestableResources().addOverride(
R.array.config_trustedAccessibilityServices,
new String[]{
@@ -926,14 +975,380 @@
assertThat(mA11yms.isAccessibilityServiceWarningRequired(info_c)).isFalse();
}
+ @Test
+ public void enableShortcutsForTargets_permissionNotGranted_throwsException() {
+ mTestableContext.getTestablePermissions().setPermission(
+ Manifest.permission.MANAGE_ACCESSIBILITY, PackageManager.PERMISSION_DENIED);
+
+ assertThrows(SecurityException.class,
+ () -> mA11yms.enableShortcutsForTargets(
+ /* enable= */true,
+ UserShortcutType.SOFTWARE,
+ List.of(TARGET_MAGNIFICATION),
+ mA11yms.getCurrentUserIdLocked()));
+ }
+
+ @Test
+ public void enableShortcutsForTargets_enableSoftwareShortcut_shortcutTurnedOn()
+ throws Exception {
+ mockManageAccessibilityGranted(mTestableContext);
+ setupShortcutTargetServices();
+ String target = TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ true,
+ UserShortcutType.SOFTWARE,
+ List.of(target),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(ShortcutUtils.isComponentIdExistingInSettings(
+ mTestableContext, UserShortcutType.SOFTWARE, target
+ )).isTrue();
+ }
+
+ @Test
+ public void enableShortcutsForTargets_disableSoftwareShortcut_shortcutTurnedOff()
+ throws Exception {
+ String target = TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString();
+ enableShortcutsForTargets_enableSoftwareShortcut_shortcutTurnedOn();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ false,
+ UserShortcutType.SOFTWARE,
+ List.of(target),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(ShortcutUtils.isComponentIdExistingInSettings(
+ mTestableContext, UserShortcutType.SOFTWARE, target
+ )).isFalse();
+ }
+
+ @Test
+ public void enableShortcutsForTargets_enableSoftwareShortcutWithMagnification_menuSizeIncreased() {
+ mockManageAccessibilityGranted(mTestableContext);
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ true,
+ UserShortcutType.SOFTWARE,
+ List.of(MAGNIFICATION_CONTROLLER_NAME),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ Settings.Secure.getInt(
+ mTestableContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
+ FloatingMenuSize.UNKNOWN))
+ .isEqualTo(FloatingMenuSize.LARGE);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_enableSoftwareShortcutWithMagnification_userConfigureSmallMenuSize_menuSizeNotChanged() {
+ mockManageAccessibilityGranted(mTestableContext);
+ Settings.Secure.putInt(
+ mTestableContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
+ FloatingMenuSize.SMALL);
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ true,
+ UserShortcutType.SOFTWARE,
+ List.of(MAGNIFICATION_CONTROLLER_NAME),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ Settings.Secure.getInt(
+ mTestableContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
+ FloatingMenuSize.UNKNOWN))
+ .isEqualTo(FloatingMenuSize.SMALL);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_enableAlwaysOnServiceSoftwareShortcut_turnsOnAlwaysOnService()
+ throws Exception {
+ mockManageAccessibilityGranted(mTestableContext);
+ setupShortcutTargetServices();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ true,
+ UserShortcutType.SOFTWARE,
+ List.of(TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString()),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ AccessibilityUtils.getEnabledServicesFromSettings(
+ mTestableContext,
+ mA11yms.getCurrentUserIdLocked())
+ ).contains(TARGET_ALWAYS_ON_A11Y_SERVICE);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_disableAlwaysOnServiceSoftwareShortcut_turnsOffAlwaysOnService()
+ throws Exception {
+ enableShortcutsForTargets_enableAlwaysOnServiceSoftwareShortcut_turnsOnAlwaysOnService();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ false,
+ UserShortcutType.SOFTWARE,
+ List.of(TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString()),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ AccessibilityUtils.getEnabledServicesFromSettings(
+ mTestableContext,
+ mA11yms.getCurrentUserIdLocked())
+ ).doesNotContain(TARGET_ALWAYS_ON_A11Y_SERVICE);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_enableStandardServiceSoftwareShortcut_wontTurnOnService()
+ throws Exception {
+ mockManageAccessibilityGranted(mTestableContext);
+ setupShortcutTargetServices();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ true,
+ UserShortcutType.SOFTWARE,
+ List.of(TARGET_STANDARD_A11Y_SERVICE.flattenToString()),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ AccessibilityUtils.getEnabledServicesFromSettings(
+ mTestableContext,
+ mA11yms.getCurrentUserIdLocked())
+ ).doesNotContain(TARGET_STANDARD_A11Y_SERVICE);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_disableStandardServiceSoftwareShortcutWithServiceOn_wontTurnOffService()
+ throws Exception {
+ enableShortcutsForTargets_enableStandardServiceSoftwareShortcut_wontTurnOnService();
+ AccessibilityUtils.setAccessibilityServiceState(
+ mTestableContext, TARGET_STANDARD_A11Y_SERVICE, /* enabled= */ true);
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ false,
+ UserShortcutType.SOFTWARE,
+ List.of(TARGET_STANDARD_A11Y_SERVICE.flattenToString()),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ AccessibilityUtils.getEnabledServicesFromSettings(
+ mTestableContext,
+ mA11yms.getCurrentUserIdLocked())
+ ).contains(TARGET_STANDARD_A11Y_SERVICE);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_enableTripleTapShortcut_settingUpdated() {
+ mockManageAccessibilityGranted(mTestableContext);
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ true,
+ UserShortcutType.TRIPLETAP,
+ List.of(TARGET_MAGNIFICATION),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ Settings.Secure.getInt(
+ mTestableContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+ AccessibilityUtils.State.OFF)
+ ).isEqualTo(AccessibilityUtils.State.ON);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_disableTripleTapShortcut_settingUpdated() {
+ enableShortcutsForTargets_enableTripleTapShortcut_settingUpdated();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ false,
+ UserShortcutType.TRIPLETAP,
+ List.of(TARGET_MAGNIFICATION),
+ mA11yms.getCurrentUserIdLocked());
+
+ assertThat(
+ Settings.Secure.getInt(
+ mTestableContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+ AccessibilityUtils.State.OFF)
+ ).isEqualTo(AccessibilityUtils.State.OFF);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_enableMultiFingerMultiTapsShortcut_settingUpdated() {
+ mockManageAccessibilityGranted(mTestableContext);
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ true,
+ UserShortcutType.TWOFINGER_DOUBLETAP,
+ List.of(TARGET_MAGNIFICATION),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ Settings.Secure.getInt(
+ mTestableContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED,
+ AccessibilityUtils.State.OFF)
+ ).isEqualTo(AccessibilityUtils.State.ON);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_disableMultiFingerMultiTapsShortcut_settingUpdated() {
+ enableShortcutsForTargets_enableMultiFingerMultiTapsShortcut_settingUpdated();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ false,
+ UserShortcutType.TWOFINGER_DOUBLETAP,
+ List.of(TARGET_MAGNIFICATION),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ Settings.Secure.getInt(
+ mTestableContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED,
+ AccessibilityUtils.State.OFF)
+ ).isEqualTo(AccessibilityUtils.State.OFF);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_enableVolumeKeysShortcut_shortcutSet() {
+ mockManageAccessibilityGranted(mTestableContext);
+ setupShortcutTargetServices();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ true,
+ UserShortcutType.HARDWARE,
+ List.of(TARGET_STANDARD_A11Y_SERVICE.flattenToString()),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ ShortcutUtils.isComponentIdExistingInSettings(
+ mTestableContext, ShortcutConstants.UserShortcutType.HARDWARE,
+ TARGET_STANDARD_A11Y_SERVICE.flattenToString())
+ ).isTrue();
+ }
+
+ @Test
+ public void enableShortcutsForTargets_disableVolumeKeysShortcut_shortcutNotSet() {
+ enableShortcutsForTargets_enableVolumeKeysShortcut_shortcutSet();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ false,
+ UserShortcutType.HARDWARE,
+ List.of(TARGET_STANDARD_A11Y_SERVICE.flattenToString()),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ ShortcutUtils.isComponentIdExistingInSettings(
+ mTestableContext, ShortcutConstants.UserShortcutType.HARDWARE,
+ TARGET_STANDARD_A11Y_SERVICE.flattenToString())
+ ).isFalse();
+ }
+
+ @Test
+ public void enableShortcutsForTargets_enableQuickSettings_shortcutSet() {
+ mockManageAccessibilityGranted(mTestableContext);
+ setupShortcutTargetServices();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ true,
+ UserShortcutType.QUICK_SETTINGS,
+ List.of(TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString()),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ ShortcutUtils.isComponentIdExistingInSettings(
+ mTestableContext, UserShortcutType.QUICK_SETTINGS,
+ TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString())
+ ).isTrue();
+ verify(mStatusBarManagerInternal)
+ .addQsTileToFrontOrEnd(
+ new ComponentName(
+ TARGET_ALWAYS_ON_A11Y_SERVICE.getPackageName(),
+ TARGET_ALWAYS_ON_A11Y_SERVICE_TILE_CLASS),
+ /* end= */ true);
+ }
+
+ @Test
+ public void enableShortcutsForTargets_disableQuickSettings_shortcutNotSet() {
+ enableShortcutsForTargets_enableQuickSettings_shortcutSet();
+
+ mA11yms.enableShortcutsForTargets(
+ /* enable= */ false,
+ UserShortcutType.QUICK_SETTINGS,
+ List.of(TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString()),
+ mA11yms.getCurrentUserIdLocked());
+ mTestableLooper.processAllMessages();
+
+ assertThat(
+ ShortcutUtils.isComponentIdExistingInSettings(
+ mTestableContext, UserShortcutType.QUICK_SETTINGS,
+ TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString())
+ ).isFalse();
+ verify(mStatusBarManagerInternal)
+ .removeQsTile(
+ new ComponentName(
+ TARGET_ALWAYS_ON_A11Y_SERVICE.getPackageName(),
+ TARGET_ALWAYS_ON_A11Y_SERVICE_TILE_CLASS));
+ }
+
+ @Test
+ public void getA11yFeatureToTileMap_permissionNotGranted_throwsException() {
+ mTestableContext.getTestablePermissions().setPermission(
+ Manifest.permission.MANAGE_ACCESSIBILITY, PackageManager.PERMISSION_DENIED);
+
+ assertThrows(SecurityException.class,
+ () -> mA11yms.getA11yFeatureToTileMap(mA11yms.getCurrentUserIdLocked()));
+ }
+
+ @Test
+ public void getA11yFeatureToTileMap() {
+ mockManageAccessibilityGranted(mTestableContext);
+ setupShortcutTargetServices();
+
+ Bundle bundle = mA11yms.getA11yFeatureToTileMap(mA11yms.getCurrentUserIdLocked());
+
+ // Framework tile size + TARGET_ALWAYS_ON_A11Y_SERVICE_TILE_CLASS
+ assertThat(bundle.size())
+ .isEqualTo(ShortcutConstants.A11Y_FEATURE_TO_FRAMEWORK_TILE.size() + 1);
+ assertThat(
+ bundle.getParcelable(TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString(),
+ ComponentName.class)
+ ).isEqualTo(
+ new ComponentName(
+ TARGET_ALWAYS_ON_A11Y_SERVICE.getPackageName(),
+ TARGET_ALWAYS_ON_A11Y_SERVICE_TILE_CLASS));
+ for (Map.Entry<ComponentName, ComponentName> entry :
+ ShortcutConstants.A11Y_FEATURE_TO_FRAMEWORK_TILE.entrySet()) {
+ assertThat(bundle.getParcelable(entry.getKey().flattenToString(), ComponentName.class))
+ .isEqualTo(entry.getValue());
+ }
+ }
+
private static AccessibilityServiceInfo mockAccessibilityServiceInfo(
ComponentName componentName) {
- return mockAccessibilityServiceInfo(componentName, false);
+ return mockAccessibilityServiceInfo(
+ componentName, /* isSystemApp= */ false, /* isAlwaysOnService=*/ false);
}
private static AccessibilityServiceInfo mockAccessibilityServiceInfo(
ComponentName componentName,
- boolean isSystemApp) {
+ boolean isSystemApp, boolean isAlwaysOnService) {
AccessibilityServiceInfo accessibilityServiceInfo =
Mockito.spy(new AccessibilityServiceInfo());
accessibilityServiceInfo.setComponentName(componentName);
@@ -941,7 +1356,15 @@
when(accessibilityServiceInfo.getResolveInfo()).thenReturn(mockResolveInfo);
mockResolveInfo.serviceInfo = Mockito.mock(ServiceInfo.class);
mockResolveInfo.serviceInfo.applicationInfo = Mockito.mock(ApplicationInfo.class);
+ mockResolveInfo.serviceInfo.packageName = componentName.getPackageName();
+ mockResolveInfo.serviceInfo.name = componentName.getClassName();
when(mockResolveInfo.serviceInfo.applicationInfo.isSystemApp()).thenReturn(isSystemApp);
+ if (isAlwaysOnService) {
+ accessibilityServiceInfo.flags |=
+ AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
+ mockResolveInfo.serviceInfo.applicationInfo.targetSdkVersion =
+ Build.VERSION_CODES.R;
+ }
return accessibilityServiceInfo;
}
@@ -974,6 +1397,22 @@
Intent.EXTRA_COMPONENT_NAME)).isEqualTo(componentName);
}
+ private void setupShortcutTargetServices() {
+ AccessibilityServiceInfo alwaysOnServiceInfo = mockAccessibilityServiceInfo(
+ TARGET_ALWAYS_ON_A11Y_SERVICE,
+ /* isSystemApp= */ false,
+ /* isAlwaysOnService= */ true);
+ when(alwaysOnServiceInfo.getTileServiceName())
+ .thenReturn(TARGET_ALWAYS_ON_A11Y_SERVICE_TILE_CLASS);
+ AccessibilityServiceInfo standardServiceInfo = mockAccessibilityServiceInfo(
+ TARGET_STANDARD_A11Y_SERVICE,
+ /* isSystemApp= */ false,
+ /* isAlwaysOnService= */ false);
+ mA11yms.getCurrentUserState().mInstalledServices.addAll(
+ List.of(alwaysOnServiceInfo, standardServiceInfo));
+ mA11yms.getCurrentUserState().updateTileServiceMapForAccessibilityServiceLocked();
+ }
+
public static class FakeInputFilter extends AccessibilityInputFilter {
FakeInputFilter(Context context,
AccessibilityManagerService service) {
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index b705077..733f056 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -16,7 +16,7 @@
package com.android.server.devicestate;
-import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
import static com.android.compatibility.common.util.PollingCheck.waitFor;
@@ -48,8 +48,6 @@
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowProcessController;
-import junit.framework.Assert;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,6 +55,8 @@
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;
@@ -69,21 +69,25 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public final class DeviceStateManagerServiceTest {
- private static final DeviceState DEFAULT_DEVICE_STATE =
- new DeviceState(0, "DEFAULT", 0 /* flags */);
- private static final DeviceState OTHER_DEVICE_STATE =
- new DeviceState(1, "OTHER", 0 /* flags */);
- private static final DeviceState
- DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP =
- new DeviceState(2, "DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP",
- DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP /* flags */);
- // A device state that is not reported as being supported for the default test provider.
- private static final DeviceState UNSUPPORTED_DEVICE_STATE =
- new DeviceState(255, "UNSUPPORTED", 0 /* flags */);
+ private static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState(
+ new DeviceState.Configuration.Builder(0, "DEFAULT").build());
+ private static final DeviceState OTHER_DEVICE_STATE = new DeviceState(
+ new DeviceState.Configuration.Builder(1, "DEFAULT").build());
+ private static final DeviceState DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP =
+ new DeviceState(new DeviceState.Configuration.Builder(2,
+ "DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP")
+ .setSystemProperties(new HashSet<>(List.of(
+ DeviceState.PROPERTY_POLICY_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)))
+ .build());
- private static final int[] SUPPORTED_DEVICE_STATE_IDENTIFIERS =
- new int[]{DEFAULT_DEVICE_STATE.getIdentifier(), OTHER_DEVICE_STATE.getIdentifier(),
- DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP.getIdentifier()};
+ // A device state that is not reported as being supported for the default test provider.
+ private static final DeviceState UNSUPPORTED_DEVICE_STATE = new DeviceState(
+ new DeviceState.Configuration.Builder(255, "UNSUPPORTED")
+ .build());
+
+ private static final List<DeviceState> SUPPORTED_DEVICE_STATES = Arrays.asList(
+ DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE,
+ DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
private static final int FAKE_PROCESS_ID = 100;
@@ -201,9 +205,8 @@
@Test
public void baseStateChanged_invalidState() {
- assertThrows(IllegalArgumentException.class, () -> {
- mProvider.setState(INVALID_DEVICE_STATE);
- });
+ assertThrows(IllegalArgumentException.class,
+ () -> mProvider.setState(INVALID_DEVICE_STATE_IDENTIFIER));
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
@@ -224,7 +227,7 @@
assertEquals(mSysPropSetter.getValue(),
DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
- assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
+ assertThat(mService.getSupportedStates()).containsExactly(DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE, DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
mProvider.notifySupportedDeviceStates(new DeviceState[]{DEFAULT_DEVICE_STATE});
@@ -237,10 +240,9 @@
assertEquals(mSysPropSetter.getValue(),
DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
- assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE);
+ assertThat(mService.getSupportedStates()).containsExactly(DEFAULT_DEVICE_STATE);
- assertArrayEquals(callback.getLastNotifiedInfo().supportedStates,
- new int[]{DEFAULT_DEVICE_STATE.getIdentifier()});
+ assertEquals(callback.getLastNotifiedInfo().supportedStates, List.of(DEFAULT_DEVICE_STATE));
}
@Test
@@ -257,7 +259,7 @@
assertEquals(mSysPropSetter.getValue(),
DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
- assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
+ assertThat(mService.getSupportedStates()).containsExactly(DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE, DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
mProvider.notifySupportedDeviceStates(new DeviceState[]{DEFAULT_DEVICE_STATE,
@@ -271,7 +273,7 @@
assertEquals(mSysPropSetter.getValue(),
DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
- assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
+ assertThat(mService.getSupportedStates()).containsExactly(DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE, DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
// The callback wasn't notified about a change in supported states as the states have not
@@ -283,9 +285,9 @@
public void getDeviceStateInfo() throws RemoteException {
DeviceStateInfo info = mService.getBinderService().getDeviceStateInfo();
assertNotNull(info);
- assertArrayEquals(info.supportedStates, SUPPORTED_DEVICE_STATE_IDENTIFIERS);
- assertEquals(info.baseState, DEFAULT_DEVICE_STATE.getIdentifier());
- assertEquals(info.currentState, DEFAULT_DEVICE_STATE.getIdentifier());
+ assertEquals(info.supportedStates, SUPPORTED_DEVICE_STATES);
+ assertEquals(info.baseState, DEFAULT_DEVICE_STATE);
+ assertEquals(info.currentState, DEFAULT_DEVICE_STATE);
}
@FlakyTest(bugId = 297949293)
@@ -299,9 +301,9 @@
DeviceStateInfo info = mService.getBinderService().getDeviceStateInfo();
- assertArrayEquals(info.supportedStates, SUPPORTED_DEVICE_STATE_IDENTIFIERS);
- assertEquals(info.baseState, INVALID_DEVICE_STATE);
- assertEquals(info.currentState, INVALID_DEVICE_STATE);
+ assertEquals(info.supportedStates, SUPPORTED_DEVICE_STATES);
+ assertEquals(info.baseState.getIdentifier(), INVALID_DEVICE_STATE_IDENTIFIER);
+ assertEquals(info.currentState.getIdentifier(), INVALID_DEVICE_STATE_IDENTIFIER);
}
@Test
@@ -310,33 +312,33 @@
mService.getBinderService().registerCallback(callback);
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
- waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().baseState.getIdentifier()
== OTHER_DEVICE_STATE.getIdentifier());
- waitAndAssert(() -> callback.getLastNotifiedInfo().currentState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().currentState.getIdentifier()
== OTHER_DEVICE_STATE.getIdentifier());
mProvider.setState(DEFAULT_DEVICE_STATE.getIdentifier());
- waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().baseState.getIdentifier()
== DEFAULT_DEVICE_STATE.getIdentifier());
- waitAndAssert(() -> callback.getLastNotifiedInfo().currentState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().currentState.getIdentifier()
== DEFAULT_DEVICE_STATE.getIdentifier());
mPolicy.blockConfigure();
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
// The callback should not have been notified of the state change as the policy is still
// pending callback.
- waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().baseState.getIdentifier()
== DEFAULT_DEVICE_STATE.getIdentifier());
- waitAndAssert(() -> callback.getLastNotifiedInfo().currentState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().currentState.getIdentifier()
== DEFAULT_DEVICE_STATE.getIdentifier());
mPolicy.resumeConfigure();
// Now that the policy is finished processing the callback should be notified of the state
// change.
- waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().baseState.getIdentifier()
== OTHER_DEVICE_STATE.getIdentifier());
- waitAndAssert(() -> callback.getLastNotifiedInfo().currentState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().currentState.getIdentifier()
== OTHER_DEVICE_STATE.getIdentifier());
}
@@ -346,10 +348,8 @@
mService.getBinderService().registerCallback(callback);
flushHandler();
assertNotNull(callback.getLastNotifiedInfo());
- assertEquals(callback.getLastNotifiedInfo().baseState,
- DEFAULT_DEVICE_STATE.getIdentifier());
- assertEquals(callback.getLastNotifiedInfo().currentState,
- DEFAULT_DEVICE_STATE.getIdentifier());
+ assertEquals(callback.getLastNotifiedInfo().baseState, DEFAULT_DEVICE_STATE);
+ assertEquals(callback.getLastNotifiedInfo().currentState, DEFAULT_DEVICE_STATE);
}
@Test
@@ -392,10 +392,8 @@
OTHER_DEVICE_STATE.getIdentifier());
assertNotNull(callback.getLastNotifiedInfo());
- assertEquals(callback.getLastNotifiedInfo().baseState,
- DEFAULT_DEVICE_STATE.getIdentifier());
- assertEquals(callback.getLastNotifiedInfo().currentState,
- OTHER_DEVICE_STATE.getIdentifier());
+ assertEquals(callback.getLastNotifiedInfo().baseState, DEFAULT_DEVICE_STATE);
+ assertEquals(callback.getLastNotifiedInfo().currentState, OTHER_DEVICE_STATE);
mService.getBinderService().cancelStateRequest();
@@ -410,10 +408,8 @@
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
- assertEquals(callback.getLastNotifiedInfo().baseState,
- DEFAULT_DEVICE_STATE.getIdentifier());
- assertEquals(callback.getLastNotifiedInfo().currentState,
- DEFAULT_DEVICE_STATE.getIdentifier());
+ assertEquals(callback.getLastNotifiedInfo().baseState, DEFAULT_DEVICE_STATE);
+ assertEquals(callback.getLastNotifiedInfo().currentState, DEFAULT_DEVICE_STATE);
}
@FlakyTest(bugId = 200332057)
@@ -636,7 +632,8 @@
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
- mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE });
+ mProvider.notifySupportedDeviceStates(
+ new DeviceState[]{DEFAULT_DEVICE_STATE});
flushHandler();
// Request is canceled because the state is no longer supported.
@@ -672,7 +669,8 @@
assertThrows(IllegalArgumentException.class, () -> {
final IBinder token = new Binder();
- mService.getBinderService().requestState(token, INVALID_DEVICE_STATE, 0 /* flags */);
+ mService.getBinderService().requestState(token, INVALID_DEVICE_STATE_IDENTIFIER,
+ 0 /* flags */);
});
}
@@ -712,10 +710,8 @@
OTHER_DEVICE_STATE.getIdentifier());
assertNotNull(callback.getLastNotifiedInfo());
- assertEquals(callback.getLastNotifiedInfo().baseState,
- OTHER_DEVICE_STATE.getIdentifier());
- assertEquals(callback.getLastNotifiedInfo().currentState,
- OTHER_DEVICE_STATE.getIdentifier());
+ assertEquals(callback.getLastNotifiedInfo().baseState, OTHER_DEVICE_STATE);
+ assertEquals(callback.getLastNotifiedInfo().currentState, OTHER_DEVICE_STATE);
mService.getBinderService().cancelBaseStateOverride();
@@ -731,19 +727,19 @@
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
- waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().baseState.getIdentifier()
== DEFAULT_DEVICE_STATE.getIdentifier());
- assertEquals(callback.getLastNotifiedInfo().currentState,
- DEFAULT_DEVICE_STATE.getIdentifier());
+ assertEquals(callback.getLastNotifiedInfo().currentState, DEFAULT_DEVICE_STATE);
}
@Test
public void requestBaseStateOverride_cancelledByBaseStateUpdate() throws RemoteException {
- final DeviceState testDeviceState = new DeviceState(2, "TEST", 0);
+ final DeviceState testDeviceState = new DeviceState(new DeviceState.Configuration.Builder(2,
+ "TEST").build());
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
mService.getBinderService().registerCallback(callback);
- mProvider.notifySupportedDeviceStates(
- new DeviceState[]{DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE, testDeviceState });
+ mProvider.notifySupportedDeviceStates(new DeviceState[]{DEFAULT_DEVICE_STATE,
+ OTHER_DEVICE_STATE, testDeviceState});
flushHandler();
final IBinder token = new Binder();
@@ -767,10 +763,8 @@
OTHER_DEVICE_STATE.getIdentifier());
assertNotNull(callback.getLastNotifiedInfo());
- assertEquals(callback.getLastNotifiedInfo().baseState,
- OTHER_DEVICE_STATE.getIdentifier());
- assertEquals(callback.getLastNotifiedInfo().currentState,
- OTHER_DEVICE_STATE.getIdentifier());
+ assertEquals(callback.getLastNotifiedInfo().baseState, OTHER_DEVICE_STATE);
+ assertEquals(callback.getLastNotifiedInfo().currentState, OTHER_DEVICE_STATE);
mProvider.setState(testDeviceState.getIdentifier());
@@ -786,10 +780,9 @@
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
testDeviceState.getIdentifier());
- waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+ waitAndAssert(() -> callback.getLastNotifiedInfo().baseState.getIdentifier()
== testDeviceState.getIdentifier());
- assertEquals(callback.getLastNotifiedInfo().currentState,
- testDeviceState.getIdentifier());
+ assertEquals(callback.getLastNotifiedInfo().currentState, testDeviceState);
}
@Test
@@ -811,8 +804,8 @@
assertThrows(IllegalArgumentException.class, () -> {
final IBinder token = new Binder();
- mService.getBinderService().requestBaseStateOverride(token, INVALID_DEVICE_STATE,
- 0 /* flags */);
+ mService.getBinderService().requestBaseStateOverride(token,
+ INVALID_DEVICE_STATE_IDENTIFIER, 0 /* flags */);
});
}
@@ -826,10 +819,6 @@
});
}
- private static void assertArrayEquals(int[] expected, int[] actual) {
- Assert.assertTrue(Arrays.equals(expected, actual));
- }
-
/**
* Common code to verify the handling of FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP flag.
*
@@ -892,7 +881,8 @@
* @param isOverrideState whether a state override is active.
*/
private void assertDeviceStateConditions(
- DeviceState state, DeviceState baseState, boolean isOverrideState) {
+ DeviceState state, DeviceState baseState,
+ boolean isOverrideState) {
assertEquals(mService.getCommittedState(), Optional.of(state));
assertEquals(mService.getBaseState(), Optional.of(baseState));
assertEquals(mSysPropSetter.getValue(),
@@ -910,7 +900,7 @@
private static final class TestDeviceStatePolicy extends DeviceStatePolicy {
private final DeviceStateProvider mProvider;
- private int mLastDeviceStateRequestedToConfigure = INVALID_DEVICE_STATE;
+ private int mLastDeviceStateRequestedToConfigure = INVALID_DEVICE_STATE_IDENTIFIER;
private boolean mConfigureBlocked = false;
private Runnable mPendingConfigureCompleteRunnable;
@@ -970,10 +960,11 @@
}
private static final class TestDeviceStateProvider implements DeviceStateProvider {
- private DeviceState[] mSupportedDeviceStates = new DeviceState[]{
- DEFAULT_DEVICE_STATE,
- OTHER_DEVICE_STATE,
- DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP};
+ private DeviceState[] mSupportedDeviceStates =
+ new DeviceState[]{
+ DEFAULT_DEVICE_STATE,
+ OTHER_DEVICE_STATE,
+ DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP};
@Nullable private final DeviceState mInitialState;
private Listener mListener;
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
index cfdb586..637bf03 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
@@ -49,10 +49,10 @@
@RunWith(AndroidJUnit4.class)
public final class OverrideRequestControllerTest {
- private static final DeviceState
- TEST_DEVICE_STATE_ZERO = new DeviceState(0, "TEST_STATE", 0);
- private static final DeviceState
- TEST_DEVICE_STATE_ONE = new DeviceState(1, "TEST_STATE", 0);
+ private static final DeviceState TEST_DEVICE_STATE_ZERO = new DeviceState(
+ new DeviceState.Configuration.Builder(0, "TEST_STATE").build());
+ private static final DeviceState TEST_DEVICE_STATE_ONE = new DeviceState(
+ new DeviceState.Configuration.Builder(1, "TEST_STATE").build());
private TestStatusChangeListener mStatusListener;
private OverrideRequestController mController;
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 1249707..67b131f 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -206,6 +206,7 @@
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
@@ -2150,12 +2151,14 @@
assertFalse(mService.isUidNetworkingBlocked(UID_E, false));
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testBackgroundChainEnabled() throws Exception {
verify(mNetworkManager).setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, true);
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testBackgroundChainOnProcStateChange() throws Exception {
@@ -2185,6 +2188,7 @@
assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testBackgroundChainOnAllowlistChange() throws Exception {
@@ -2223,6 +2227,7 @@
assertFalse(mService.isUidNetworkingBlocked(UID_B, false));
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testBackgroundChainOnTempAllowlistChange() throws Exception {
@@ -2261,6 +2266,7 @@
&& uidState.procState == procState && uidState.capability == capability;
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testUidObserverFiltersProcStateChanges() throws Exception {
@@ -2323,6 +2329,7 @@
waitForUidEventHandlerIdle();
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testUidObserverFiltersStaleChanges() throws Exception {
@@ -2343,6 +2350,7 @@
waitForUidEventHandlerIdle();
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testUidObserverFiltersCapabilityChanges() throws Exception {
@@ -2422,6 +2430,7 @@
assertFalse(mService.isUidNetworkingBlocked(UID_A, false));
}
+ @Ignore("Temporarily disabled until the feature is enabled")
@Test
@RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
public void testObsoleteHandleUidChanged() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
index 16909ab..fad10f7 100644
--- a/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
@@ -60,7 +60,10 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Unit tests for {@link DeviceStateProviderImpl}.
@@ -68,10 +71,15 @@
* Run with <code>atest DeviceStateProviderImplTest</code>.
*/
public final class DeviceStateProviderImplTest {
- private final ArgumentCaptor<DeviceState[]> mDeviceStateArrayCaptor = ArgumentCaptor.forClass(
- DeviceState[].class);
+ private final ArgumentCaptor<DeviceState[]> mDeviceStateArrayCaptor =
+ ArgumentCaptor.forClass(DeviceState[].class);
private final ArgumentCaptor<Integer> mIntegerCaptor = ArgumentCaptor.forClass(Integer.class);
private static final int MAX_HINGE_ANGLE_EXCLUSIVE = 360;
+ private static final Set<Integer> EMPTY_PROPERTY_SET = new HashSet<>();
+ private static final Set<Integer> THERMAL_TEST_PROPERTY_SET = new HashSet<>(
+ Arrays.asList(DeviceState.PROPERTY_EMULATED_ONLY,
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL,
+ DeviceState.PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE));
private Context mContext;
private SensorManager mSensorManager;
@@ -160,8 +168,8 @@
verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
final DeviceState[] expectedStates = new DeviceState[]{
- new DeviceState(1, "", 0 /* flags */),
- new DeviceState(2, "", 0 /* flags */) };
+ createDeviceState(1, "", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "", EMPTY_PROPERTY_SET)};
assertArrayEquals(expectedStates, mDeviceStateArrayCaptor.getValue());
verify(listener).onStateChanged(mIntegerCaptor.capture());
@@ -169,13 +177,13 @@
}
@Test
- public void create_stateWithCancelOverrideRequestFlag() {
+ public void create_stateWithCancelOverrideRequestProperty() {
String configString = "<device-state-config>\n"
+ " <device-state>\n"
+ " <identifier>1</identifier>\n"
- + " <flags>\n"
- + " <flag>FLAG_CANCEL_OVERRIDE_REQUESTS</flag>\n"
- + " </flags>\n"
+ + " <properties>\n"
+ + " <property>PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS</property>\n"
+ + " </properties>\n"
+ " <conditions/>\n"
+ " </device-state>\n"
+ " <device-state>\n"
@@ -192,20 +200,22 @@
verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
+
final DeviceState[] expectedStates = new DeviceState[]{
- new DeviceState(1, "", DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS),
- new DeviceState(2, "", 0 /* flags */) };
+ createDeviceState(1, "", new HashSet<>(
+ List.of(DeviceState.PROPERTY_POLICY_CANCEL_OVERRIDE_REQUESTS))),
+ createDeviceState(2, "", EMPTY_PROPERTY_SET)};
assertArrayEquals(expectedStates, mDeviceStateArrayCaptor.getValue());
}
@Test
- public void create_stateWithInvalidFlag() {
+ public void create_stateWithInvalidProperty() {
String configString = "<device-state-config>\n"
+ " <device-state>\n"
+ " <identifier>1</identifier>\n"
- + " <flags>\n"
- + " <flag>INVALID_FLAG</flag>\n"
- + " </flags>\n"
+ + " <properties>\n"
+ + " <property>INVALID_PROPERTY</property>\n"
+ + " </properties>\n"
+ " <conditions/>\n"
+ " </device-state>\n"
+ " <device-state>\n"
@@ -223,8 +233,8 @@
verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
final DeviceState[] expectedStates = new DeviceState[]{
- new DeviceState(1, "", 0 /* flags */),
- new DeviceState(2, "", 0 /* flags */) };
+ createDeviceState(1, "", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "", EMPTY_PROPERTY_SET)};
assertArrayEquals(expectedStates, mDeviceStateArrayCaptor.getValue());
}
@@ -259,8 +269,8 @@
verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
final DeviceState[] expectedStates = new DeviceState[]{
- new DeviceState(1, "", 0 /* flags */),
- new DeviceState(2, "CLOSED", 0 /* flags */) };
+ createDeviceState(1, "", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "CLOSED", EMPTY_PROPERTY_SET)};
assertArrayEquals(expectedStates, mDeviceStateArrayCaptor.getValue());
// onStateChanged() should not be called because the provider has not yet been notified of
@@ -327,11 +337,13 @@
+ " <device-state>\n"
+ " <identifier>4</identifier>\n"
+ " <name>THERMAL_TEST</name>\n"
- + " <flags>\n"
- + " <flag>FLAG_EMULATED_ONLY</flag>\n"
- + " <flag>FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL</flag>\n"
- + " <flag>FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE</flag>\n"
- + " </flags>\n"
+ + " <properties>\n"
+ + " <property>PROPERTY_EMULATED_ONLY</property>\n"
+ + " <property>PROPERTY_POLICY_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL"
+ + "</property>\n"
+ + " <property>PROPERTY_POLICY_UNSUPPORTED_WHEN_POWER_SAVE_MODE"
+ + "</property>\n"
+ + " </properties>\n"
+ " </device-state>\n"
+ "</device-state-config>\n";
DeviceStateProviderImpl.ReadableConfig config = new TestReadableConfig(configString);
@@ -352,13 +364,11 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "THERMAL_TEST",
+ THERMAL_TEST_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
// onStateChanged() should not be called because the provider has not yet been notified of
// the initial sensor state.
@@ -405,7 +415,7 @@
}
@Test
- public void test_flagDisableWhenThermalStatusCritical() throws Exception {
+ public void test_propertyDisableWhenThermalStatusCritical() throws Exception {
Sensor sensor = newSensor("sensor", Sensor.STRING_TYPE_HINGE_ANGLE);
when(mSensorManager.getSensorList(anyInt())).thenReturn(List.of(sensor));
DeviceStateProviderImpl provider = create_sensorBasedProvider(sensor);
@@ -418,13 +428,11 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "THERMAL_TEST",
+ THERMAL_TEST_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
Mockito.clearInvocations(listener);
@@ -439,9 +447,9 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_CRITICAL));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
Mockito.clearInvocations(listener);
@@ -451,18 +459,16 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_NORMAL));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "THERMAL_TEST",
+ THERMAL_TEST_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
}
@Test
- public void test_flagDisableWhenPowerSaveEnabled() throws Exception {
+ public void test_propertyDisableWhenPowerSaveEnabled() throws Exception {
Sensor sensor = newSensor("sensor", Sensor.STRING_TYPE_HINGE_ANGLE);
when(mSensorManager.getSensorList(anyInt())).thenReturn(List.of(sensor));
DeviceStateProviderImpl provider = create_sensorBasedProvider(sensor);
@@ -475,13 +481,11 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "THERMAL_TEST",
+ THERMAL_TEST_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
Mockito.clearInvocations(listener);
@@ -496,9 +500,9 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_POWER_SAVE_ENABLED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
Mockito.clearInvocations(listener);
@@ -508,13 +512,11 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_POWER_SAVE_DISABLED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */),
- new DeviceState(4, "THERMAL_TEST",
- DeviceState.FLAG_EMULATED_ONLY
- | DeviceState.FLAG_UNSUPPORTED_WHEN_THERMAL_STATUS_CRITICAL
- | DeviceState.FLAG_UNSUPPORTED_WHEN_POWER_SAVE_MODE) },
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(3, "OPENED", EMPTY_PROPERTY_SET),
+ createDeviceState(4, "THERMAL_TEST",
+ THERMAL_TEST_PROPERTY_SET)},
mDeviceStateArrayCaptor.getValue());
}
@@ -598,13 +600,22 @@
eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
assertArrayEquals(
new DeviceState[]{
- new DeviceState(1, "CLOSED", 0 /* flags */),
- new DeviceState(2, "HALF_OPENED", 0 /* flags */)
+ createDeviceState(1, "CLOSED", EMPTY_PROPERTY_SET),
+ createDeviceState(2, "HALF_OPENED", EMPTY_PROPERTY_SET)
}, mDeviceStateArrayCaptor.getValue());
// onStateChanged() should not be called because the provider could not find the sensor.
verify(listener, never()).onStateChanged(mIntegerCaptor.capture());
}
+ private DeviceState createDeviceState(int identifier, @NonNull String name,
+ @NonNull Set<@DeviceState.DeviceStateProperties Integer> systemProperties) {
+ DeviceState.Configuration configuration = new DeviceState.Configuration.Builder(identifier,
+ name)
+ .setSystemProperties(systemProperties)
+ .build();
+ return new DeviceState(configuration);
+ }
+
private static Sensor newSensor(String name, String type) throws Exception {
Constructor<Sensor> constructor = Sensor.class.getDeclaredConstructor();
constructor.setAccessible(true);
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 55fc03e..0b76154 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -87,6 +87,8 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import java.util.function.BooleanSupplier;
import java.util.stream.Collectors;
@@ -1246,6 +1248,112 @@
assertEquals(expectedAmplitudes(6), mVibratorProviders.get(3).getAmplitudes());
}
+ @Test
+ public void vibrate_withRampDown_vibrationFinishedAfterDurationAndBeforeRampDown()
+ throws Exception {
+ int expectedDuration = 100;
+ int rampDownDuration = 200;
+
+ when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(rampDownDuration);
+ mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+
+ HalVibration vibration = createVibration(
+ CombinedVibration.createParallel(
+ VibrationEffect.createOneShot(
+ expectedDuration, VibrationEffect.DEFAULT_AMPLITUDE)));
+ CountDownLatch vibrationCompleteLatch = new CountDownLatch(1);
+ doAnswer(unused -> {
+ vibrationCompleteLatch.countDown();
+ return null;
+ }).when(mManagerHooks).onVibrationCompleted(eq(vibration.id), any());
+
+ startThreadAndDispatcher(vibration);
+ long startTime = SystemClock.elapsedRealtime();
+
+ assertTrue(vibrationCompleteLatch.await(expectedDuration + TEST_TIMEOUT_MILLIS,
+ TimeUnit.MILLISECONDS));
+ long vibrationEndTime = SystemClock.elapsedRealtime();
+
+ waitForCompletion(rampDownDuration + TEST_TIMEOUT_MILLIS);
+ long completionTime = SystemClock.elapsedRealtime();
+
+ verify(mControllerCallbacks).onComplete(VIBRATOR_ID, vibration.id);
+ // Vibration ends after duration, thread completed after ramp down
+ assertThat(vibrationEndTime - startTime).isAtLeast(expectedDuration);
+ assertThat(vibrationEndTime - startTime).isLessThan(expectedDuration + rampDownDuration);
+ assertThat(completionTime - startTime).isAtLeast(expectedDuration + rampDownDuration);
+ }
+
+ @Test
+ public void vibrate_withVibratorCallbackDelayShorterThanTimeout_vibrationFinishedAfterDelay()
+ throws Exception {
+ long expectedDuration = 10;
+ long callbackDelay = VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT / 2;
+
+ mVibratorProviders.get(VIBRATOR_ID).setCompletionCallbackDelay(callbackDelay);
+ mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+
+ HalVibration vibration = createVibration(
+ CombinedVibration.createParallel(
+ VibrationEffect.createOneShot(
+ expectedDuration, VibrationEffect.DEFAULT_AMPLITUDE)));
+ CountDownLatch vibrationCompleteLatch = new CountDownLatch(1);
+ doAnswer(unused -> {
+ vibrationCompleteLatch.countDown();
+ return null;
+ }).when(mManagerHooks).onVibrationCompleted(eq(vibration.id), any());
+
+ startThreadAndDispatcher(vibration);
+ long startTime = SystemClock.elapsedRealtime();
+
+ assertTrue(vibrationCompleteLatch.await(callbackDelay + TEST_TIMEOUT_MILLIS,
+ TimeUnit.MILLISECONDS));
+ long vibrationEndTime = SystemClock.elapsedRealtime();
+
+ waitForCompletion(TEST_TIMEOUT_MILLIS);
+
+ verify(mControllerCallbacks).onComplete(VIBRATOR_ID, vibration.id);
+ assertThat(vibrationEndTime - startTime).isAtLeast(expectedDuration + callbackDelay);
+ }
+
+ @LargeTest
+ @Test
+ public void vibrate_withVibratorCallbackDelayLongerThanTimeout_vibrationFinishedAfterTimeout()
+ throws Exception {
+ long expectedDuration = 10;
+ long callbackTimeout = VibrationStepConductor.CALLBACKS_EXTRA_TIMEOUT;
+ long callbackDelay = callbackTimeout * 2;
+
+ mVibratorProviders.get(VIBRATOR_ID).setCompletionCallbackDelay(callbackDelay);
+ mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+
+ HalVibration vibration = createVibration(
+ CombinedVibration.createParallel(
+ VibrationEffect.createOneShot(
+ expectedDuration, VibrationEffect.DEFAULT_AMPLITUDE)));
+ CountDownLatch vibrationCompleteLatch = new CountDownLatch(1);
+ doAnswer(unused -> {
+ vibrationCompleteLatch.countDown();
+ return null;
+ }).when(mManagerHooks).onVibrationCompleted(eq(vibration.id), any());
+
+ startThreadAndDispatcher(vibration);
+ long startTime = SystemClock.elapsedRealtime();
+
+ assertTrue(vibrationCompleteLatch.await(callbackTimeout + TEST_TIMEOUT_MILLIS,
+ TimeUnit.MILLISECONDS));
+ long vibrationEndTime = SystemClock.elapsedRealtime();
+
+ waitForCompletion(callbackDelay + TEST_TIMEOUT_MILLIS);
+ long completionTime = SystemClock.elapsedRealtime();
+
+ verify(mControllerCallbacks, never()).onComplete(VIBRATOR_ID, vibration.id);
+ // Vibration ends and thread completes after timeout, before the HAL callback
+ assertThat(vibrationEndTime - startTime).isAtLeast(expectedDuration + callbackTimeout);
+ assertThat(vibrationEndTime - startTime).isLessThan(expectedDuration + callbackDelay);
+ assertThat(completionTime - startTime).isLessThan(expectedDuration + callbackDelay);
+ }
+
@LargeTest
@Test
public void vibrate_withWaveform_totalVibrationTimeRespected() {
diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java
index 12815fa..2ddb47b 100644
--- a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java
+++ b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java
@@ -53,6 +53,7 @@
private boolean mIsAvailable = true;
private boolean mIsInfoLoadSuccessful = true;
+ private long mCompletionCallbackDelay;
private long mOnLatency;
private long mOffLatency;
private int mOffCount;
@@ -206,7 +207,7 @@
private void scheduleListener(long vibrationDuration, long vibrationId) {
mHandler.postDelayed(() -> listener.onComplete(vibratorId, vibrationId),
- vibrationDuration);
+ vibrationDuration + mCompletionCallbackDelay);
}
}
@@ -241,6 +242,13 @@
}
/**
+ * Sets the delay this controller should fake for triggering the vibration completed callback.
+ */
+ public void setCompletionCallbackDelay(long millis) {
+ mCompletionCallbackDelay = millis;
+ }
+
+ /**
* Sets the latency this controller should fake for turning the vibrator hardware on or setting
* the vibration amplitude.
*/
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 38a66a9..eeec54f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -411,6 +411,10 @@
app2.mAboveInsetsState.addSource(statusBarSource);
assertTrue(app2.getInsetsState().peekSource(statusBarId).isVisible());
+ // Let app2 be the focused window. Otherwise, the control target could be overwritten by
+ // DisplayPolicy#updateSystemBarAttributes unexpectedly.
+ mDisplayContent.getDisplayPolicy().focusChangedLw(null, app2);
+
app2.setRequestedVisibleTypes(0, navigationBars() | statusBars());
mDisplayContent.getInsetsPolicy().updateBarControlTarget(app2);
waitUntilWindowAnimatorIdle();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index 80fb44a..72bedf2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -39,6 +39,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -305,12 +307,12 @@
final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
wallpaperController.adjustWallpaperWindows();
// Wallpaper is visible because the show-when-locked activity is translucent.
- assertTrue(wallpaperController.isWallpaperTarget(wallpaperWindow));
+ assertSame(wallpaperWindow, wallpaperController.getWallpaperTarget());
behind.mActivityRecord.setShowWhenLocked(true);
wallpaperController.adjustWallpaperWindows();
// Wallpaper is invisible because the lowest show-when-locked activity is opaque.
- assertTrue(wallpaperController.isWallpaperTarget(null));
+ assertNull(wallpaperController.getWallpaperTarget());
// A show-when-locked wallpaper is used for lockscreen. So the top wallpaper should
// be the one that is not show-when-locked.
@@ -374,10 +376,10 @@
// The activity in restore-below task should not be the target if keyguard is not locked.
mDisplayContent.mWallpaperController.adjustWallpaperWindows();
assertNotEquals(appWin, mDisplayContent.mWallpaperController.getWallpaperTarget());
- // The activity in restore-below task should be the target if keyguard is occluded.
+ // The activity in restore-below task should not be the target if keyguard is occluded.
doReturn(true).when(mDisplayContent).isKeyguardLocked();
mDisplayContent.mWallpaperController.adjustWallpaperWindows();
- assertEquals(appWin, mDisplayContent.mWallpaperController.getWallpaperTarget());
+ assertNotEquals(appWin, mDisplayContent.mWallpaperController.getWallpaperTarget());
}
@Test
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index a58cf5f..dc504ca 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -152,6 +152,9 @@
public static final boolean ENABLE_TIME_CHANGE_CORRECTION
= SystemProperties.getBoolean("persist.debug.time_correction", true);
+ private static final boolean USE_DEDICATED_HANDLER_THREAD =
+ SystemProperties.getBoolean("persist.debug.use_dedicated_handler_thread", false);
+
static final boolean DEBUG = false; // Never submit with true
static final boolean DEBUG_RESPONSE_STATS = DEBUG || Log.isLoggable(TAG, Log.DEBUG);
static final boolean COMPRESS_TIME = false;
@@ -404,11 +407,11 @@
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
filter.addAction(Intent.ACTION_USER_STARTED);
getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
- null, /* scheduler= */ Flags.useDedicatedHandlerThread() ? mHandler : null);
+ null, /* scheduler= */ USE_DEDICATED_HANDLER_THREAD ? mHandler : null);
getContext().registerReceiverAsUser(new UidRemovedReceiver(), UserHandle.ALL,
new IntentFilter(ACTION_UID_REMOVED), null,
- /* scheduler= */ Flags.useDedicatedHandlerThread() ? mHandler : null);
+ /* scheduler= */ USE_DEDICATED_HANDLER_THREAD ? mHandler : null);
mRealTimeSnapshot = SystemClock.elapsedRealtime();
mSystemTimeSnapshot = System.currentTimeMillis();
@@ -497,7 +500,7 @@
}
private Handler getUsageEventProcessingHandler() {
- if (Flags.useDedicatedHandlerThread()) {
+ if (USE_DEDICATED_HANDLER_THREAD) {
return new H(UsageStatsHandlerThread.get().getLooper());
} else {
return new H(BackgroundThread.get().getLooper());
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 5a52968..ae4faa8 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.voiceinteraction;
+import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
@@ -1072,8 +1073,10 @@
// If visEnabledKey is set to true (or absent), we try following VIS path.
String csPkgName = mContext.getResources()
.getString(R.string.config_defaultContextualSearchPackageName);
- if (!csPkgName.equals(getCurInteractor(
- Binder.getCallingUserHandle().getIdentifier()).getPackageName())) {
+ ComponentName currInteractor =
+ getCurInteractor(Binder.getCallingUserHandle().getIdentifier());
+ if (currInteractor == null
+ || !csPkgName.equals(currInteractor.getPackageName())) {
// Check if the interactor can handle Contextual Search.
// If not, return failure.
Slog.w(TAG, "Contextual Search not supported yet. Returning failure.");
@@ -2718,7 +2721,7 @@
}
launchIntent.setComponent(resolveInfo.getComponentInfo().getComponentName());
launchIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION
- | FLAG_ACTIVITY_NO_USER_ACTION);
+ | FLAG_ACTIVITY_NO_USER_ACTION | FLAG_ACTIVITY_CLEAR_TASK);
launchIntent.putExtras(args);
boolean isAssistDataAllowed = mAtmInternal.isAssistDataAllowed();
final List<ActivityAssistInfo> records = mAtmInternal.getTopVisibleActivities();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 2150b5d..d3a50bb 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -10258,6 +10258,31 @@
@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
public static final String KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY =
"cellular_service_capabilities_int_array";
+ /**
+ * Transition delay from BT to Cellular on Wear.
+ * Specifies delay when transitioning away from BT.
+ * This minimizes the duration of the netTransitionWakelock held by ConnectivityService
+ * whenever the primary/default network disappears, while still allowing some amount of time
+ * for BT to reconnect before we enable cell.
+ *
+ * If set as -1 then value from resources will be used
+ *
+ * @hide
+ */
+ public static final String KEY_WEAR_CONNECTIVITY_BT_TO_CELL_DELAY_MS_INT =
+ "proxy_connectivity_delay_cell";
+
+ /**
+ * Transition delay from BT to Cellular on Wear.
+ * If wifi connected it extends delay that has been started for BT to Cellular transition
+ * to avoid Wifi thrashing turning Cell radio and causing higher battery drain.
+ *
+ * If set as -1 then value from resources will be used
+ *
+ * @hide
+ */
+ public static final String KEY_WEAR_CONNECTIVITY_EXTEND_BT_TO_CELL_DELAY_ON_WIFI_MS_INT =
+ "wifi_connectivity_extend_cell_delay";
/** The default value for every variable. */
private static final PersistableBundle sDefaults;
@@ -11054,6 +11079,8 @@
sDefaults.putStringArray(KEY_CARRIER_SERVICE_NAME_STRING_ARRAY, new String[0]);
sDefaults.putStringArray(KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY, new String[0]);
sDefaults.putIntArray(KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY, new int[]{1, 2, 3});
+ sDefaults.putInt(KEY_WEAR_CONNECTIVITY_BT_TO_CELL_DELAY_MS_INT, -1);
+ sDefaults.putInt(KEY_WEAR_CONNECTIVITY_EXTEND_BT_TO_CELL_DELAY_ON_WIFI_MS_INT, -1);
}
/**
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
index 78f277e..f70a17d 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -1051,6 +1051,9 @@
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 name Ljava/lang/String;
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
@@ -1074,6 +1077,12 @@
0 18 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
0 18 3 longName Ljava/lang/String;
0 18 4 shortName Ljava/lang/String;
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
+ <no name>
+ <no name>
Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V
RuntimeInvisibleAnnotations:
x: #x()
@@ -1224,6 +1233,9 @@
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 name Ljava/lang/String;
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
descriptor: (Ljava/lang/String;I)V
@@ -1239,6 +1251,10 @@
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
Signature: #x // ()V
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
@@ -2031,6 +2047,9 @@
Start Length Slot Name Signature
0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2147,6 +2166,9 @@
Start Length Slot Name Signature
0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2304,6 +2326,9 @@
Start Length Slot Name Signature
0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass;
0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
}
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeInvisibleAnnotations:
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
index 406cb74..37de857 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
@@ -795,6 +795,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
@@ -815,6 +818,12 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
+ <no name>
+ <no name>
public java.lang.String getLongName();
descriptor: ()Ljava/lang/String;
@@ -969,6 +978,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
descriptor: (Ljava/lang/String;I)V
@@ -986,6 +998,10 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1769,6 +1785,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
}
InnerClasses:
public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
index c673262..c9c607c 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
@@ -1225,6 +1225,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
@@ -1257,6 +1260,12 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
+ <no name>
+ <no name>
public java.lang.String getLongName();
descriptor: ()Ljava/lang/String;
@@ -1453,6 +1462,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
descriptor: (Ljava/lang/String;I)V
@@ -1474,6 +1486,10 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -2578,6 +2594,9 @@
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2745,6 +2764,9 @@
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -2977,6 +2999,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
}
InnerClasses:
public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
index 406cb74..37de857 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
@@ -795,6 +795,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
@@ -815,6 +818,12 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
+ <no name>
+ <no name>
public java.lang.String getLongName();
descriptor: ()Ljava/lang/String;
@@ -969,6 +978,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
descriptor: (Ljava/lang/String;I)V
@@ -986,6 +998,10 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1769,6 +1785,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
}
InnerClasses:
public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
index 4fd5701..a57907d 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
@@ -1532,6 +1532,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
@@ -1569,6 +1572,12 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestStub
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
+ <no name>
+ <no name>
public java.lang.String getLongName();
descriptor: ()Ljava/lang/String;
@@ -1798,6 +1807,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> mandated
private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
descriptor: (Ljava/lang/String;I)V
@@ -1824,6 +1836,10 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> synthetic
+ <no name> synthetic
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -3190,6 +3206,9 @@
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -3407,6 +3426,9 @@
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -3704,6 +3726,9 @@
com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ MethodParameters:
+ Name Flags
+ <no name> final mandated
}
InnerClasses:
public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses