Merge "Add more fields to FGS_STATE_CHANGED atom." into udc-qpr-dev
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index f53c087..8a4b6af 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2151,6 +2151,7 @@
public class SharedConnectivityManager {
method @Nullable public static android.net.wifi.sharedconnectivity.app.SharedConnectivityManager create(@NonNull android.content.Context, @NonNull String, @NonNull String);
+ method @NonNull public android.content.BroadcastReceiver getBroadcastReceiver();
method @Nullable public android.content.ServiceConnection getServiceConnection();
method public void setService(@Nullable android.os.IInterface);
}
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 2ae7216..895dde7 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1507,8 +1507,9 @@
}
/** @hide */
- public void setRemoteTransition(@Nullable RemoteTransition remoteTransition) {
+ public ActivityOptions setRemoteTransition(@Nullable RemoteTransition remoteTransition) {
mRemoteTransition = remoteTransition;
+ return this;
}
/** @hide */
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index d189bab..2c428ef 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -236,6 +236,7 @@
* {@link android.view.WindowManagerPolicyConstants#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
* etc.
*/
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD)")
void keyguardGoingAway(int flags);
void suppressResizeConfigChanges(boolean suppress);
diff --git a/core/java/android/app/IUriGrantsManager.aidl b/core/java/android/app/IUriGrantsManager.aidl
index 9e7f2fe..b630d03 100644
--- a/core/java/android/app/IUriGrantsManager.aidl
+++ b/core/java/android/app/IUriGrantsManager.aidl
@@ -39,4 +39,7 @@
void clearGrantedUriPermissions(in String packageName, int userId);
ParceledListSlice getUriPermissions(in String packageName, boolean incoming,
boolean persistedOnly);
+
+ int checkGrantUriPermission_ignoreNonSystem(
+ int sourceUid, String targetPkg, in Uri uri, int modeFlags, int userId);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index da5e40a..a1dd5a4 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -11806,6 +11806,34 @@
}
/**
+ * Returns the list of {@link EnforcingAdmin}s who have set this restriction.
+ *
+ * <p>Note that for {@link #POLICY_SUSPEND_PACKAGES} it returns the PO or DO to keep the
+ * behavior the same as before the bug fix for b/192245204.
+ *
+ * <p>This API is only callable by the system UID
+ *
+ * @param userId The user for whom to retrieve the information.
+ * @param restriction The restriction enforced by admins. It could be any user restriction or
+ * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and
+ * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}.
+ *
+ * @hide
+ */
+ public @NonNull Set<EnforcingAdmin> getEnforcingAdminsForRestriction(int userId,
+ @NonNull String restriction) {
+ if (mService != null) {
+ try {
+ return new HashSet<>(mService.getEnforcingAdminsForRestriction(
+ userId, restriction));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return null;
+ }
+
+ /**
* Hide or unhide packages. When a package is hidden it is unavailable for use, but the data and
* actual package file remain. This function can be called by a device owner, profile owner, or
* by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via
diff --git a/core/java/android/app/admin/EnforcingAdmin.aidl b/core/java/android/app/admin/EnforcingAdmin.aidl
new file mode 100644
index 0000000..bfbfdbe
--- /dev/null
+++ b/core/java/android/app/admin/EnforcingAdmin.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+parcelable EnforcingAdmin;
\ No newline at end of file
diff --git a/core/java/android/app/admin/EnforcingAdmin.java b/core/java/android/app/admin/EnforcingAdmin.java
index 771794d..7c718f6 100644
--- a/core/java/android/app/admin/EnforcingAdmin.java
+++ b/core/java/android/app/admin/EnforcingAdmin.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
@@ -38,6 +39,11 @@
private final UserHandle mUserHandle;
/**
+ * @hide
+ */
+ private final ComponentName mComponentName;
+
+ /**
* Creates an enforcing admin with the given params.
*/
public EnforcingAdmin(
@@ -46,6 +52,21 @@
mPackageName = Objects.requireNonNull(packageName);
mAuthority = Objects.requireNonNull(authority);
mUserHandle = Objects.requireNonNull(userHandle);
+ mComponentName = null;
+ }
+
+ /**
+ * Creates an enforcing admin with the given params.
+ *
+ * @hide
+ */
+ public EnforcingAdmin(
+ @NonNull String packageName, @NonNull Authority authority,
+ @NonNull UserHandle userHandle, @Nullable ComponentName componentName) {
+ mPackageName = Objects.requireNonNull(packageName);
+ mAuthority = Objects.requireNonNull(authority);
+ mUserHandle = Objects.requireNonNull(userHandle);
+ mComponentName = componentName;
}
private EnforcingAdmin(Parcel source) {
@@ -53,6 +74,7 @@
mUserHandle = new UserHandle(source.readInt());
mAuthority = Objects.requireNonNull(
source.readParcelable(Authority.class.getClassLoader()));
+ mComponentName = source.readParcelable(ComponentName.class.getClassLoader());
}
/**
@@ -86,7 +108,8 @@
EnforcingAdmin other = (EnforcingAdmin) o;
return Objects.equals(mPackageName, other.mPackageName)
&& Objects.equals(mAuthority, other.mAuthority)
- && Objects.equals(mUserHandle, other.mUserHandle);
+ && Objects.equals(mUserHandle, other.mUserHandle)
+ && Objects.equals(mComponentName, other.mComponentName);
}
@Override
@@ -97,7 +120,7 @@
@Override
public String toString() {
return "EnforcingAdmin { mPackageName= " + mPackageName + ", mAuthority= " + mAuthority
- + ", mUserHandle= " + mUserHandle + " }";
+ + ", mUserHandle= " + mUserHandle + ", mComponentName= " + mComponentName + " }";
}
@Override
@@ -110,6 +133,7 @@
dest.writeString(mPackageName);
dest.writeInt(mUserHandle.getIdentifier());
dest.writeParcelable(mAuthority, flags);
+ dest.writeParcelable(mComponentName, flags);
}
@NonNull
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 003e804..beb452c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -54,6 +54,7 @@
import android.telephony.data.ApnSetting;
import com.android.internal.infra.AndroidFuture;
import android.app.admin.DevicePolicyState;
+import android.app.admin.EnforcingAdmin;
import java.util.List;
@@ -274,6 +275,7 @@
Intent createAdminSupportIntent(in String restriction);
Bundle getEnforcingAdminAndUserDetails(int userId,String restriction);
+ List<EnforcingAdmin> getEnforcingAdminsForRestriction(int userId,String restriction);
boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden, boolean parent);
boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean parent);
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index b7ec7b5..d66fca8 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -22,6 +22,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.autofill.FillRequest;
+import android.text.Spanned;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -1557,6 +1558,10 @@
/**
* Returns any text associated with the node that is displayed to the user, or null
* if there is none.
+ *
+ * <p> The text will be stripped of any spans that could potentially contain reference to
+ * the activity context, to avoid memory leak. If the text contained a span, a plain
+ * string version of the text will be returned.
*/
@Nullable
public CharSequence getText() {
@@ -1996,14 +2001,16 @@
@Override
public void setText(CharSequence text) {
ViewNodeText t = getNodeText();
- t.mText = TextUtils.trimNoCopySpans(text);
+ // Strip spans from the text to avoid memory leak
+ t.mText = TextUtils.trimToParcelableSize(stripAllSpansFromText(text));
t.mTextSelectionStart = t.mTextSelectionEnd = -1;
}
@Override
public void setText(CharSequence text, int selectionStart, int selectionEnd) {
ViewNodeText t = getNodeText();
- t.mText = TextUtils.trimNoCopySpans(text);
+ // Strip spans from the text to avoid memory leak
+ t.mText = stripAllSpansFromText(text);
t.mTextSelectionStart = selectionStart;
t.mTextSelectionEnd = selectionEnd;
}
@@ -2222,6 +2229,13 @@
public void setHtmlInfo(@NonNull HtmlInfo htmlInfo) {
mNode.mHtmlInfo = htmlInfo;
}
+
+ private CharSequence stripAllSpansFromText(CharSequence text) {
+ if (text instanceof Spanned) {
+ return text.toString();
+ }
+ return text;
+ }
}
private static final class HtmlInfoNode extends HtmlInfo implements Parcelable {
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 4dea4a7..b17dfa6 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -36,6 +36,7 @@
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.companion.datatransfer.PermissionSyncRequest;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -177,7 +178,7 @@
public @interface DataSyncTypes {}
/**
- * Used by {@link #enableSystemDataSync(int, int)}}.
+ * Used by {@link #enableSystemDataSyncForTypes(int, int)}}.
* Sync call metadata like muting, ending and silencing a call.
*
*/
@@ -529,6 +530,39 @@
}
/**
+ * @hide
+ */
+ public void enablePermissionsSync(int associationId) {
+ try {
+ mService.enablePermissionsSync(associationId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void disablePermissionsSync(int associationId) {
+ try {
+ mService.disablePermissionsSync(associationId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public PermissionSyncRequest getPermissionSyncRequest(int associationId) {
+ try {
+ return mService.getPermissionSyncRequest(associationId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* <p>Calling this API requires a uses-feature
* {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
*
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index b5e2670..4d05a28 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -24,6 +24,7 @@
import android.companion.ISystemDataTransferCallback;
import android.companion.AssociationInfo;
import android.companion.AssociationRequest;
+import android.companion.datatransfer.PermissionSyncRequest;
import android.content.ComponentName;
/**
@@ -101,5 +102,11 @@
void disableSystemDataSync(int associationId, int flags);
+ void enablePermissionsSync(int associationId);
+
+ void disablePermissionsSync(int associationId);
+
+ PermissionSyncRequest getPermissionSyncRequest(int associationId);
+
void enableSecureTransport(boolean enabled);
}
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 2f2ec90..b4f4a7e 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -544,8 +544,6 @@
o.mAttributionSourceState.packageName)
&& Objects.equals(mAttributionSourceState.attributionTag,
o.mAttributionSourceState.attributionTag)
- && Objects.equals(mAttributionSourceState.token,
- o.mAttributionSourceState.token)
&& Arrays.equals(mAttributionSourceState.renouncedPermissions,
o.mAttributionSourceState.renouncedPermissions)
&& Objects.equals(getNext(), o.getNext());
diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
index addd622..17cd18c 100644
--- a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
@@ -48,7 +48,8 @@
// startPreparedClient().
void prepareForAuthentication(boolean requireConfirmation, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- long requestId, int cookie, boolean allowBackgroundAuthentication);
+ long requestId, int cookie, boolean allowBackgroundAuthentication,
+ boolean isForLegacyFingerprintManager);
// Starts authentication with the previously prepared client.
void startPreparedClient(int cookie);
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 0e45787..2eed993 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -633,12 +633,13 @@
* <style scoped>
* #rb { border-right-width: thick; }
* </style>
+ *
+ * <h5>LEGACY-level guaranteed configurations</h5>
+ *
* <p>Legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
* least the following stream combinations:
*
- * <h5>LEGACY-level guaranteed configurations</h5>
- *
* <table>
* <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
@@ -653,13 +654,13 @@
* </table><br>
* </p>
*
+ * <h5>LIMITED-level additional guaranteed configurations</h5>
+ *
* <p>Limited-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
* support at least the following stream combinations in addition to those for
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
*
- * <h5>LIMITED-level additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
@@ -672,13 +673,13 @@
* </table><br>
* </p>
*
+ * <h5>FULL-level additional guaranteed configurations</h5>
+ *
* <p>FULL-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
* support at least the following stream combinations in addition to those for
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
*
- * <h5>FULL-level additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -691,14 +692,14 @@
* </table><br>
* </p>
*
+ * <h5>RAW-capability additional guaranteed configurations</h5>
+ *
* <p>RAW-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
* at least the following stream combinations on both
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
*
- * <h5>RAW-capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -713,6 +714,8 @@
* </table><br>
* </p>
*
+ * <h5>BURST-capability additional guaranteed configurations</h5>
+ *
* <p>BURST-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}) devices
* support at least the below stream combinations in addition to those for
@@ -721,8 +724,6 @@
* list for FULL-level devices, so this table is only relevant for LIMITED-level devices that
* support the BURST_CAPTURE capability.
*
- * <h5>BURST-capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -732,6 +733,8 @@
* </table><br>
* </p>
*
+ * <h5>LEVEL-3 additional guaranteed configurations</h5>
+ *
* <p>LEVEL-3 ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_3 LEVEL_3})
* support at least the following stream combinations in addition to the combinations for
@@ -739,8 +742,6 @@
* RAW capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}):
*
- * <h5>LEVEL-3 additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -749,14 +750,16 @@
* </table><br>
* </p>
*
- *<p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as described by
- * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
+ * <h5>Concurrent stream guaranteed configurations</h5>
+ *
+ * <p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as
+ * described by {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
* following guaranteed streams (when streaming concurrently with other devices)</p>
+ *
* <p> Note: The sizes mentioned for these concurrent streams are the maximum sizes guaranteed
* to be supported. Sizes smaller than these, obtained by {@link StreamConfigurationMap#getOutputSizes} for a particular format, are supported as well. </p>
*
- * <h5>Concurrent stream guaranteed configurations</h5>
- *
+ * <p>
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -792,6 +795,8 @@
* level and capabilities. Calling createCaptureSession with both JPEG and HEIC outputs is not
* supported.</p>
*
+ * <h5>LEGACY-level additional guaranteed combinations with multi-resolution outputs</h5>
+ *
* <p>Devices capable of multi-resolution output for a particular format (
* {@link android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getOutputInfo}
* returns a non-empty list) support using {@link MultiResolutionImageReader} for MAXIMUM
@@ -802,8 +807,6 @@
* stream combinations ({@code MULTI_RES} in the Max size column refers to a {@link
* MultiResolutionImageReader} created based on the variable max resolutions supported):
*
- * <h5>LEGACY-level additional guaranteed combinations with MultiResolutionoutputs</h5>
- *
* <table>
* <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
@@ -812,8 +815,12 @@
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td>Still capture plus in-app processing.</td> </tr>
* </table><br>
+ * </p>
+ *
+ * <h5>LIMITED-level additional guaranteed configurations with multi-resolution outputs</h5>
+ *
+ * <p>
* <table>
- * <tr><th colspan="7">LIMITED-level additional guaranteed configurations with MultiResolutionoutputs</th></tr>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
* <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td>Two-input in-app processing with still capture.</td> </tr>
@@ -821,11 +828,11 @@
* The same logic applies to other hardware levels and capabilities.
* </p>
*
- * <p> Devices with the ULTRA_HIGH_RESOLUTION_SENSOR capability have some additional guarantees
- * which clients can take advantage of : </p>
- *
* <h5>Additional guaranteed combinations for ULTRA_HIGH_RESOLUTION sensors</h5>
*
+ * <p> Devices with the ULTRA_HIGH_RESOLUTION_SENSOR capability have some additional guarantees
+ * which clients can take advantage of:
+ *
* <table>
* <tr> <th colspan="3" id="rb">Target 1</th> <th colspan="3" id="rb">Target 2</th> <th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th></tr>
@@ -833,6 +840,7 @@
* <tr> <td>{@code YUV / JPEG / RAW}</td><td id="rb">{@code MAX_RES}</td><td id="rb">{@code MAX}</td><td id="rb">{@code PRIV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PRIV / YUV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code RECORD}</td> <td>Ultra high res still capture with preview + app based RECORD size analysis</td> </tr>
* <tr> <td>{@code YUV / JPEG / RAW}</td><td id="rb">{@code MAX_RES}</td><td id="rb">{@code MAX}</td><td id="rb">{@code PRIV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code JPEG / YUV / RAW}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code MAX}</td> <td>Ultra high res still image capture with preview + default sensor pixel mode analysis stream</td> </tr>
* </table><br>
+ * </p>
*
* <p> Here, SC Map, refers to the {@link StreamConfigurationMap}, the target stream sizes must
* be chosen from. {@code DEFAULT} refers to the default sensor pixel mode {@link
@@ -842,17 +850,17 @@
* Note: The same capture request must not mix targets from
* {@link StreamConfigurationMap}s corresponding to different sensor pixel modes. </p>
*
- * <p> 10-bit output capable
- * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
- * devices support at least the following stream combinations: </p>
- *
* <h5>10-bit output additional guaranteed configurations</h5>
*
+ * <p>10-bit output capable
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
+ * devices support at least the following stream combinations:
+ *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
- * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> }</td> <td colspan="4" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
- * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> }</td> <td colspan="4" id="rb"></td> <td>In-application video/image processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> </td> <td colspan="4" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
+ * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> </td> <td colspan="4" id="rb"></td> <td>In-application video/image processing.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
* <tr> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution two-input in-app processing.</td> </tr>
@@ -860,6 +868,8 @@
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td>{@code YUV}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with in-app snapshot.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV }</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with video snapshot.</td> </tr>
* </table><br>
+ * </p>
+ *
* <p>Here PRIV can be either 8 or 10-bit {@link android.graphics.ImageFormat#PRIVATE} pixel
* format. YUV can be either {@link android.graphics.ImageFormat#YUV_420_888} or
* {@link android.graphics.ImageFormat#YCBCR_P010}.
@@ -895,13 +905,13 @@
* {@link CameraDevice#isSessionConfigurationSupported} to ensure that this particular
* configuration is supported.</p>
*
+ * <h5>STREAM_USE_CASE capability additional guaranteed configurations</h5>
+ *
* <p>Devices with the STREAM_USE_CASE capability ({@link
* CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes {@link
* CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE}) support below additional
* stream combinations:
*
- * <h5>STREAM_USE_CASE capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
@@ -921,12 +931,12 @@
* </table><br>
* </p>
*
+ * <h5>STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</h5>
+ *
* <p>Devices that include the {@link CameraMetadata#SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW}
* stream use-case in {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES},
* support the additional stream combinations below:
*
- * <h5>STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
@@ -934,16 +944,18 @@
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td colspan="3" id="rb"></td> <td>Preview with cropped RAW still capture</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV / JPEG}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code STILL_CAPTURE}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td>Preview with YUV / JPEG and cropped RAW still capture</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code VIDEO_RECORD / PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td>Video recording with preview and cropped RAW still capture</td> </tr>
- *
- *
- *<p> For devices where {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES}
- * includes {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION},
- * the following stream combinations are guaranteed,
- * for CaptureRequests where {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE} is set to
- * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION} <p>
+ * </table><br>
+ * </p>
*
* <h5>Preview stabilization guaranteed stream configurations</h5>
*
+ * <p>For devices where
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES} includes
+ * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION},
+ * the following stream combinations are guaranteed,
+ * for CaptureRequests where {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE} is set to
+ * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION}
+ *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
@@ -951,6 +963,8 @@
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p}</td> <td>{@code JPEG / YUV}</td><td id="rb">{@code MAXIMUM }</td><td>Standard still imaging with stabilized preview.</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p }</td><td>High-resolution recording with stabilized preview and recording stream.</td> </tr>
* </table><br>
+ * </p>
+ *
* <p>
* For the maximum size column, PREVIEW refers to the best size match to the device's screen
* resolution, or to 1080p (1920x1080), whichever is smaller. RECORD refers to the camera
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index e2840ec..0100660 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -74,7 +74,8 @@
@EnforcePermission("MANAGE_BIOMETRIC")
void prepareForAuthentication(IBinder token, long operationId,
IBiometricSensorReceiver sensorReceiver, in FingerprintAuthenticateOptions options, long requestId,
- int cookie, boolean allowBackgroundAuthentication);
+ int cookie, boolean allowBackgroundAuthentication,
+ boolean isForLegacyFingerprintManager);
// Starts authentication with the previously prepared client.
@EnforcePermission("MANAGE_BIOMETRIC")
diff --git a/core/java/android/hardware/usb/DisplayPortAltModeInfo.java b/core/java/android/hardware/usb/DisplayPortAltModeInfo.java
index 9da2f4c..36c4a2a 100644
--- a/core/java/android/hardware/usb/DisplayPortAltModeInfo.java
+++ b/core/java/android/hardware/usb/DisplayPortAltModeInfo.java
@@ -200,19 +200,43 @@
dest.writeInt(mLinkTrainingStatus);
}
+ private String displayPortAltModeStatusToString(@DisplayPortAltModeStatus int status) {
+ switch (status) {
+ case DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE:
+ return "not capable";
+ case DISPLAYPORT_ALT_MODE_STATUS_CAPABLE_DISABLED:
+ return "capable disabled";
+ case DISPLAYPORT_ALT_MODE_STATUS_ENABLED:
+ return "enabled";
+ default:
+ return "unknown";
+ }
+ }
+
+ private String linkTrainingStatusToString(@LinkTrainingStatus int status) {
+ switch (status) {
+ case LINK_TRAINING_STATUS_SUCCESS:
+ return "success";
+ case LINK_TRAINING_STATUS_FAILURE:
+ return "failure";
+ default:
+ return "unknown";
+ }
+ }
+
@NonNull
@Override
public String toString() {
return "DisplayPortAltModeInfo{partnerSink="
- + mPartnerSinkStatus
- + " cable="
- + mCableStatus
- + " numLanes="
+ + displayPortAltModeStatusToString(mPartnerSinkStatus)
+ + ", cable="
+ + displayPortAltModeStatusToString(mCableStatus)
+ + ", numLanes="
+ mNumLanes
- + " hotPlugDetect="
+ + ", hotPlugDetect="
+ mHotPlugDetect
- + " linkTrainingStatus="
- + mLinkTrainingStatus
+ + ", linkTrainingStatus="
+ + linkTrainingStatusToString(mLinkTrainingStatus)
+ "}";
}
diff --git a/core/java/android/inputmethodservice/InkWindow.java b/core/java/android/inputmethodservice/InkWindow.java
index 24d1c95..1b8d925 100644
--- a/core/java/android/inputmethodservice/InkWindow.java
+++ b/core/java/android/inputmethodservice/InkWindow.java
@@ -104,7 +104,11 @@
*/
void hide(boolean remove) {
if (getDecorView() != null) {
- getDecorView().setVisibility(remove ? View.GONE : View.INVISIBLE);
+ if (remove) {
+ mWindowManager.removeViewImmediate(getDecorView());
+ } else {
+ getDecorView().setVisibility(View.INVISIBLE);
+ }
}
}
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index c01664e..8be4c58 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -237,7 +237,7 @@
mNavigationBarFrame.setOnApplyWindowInsetsListener((view, insets) -> {
if (mNavigationBarFrame != null) {
boolean visible = insets.isVisible(captionBar());
- mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.GONE);
}
return view.onApplyWindowInsets(insets);
});
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 2bad670..143983a 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1655,6 +1655,8 @@
public abstract long[] getCpuFreqs();
public final static class HistoryTag {
+ public static final int HISTORY_TAG_POOL_OVERFLOW = -1;
+
public String string;
public int uid;
@@ -6786,10 +6788,11 @@
if (bd.mask == HistoryItem.STATE_WAKE_LOCK_FLAG && wakelockTag != null) {
didWake = true;
sb.append("=");
- if (longNames) {
+ if (longNames
+ || wakelockTag.poolIdx == HistoryTag.HISTORY_TAG_POOL_OVERFLOW) {
UserHandle.formatUid(sb, wakelockTag.uid);
sb.append(":\"");
- sb.append(wakelockTag.string);
+ sb.append(wakelockTag.string.replace("\"", "\"\""));
sb.append("\"");
} else {
sb.append(wakelockTag.poolIdx);
@@ -6809,7 +6812,7 @@
}
if (!didWake && wakelockTag != null) {
sb.append(longNames ? " wake_lock=" : ",w=");
- if (longNames) {
+ if (longNames || wakelockTag.poolIdx == HistoryTag.HISTORY_TAG_POOL_OVERFLOW) {
UserHandle.formatUid(sb, wakelockTag.uid);
sb.append(":\"");
sb.append(wakelockTag.string);
@@ -7070,7 +7073,14 @@
if (rec.wakeReasonTag != null) {
if (checkin) {
item.append(",wr=");
- item.append(rec.wakeReasonTag.poolIdx);
+ if (rec.wakeReasonTag.poolIdx == HistoryTag.HISTORY_TAG_POOL_OVERFLOW) {
+ item.append(sUidToString.applyAsString(rec.wakeReasonTag.uid));
+ item.append(":\"");
+ item.append(rec.wakeReasonTag.string.replace("\"", "\"\""));
+ item.append("\"");
+ } else {
+ item.append(rec.wakeReasonTag.poolIdx);
+ }
} else {
item.append(" wake_reason=");
item.append(rec.wakeReasonTag.uid);
@@ -7098,7 +7108,15 @@
}
item.append("=");
if (checkin) {
- item.append(rec.eventTag.poolIdx);
+ if (rec.eventTag.poolIdx == HistoryTag.HISTORY_TAG_POOL_OVERFLOW) {
+ item.append(HISTORY_EVENT_INT_FORMATTERS[idx]
+ .applyAsString(rec.eventTag.uid));
+ item.append(":\"");
+ item.append(rec.eventTag.string.replace("\"", "\"\""));
+ item.append("\"");
+ } else {
+ item.append(rec.eventTag.poolIdx);
+ }
} else {
item.append(HISTORY_EVENT_INT_FORMATTERS[idx]
.applyAsString(rec.eventTag.uid));
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d66ffce..a55183c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4724,13 +4724,13 @@
public static final String PEAK_REFRESH_RATE = "peak_refresh_rate";
/**
- * Control whether to stay awake on fold
+ * Control lock behavior on fold
*
* If this isn't set, the system falls back to a device specific default.
* @hide
*/
@Readable
- public static final String STAY_AWAKE_ON_FOLD = "stay_awake_on_fold";
+ public static final String FOLD_LOCK_BEHAVIOR = "fold_lock_behavior_setting";
/**
* The amount of time in milliseconds before the device goes to sleep or begins
@@ -10505,6 +10505,14 @@
"search_press_hold_nav_handle_enabled";
/**
+ * Whether long-pressing on the home button can trigger search.
+ *
+ * @hide
+ */
+ public static final String SEARCH_LONG_PRESS_HOME_ENABLED =
+ "search_long_press_home_enabled";
+
+ /**
* Control whether Trust Agents are in active unlock or extend unlock mode.
* @hide
*/
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index de2a99b..75ec028 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -46,6 +46,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SharedMemory;
+import android.os.SystemProperties;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.Log;
@@ -131,6 +132,9 @@
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
static final long MULTIPLE_ACTIVE_HOTWORD_DETECTORS = 193232191L;
+ private static final boolean SYSPROP_VISUAL_QUERY_SERVICE_ENABLED =
+ SystemProperties.getBoolean("ro.hotword.visual_query_service_enabled", false);
+
IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() {
@Override
public void ready() {
@@ -947,6 +951,10 @@
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
+ if (!SYSPROP_VISUAL_QUERY_SERVICE_ENABLED) {
+ throw new IllegalStateException("VisualQueryDetectionService is not enabled on this "
+ + "system. Please set ro.hotword.visual_query_service_enabled to true.");
+ }
if (mSystemService == null) {
throw new IllegalStateException("Not available until onReady() is called");
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 85f5395..827600c 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -247,7 +247,6 @@
DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "true");
DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "true");
DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS, "false");
- DEFAULT_FLAGS.put("settings_press_hold_nav_handle_to_search", "false");
}
private static final Set<String> PERSISTENT_FLAGS;
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index 297754f..dfade01 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -24,6 +24,7 @@
import android.graphics.RectF;
import android.graphics.Region;
import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
@@ -81,6 +82,8 @@
private int mConnectionCount = 0;
private final InputMethodManager mImm;
+ private final int[] mTempLocation = new int[2];
+
private final Rect mTempRect = new Rect();
private final RectF mTempRectF = new RectF();
@@ -429,7 +432,19 @@
return null;
}
- private static void requestFocusWithoutReveal(View view) {
+ private void requestFocusWithoutReveal(View view) {
+ if (view instanceof EditText editText && !mState.mStylusDownWithinEditorBounds) {
+ // If the stylus down point was inside the EditText's bounds, then the EditText will
+ // automatically set its cursor position nearest to the stylus down point when it
+ // gains focus. If the stylus down point was outside the EditText's bounds (within
+ // the extended handwriting bounds), then we must calculate and set the cursor
+ // position manually.
+ view.getLocationInWindow(mTempLocation);
+ int offset = editText.getOffsetForPosition(
+ mState.mStylusDownX - mTempLocation[0],
+ mState.mStylusDownY - mTempLocation[1]);
+ editText.setSelection(offset);
+ }
if (view.getRevealOnFocusHint()) {
view.setRevealOnFocusHint(false);
view.requestFocus();
@@ -457,6 +472,10 @@
if (getViewHandwritingArea(connectedView, handwritingArea)
&& isInHandwritingArea(handwritingArea, x, y, connectedView, isHover)
&& shouldTriggerStylusHandwritingForView(connectedView)) {
+ if (!isHover && mState != null) {
+ mState.mStylusDownWithinEditorBounds =
+ contains(handwritingArea, x, y, 0f, 0f, 0f, 0f);
+ }
return connectedView;
}
}
@@ -475,7 +494,12 @@
}
final float distance = distance(handwritingArea, x, y);
- if (distance == 0f) return view;
+ if (distance == 0f) {
+ if (!isHover && mState != null) {
+ mState.mStylusDownWithinEditorBounds = true;
+ }
+ return view;
+ }
if (distance < minDistance) {
minDistance = distance;
bestCandidate = view;
@@ -658,6 +682,12 @@
private boolean mExceedHandwritingSlop;
/**
+ * Whether the stylus down point of the MotionEvent sequence was within the editor's bounds
+ * (not including the extended handwriting bounds).
+ */
+ private boolean mStylusDownWithinEditorBounds;
+
+ /**
* A view which has requested focus and is pending input connection creation. When an input
* connection is created for the view, a handwriting session should be started for the view.
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index d680d04..c2afb4b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -434,15 +434,15 @@
/**
* Called when the typing hint is changed. This would be invoked by the
* {@link android.view.inputmethod.RemoteInputConnectionImpl}
- * to hint if the user is typing when the it is {@link #isActive() active}.
+ * to hint if the user is typing when it is {@link #isActive() active}.
*
- * This can be only happened on the UI thread. The behavior won't be guaranteed if
- * invoking this on a non-UI thread.
+ * The operation in this method should be dispatched to the UI thread to
+ * keep the sequence.
*
* @param isTyping {@code true} if the user is typing.
+ * @param deactivate {code true} if the input connection deactivate
*/
- @UiThread
- void onTypingHintChanged(boolean isTyping);
+ void onTypingHintChanged(boolean isTyping, boolean deactivate);
/**
* Indicates whether the notifier is currently in active state or not.
@@ -468,19 +468,40 @@
@NonNull
private final ViewRootRefreshRateController mController;
+ @NonNull
+ private final Handler mHandler;
+
+ @NonNull
+ private final Thread mThread;
+
TypingHintNotifierImpl(@NonNull AtomicReference<TypingHintNotifier> notifier,
- @NonNull ViewRootRefreshRateController controller) {
+ @NonNull ViewRootRefreshRateController controller, @NonNull Handler handler,
+ @NonNull Thread thread) {
mController = controller;
mActiveNotifier = notifier;
+ mHandler = handler;
+ mThread = thread;
}
@Override
- public void onTypingHintChanged(boolean isTyping) {
- if (!isActive()) {
- // No-op when the listener was deactivated.
- return;
+ public void onTypingHintChanged(boolean isTyping, boolean deactivate) {
+ final Runnable runnable = () -> {
+ if (!isActive()) {
+ // No-op when the listener was deactivated.
+ return;
+ }
+ mController.updateRefreshRatePreference(isTyping ? LOWER : RESTORE);
+ if (deactivate) {
+ deactivate();
+ }
+ };
+
+ if (Thread.currentThread() == mThread) {
+ // Run directly if it's on the UiThread.
+ runnable.run();
+ } else {
+ mHandler.post(runnable);
}
- mController.updateRefreshRatePreference(isTyping ? LOWER : RESTORE);
}
@Override
@@ -521,7 +542,7 @@
return null;
}
final TypingHintNotifier newNotifier = new TypingHintNotifierImpl(mActiveTypingHintNotifier,
- mRefreshRateController);
+ mRefreshRateController, mHandler, mThread);
mActiveTypingHintNotifier.set(newNotifier);
return newNotifier;
diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java
index 3b8298e..dda3993 100644
--- a/core/java/android/view/WindowLayout.java
+++ b/core/java/android/view/WindowLayout.java
@@ -124,16 +124,16 @@
|| cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
final Insets systemBarsInsets = state.calculateInsets(
displayFrame, systemBars(), requestedVisibleTypes);
- if (systemBarsInsets.left > 0) {
+ if (systemBarsInsets.left >= cutout.getSafeInsetLeft()) {
displayCutoutSafeExceptMaybeBars.left = MIN_X;
}
- if (systemBarsInsets.top > 0) {
+ if (systemBarsInsets.top >= cutout.getSafeInsetTop()) {
displayCutoutSafeExceptMaybeBars.top = MIN_Y;
}
- if (systemBarsInsets.right > 0) {
+ if (systemBarsInsets.right >= cutout.getSafeInsetRight()) {
displayCutoutSafeExceptMaybeBars.right = MAX_X;
}
- if (systemBarsInsets.bottom > 0) {
+ if (systemBarsInsets.bottom >= cutout.getSafeInsetBottom()) {
displayCutoutSafeExceptMaybeBars.bottom = MAX_Y;
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 30bdd95..c00924b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -3139,15 +3139,6 @@
public static final int PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS = 1 << 10;
/**
- * Flag to force the status bar window to be visible all the time. If the bar is hidden when
- * this flag is set it will be shown again.
- * This can only be set by {@link LayoutParams#TYPE_STATUS_BAR}.
- *
- * {@hide}
- */
- public static final int PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR = 1 << 11;
-
- /**
* Flag to indicate that the window frame should be the requested frame adding the display
* cutout frame. This will only be applied if a specific size smaller than the parent frame
* is given, and the window is covering the display cutout. The extended frame will not be
@@ -3238,15 +3229,6 @@
public static final int PRIVATE_FLAG_NOT_MAGNIFIABLE = 1 << 22;
/**
- * Flag to indicate that the status bar window is in a state such that it forces showing
- * the navigation bar unless the navigation bar window is explicitly set to
- * {@link View#GONE}.
- * It only takes effects if this is set by {@link LayoutParams#TYPE_STATUS_BAR}.
- * @hide
- */
- public static final int PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION = 1 << 23;
-
- /**
* Flag to indicate that the window is color space agnostic, and the color can be
* interpreted to any color space.
* @hide
@@ -3334,7 +3316,6 @@
PRIVATE_FLAG_SYSTEM_ERROR,
PRIVATE_FLAG_OPTIMIZE_MEASURE,
PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS,
- PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR,
PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT,
PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY,
PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME,
@@ -3345,7 +3326,6 @@
PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY,
PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION,
PRIVATE_FLAG_NOT_MAGNIFIABLE,
- PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION,
PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
PRIVATE_FLAG_USE_BLAST,
PRIVATE_FLAG_APPEARANCE_CONTROLLED,
@@ -3401,10 +3381,6 @@
equals = PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS,
name = "DISABLE_WALLPAPER_TOUCH_EVENTS"),
@ViewDebug.FlagToString(
- mask = PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR,
- equals = PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR,
- name = "FORCE_STATUS_BAR_VISIBLE"),
- @ViewDebug.FlagToString(
mask = PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT,
equals = PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT,
name = "LAYOUT_SIZE_EXTENDED_BY_CUTOUT"),
@@ -3445,10 +3421,6 @@
equals = PRIVATE_FLAG_NOT_MAGNIFIABLE,
name = "NOT_MAGNIFIABLE"),
@ViewDebug.FlagToString(
- mask = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION,
- equals = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION,
- name = "STATUS_FORCE_SHOW_NAVIGATION"),
- @ViewDebug.FlagToString(
mask = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
equals = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
name = "COLOR_SPACE_AGNOSTIC"),
@@ -4412,6 +4384,16 @@
public InsetsFrameProvider[] providedInsets;
/**
+ * Specifies which {@link InsetsType}s should be forcibly shown. The types shown by this
+ * method won't affect the app's layout. This field only takes effects if the caller has
+ * {@link android.Manifest.permission#STATUS_BAR_SERVICE} or the caller has the same uid as
+ * the recents component.
+ *
+ * @hide
+ */
+ public @InsetsType int forciblyShownTypes;
+
+ /**
* {@link LayoutParams} to be applied to the window when layout with a assigned rotation.
* This will make layout during rotation change smoothly.
*
@@ -4869,6 +4851,7 @@
out.writeInt(mBlurBehindRadius);
out.writeBoolean(mWallpaperTouchEventsEnabled);
out.writeTypedArray(providedInsets, 0 /* parcelableFlags */);
+ out.writeInt(forciblyShownTypes);
checkNonRecursiveParams();
out.writeTypedArray(paramsForRotation, 0 /* parcelableFlags */);
out.writeInt(mDisplayFlags);
@@ -4940,6 +4923,7 @@
mBlurBehindRadius = in.readInt();
mWallpaperTouchEventsEnabled = in.readBoolean();
providedInsets = in.createTypedArray(InsetsFrameProvider.CREATOR);
+ forciblyShownTypes = in.readInt();
paramsForRotation = in.createTypedArray(LayoutParams.CREATOR);
mDisplayFlags = in.readInt();
}
@@ -5245,6 +5229,11 @@
changes |= LAYOUT_CHANGED;
}
+ if (forciblyShownTypes != o.forciblyShownTypes) {
+ forciblyShownTypes = o.forciblyShownTypes;
+ changes |= PRIVATE_FLAGS_CHANGED;
+ }
+
if (paramsForRotation != o.paramsForRotation) {
if ((changes & LAYOUT_CHANGED) == 0) {
if (paramsForRotation != null && o.paramsForRotation != null
@@ -5482,6 +5471,11 @@
sb.append(prefix).append(" ").append(providedInsets[i]);
}
}
+ if (forciblyShownTypes != 0) {
+ sb.append(System.lineSeparator());
+ sb.append(prefix).append(" forciblyShownTypes=").append(
+ WindowInsets.Type.toString(forciblyShownTypes));
+ }
if (paramsForRotation != null && paramsForRotation.length != 0) {
sb.append(System.lineSeparator());
sb.append(prefix).append(" paramsForRotation:");
diff --git a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
index 364adc7..3ad49af 100644
--- a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
@@ -28,8 +28,12 @@
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UiThread;
+import android.app.UriGrantsManager;
+import android.content.ContentProvider;
+import android.content.Intent;
import android.graphics.RectF;
+import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.CancellationSignalBeamer;
@@ -38,6 +42,7 @@
import android.os.Looper;
import android.os.ResultReceiver;
import android.os.Trace;
+import android.os.UserHandle;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.KeyEvent;
@@ -373,11 +378,8 @@
return;
}
dispatch(() -> {
- notifyTypingHint(false /* isTyping */);
// Deactivate the notifier when finishing typing.
- if (mTypingHintNotifier != null) {
- mTypingHintNotifier.deactivate();
- }
+ notifyTypingHint(false /* isTyping */, true /* deactivate */);
// Note that we do not need to worry about race condition here, because 1) mFinished is
// updated only inside this block, and 2) the code here is running on a Handler hence we
@@ -643,7 +645,7 @@
return;
}
ic.commitText(text, newCursorPosition);
- notifyTypingHint(true /* isTyping */);
+ notifyTypingHint(true /* isTyping */, false /* deactivate */);
});
}
@@ -799,7 +801,7 @@
return;
}
ic.setComposingText(text, newCursorPosition);
- notifyTypingHint(true /* isTyping */);
+ notifyTypingHint(true /* isTyping */, false /* deactivate */);
});
}
@@ -927,7 +929,7 @@
return;
}
ic.deleteSurroundingText(beforeLength, afterLength);
- notifyTypingHint(true /* isTyping */);
+ notifyTypingHint(true /* isTyping */, false /* deactivate */);
});
}
@@ -1197,7 +1199,22 @@
public void commitContent(InputConnectionCommandHeader header,
InputContentInfo inputContentInfo, int flags, Bundle opts,
AndroidFuture future /* T=Boolean */) {
+ final int imeUid = Binder.getCallingUid();
dispatchWithTracing("commitContent", future, () -> {
+ // Check if the originator IME has the right permissions
+ try {
+ final int contentUriOwnerUserId = ContentProvider.getUserIdFromUri(
+ inputContentInfo.getContentUri(), UserHandle.getUserId(imeUid));
+ final Uri contentUriWithoutUserId = ContentProvider.getUriWithoutUserId(
+ inputContentInfo.getContentUri());
+ UriGrantsManager.getService().checkGrantUriPermission_ignoreNonSystem(imeUid, null,
+ contentUriWithoutUserId, Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ contentUriOwnerUserId);
+ } catch (Exception e) {
+ Log.w(TAG, "commitContent with invalid Uri permission from IME:", e);
+ return false;
+ }
+
if (header.mSessionId != mCurrentSessionId.get()) {
return false; // cancelled
}
@@ -1497,10 +1514,9 @@
* The input connection indicates that the user is typing when {@link #commitText} or
* {@link #setComposingText)} and the user finish typing when {@link #deactivate()}.
*/
- @UiThread
- private void notifyTypingHint(boolean isTyping) {
+ private void notifyTypingHint(boolean isTyping, boolean deactivate) {
if (mTypingHintNotifier != null) {
- mTypingHintNotifier.onTypingHintChanged(isTyping);
+ mTypingHintNotifier.onTypingHintChanged(isTyping, deactivate);
}
}
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6523fff..f5b81b0 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -50,6 +50,7 @@
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
@@ -3139,4 +3140,15 @@
if (result == null) return super.onApplyWindowInsets(insets);
return result;
}
+
+ @Override
+ @Nullable
+ public PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ PointerIcon icon =
+ mProvider.getViewDelegate().onResolvePointerIcon(event, pointerIndex);
+ if (icon != null) {
+ return icon;
+ }
+ return super.onResolvePointerIcon(event, pointerIndex);
+ }
}
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 26579c5d..ca423e0 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -39,6 +39,7 @@
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowInsets;
@@ -496,6 +497,15 @@
default WindowInsets onApplyWindowInsets(@Nullable WindowInsets insets) {
return null;
}
+
+ /**
+ * @hide Only used by WebView.
+ */
+ @SuppressWarnings("unused")
+ @Nullable
+ default PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ return null;
+ }
}
interface ScrollDelegate {
diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java
index 065089f5..53c73c6 100644
--- a/core/java/android/widget/AdapterViewFlipper.java
+++ b/core/java/android/widget/AdapterViewFlipper.java
@@ -16,10 +16,7 @@
package android.widget;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.TypedArray;
import android.os.Message;
import android.util.AttributeSet;
@@ -48,7 +45,6 @@
private boolean mRunning = false;
private boolean mStarted = false;
private boolean mVisible = false;
- private boolean mUserPresent = true;
private boolean mAdvancedByHost = false;
public AdapterViewFlipper(Context context) {
@@ -82,40 +78,10 @@
a.recycle();
}
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (Intent.ACTION_SCREEN_OFF.equals(action)) {
- mUserPresent = false;
- updateRunning();
- } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
- mUserPresent = true;
- updateRunning(false);
- }
- }
- };
-
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- // Listen for broadcasts related to user-presence
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(Intent.ACTION_USER_PRESENT);
-
- // OK, this is gross but needed. This class is supported by the
- // remote views machanism and as a part of that the remote views
- // can be inflated by a context for another user without the app
- // having interact users permission - just for loading resources.
- // For exmaple, when adding widgets from a user profile to the
- // home screen. Therefore, we register the receiver as the current
- // user not the one the context is for.
- getContext().registerReceiverAsUser(mReceiver, android.os.Process.myUserHandle(),
- filter, null, getHandler());
-
-
if (mAutoStart) {
// Automatically start when requested
startFlipping();
@@ -126,8 +92,6 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mVisible = false;
-
- getContext().unregisterReceiver(mReceiver);
updateRunning();
}
@@ -235,8 +199,7 @@
* true.
*/
private void updateRunning(boolean flipNow) {
- boolean running = !mAdvancedByHost && mVisible && mStarted && mUserPresent
- && mAdapter != null;
+ boolean running = !mAdvancedByHost && mVisible && mStarted && mAdapter != null;
if (running != mRunning) {
if (running) {
showOnly(mWhichChild, flipNow);
@@ -248,7 +211,7 @@
}
if (LOGD) {
Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted=" + mStarted
- + ", mUserPresent=" + mUserPresent + ", mRunning=" + mRunning);
+ + ", mRunning=" + mRunning);
}
}
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 1f0e95e..e0158332 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -23,7 +23,6 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.BlendMode;
@@ -37,6 +36,9 @@
import android.view.View;
import android.view.inspector.InspectableProperty;
import android.widget.RemoteViews.RemoteView;
+import android.widget.TextClock.ClockEventDelegate;
+
+import com.android.internal.util.Preconditions;
import java.time.Clock;
import java.time.DateTimeException;
@@ -112,6 +114,7 @@
public AnalogClock(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ mClockEventDelegate = new ClockEventDelegate(context);
mSecondsHandFps = AppGlobals.getIntCoreSetting(
WidgetFlags.KEY_ANALOG_CLOCK_SECONDS_HAND_FPS,
context.getResources()
@@ -584,21 +587,9 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- IntentFilter filter = new IntentFilter();
if (!mReceiverAttached) {
- filter.addAction(Intent.ACTION_TIME_CHANGED);
- filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
-
- // OK, this is gross but needed. This class is supported by the
- // remote views mechanism and as a part of that the remote views
- // can be inflated by a context for another user without the app
- // having interact users permission - just for loading resources.
- // For example, when adding widgets from a user profile to the
- // home screen. Therefore, we register the receiver as the current
- // user not the one the context is for.
- getContext().registerReceiverAsUser(mIntentReceiver,
- android.os.Process.myUserHandle(), filter, null, getHandler());
+ mClockEventDelegate.registerTimeChangeReceiver(mIntentReceiver, getHandler());
mReceiverAttached = true;
}
@@ -615,12 +606,23 @@
@Override
protected void onDetachedFromWindow() {
if (mReceiverAttached) {
- getContext().unregisterReceiver(mIntentReceiver);
+ mClockEventDelegate.unregisterTimeChangeReceiver(mIntentReceiver);
mReceiverAttached = false;
}
super.onDetachedFromWindow();
}
+ /**
+ * Sets a delegate to handle clock event registration. This must be called before the view is
+ * attached to the window
+ *
+ * @hide
+ */
+ public void setClockEventDelegate(ClockEventDelegate delegate) {
+ Preconditions.checkState(!mReceiverAttached, "Clock events already registered");
+ mClockEventDelegate = delegate;
+ }
+
private void onVisible() {
if (!mVisible) {
mVisible = true;
@@ -797,6 +799,7 @@
}
};
private boolean mReceiverAttached;
+ private ClockEventDelegate mClockEventDelegate;
private final Runnable mTick = new Runnable() {
@Override
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index e48afb2..255bd67 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -16,6 +16,7 @@
package android.widget;
+import static android.os.Process.myUserHandle;
import static android.view.ViewDebug.ExportedProperty;
import static android.widget.RemoteViews.RemoteView;
@@ -24,7 +25,6 @@
import android.app.ActivityManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -43,6 +43,7 @@
import android.view.inspector.InspectableProperty;
import com.android.internal.R;
+import com.android.internal.util.Preconditions;
import java.time.Duration;
import java.time.Instant;
@@ -141,6 +142,8 @@
private boolean mRegistered;
private boolean mShouldRunTicker;
+ private ClockEventDelegate mClockEventDelegate;
+
private Calendar mTime;
private String mTimeZone;
@@ -178,8 +181,7 @@
if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
final String timeZone = intent.getStringExtra(Intent.EXTRA_TIMEZONE);
createTime(timeZone);
- } else if (!mShouldRunTicker && (Intent.ACTION_TIME_TICK.equals(intent.getAction())
- || Intent.ACTION_TIME_CHANGED.equals(intent.getAction()))) {
+ } else if (!mShouldRunTicker && Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
return;
}
onTimeChanged();
@@ -282,6 +284,7 @@
if (mFormat24 == null) {
mFormat24 = getBestDateTimePattern("Hm");
}
+ mClockEventDelegate = new ClockEventDelegate(getContext());
createTime(mTimeZone);
chooseFormat();
@@ -431,6 +434,17 @@
}
/**
+ * Sets a delegate to handle clock event registration. This must be called before the view is
+ * attached to the window
+ *
+ * @hide
+ */
+ public void setClockEventDelegate(ClockEventDelegate delegate) {
+ Preconditions.checkState(!mRegistered, "Clock events already registered");
+ mClockEventDelegate = delegate;
+ }
+
+ /**
* Update the displayed time if necessary and invalidate the view.
*/
public void refreshTime() {
@@ -557,7 +571,7 @@
if (!mRegistered) {
mRegistered = true;
- registerReceiver();
+ mClockEventDelegate.registerTimeChangeReceiver(mIntentReceiver, getHandler());
registerObserver();
createTime(mTimeZone);
@@ -582,7 +596,7 @@
super.onDetachedFromWindow();
if (mRegistered) {
- unregisterReceiver();
+ mClockEventDelegate.unregisterTimeChangeReceiver(mIntentReceiver);
unregisterObserver();
mRegistered = false;
@@ -598,56 +612,27 @@
mStopTicking = true;
}
- private void registerReceiver() {
- final IntentFilter filter = new IntentFilter();
-
- filter.addAction(Intent.ACTION_TIME_CHANGED);
- filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
-
- // OK, this is gross but needed. This class is supported by the
- // remote views mechanism and as a part of that the remote views
- // can be inflated by a context for another user without the app
- // having interact users permission - just for loading resources.
- // For example, when adding widgets from a managed profile to the
- // home screen. Therefore, we register the receiver as the user
- // the app is running as not the one the context is for.
- getContext().registerReceiverAsUser(mIntentReceiver, android.os.Process.myUserHandle(),
- filter, null, getHandler());
- }
-
private void registerObserver() {
if (mRegistered) {
if (mFormatChangeObserver == null) {
mFormatChangeObserver = new FormatChangeObserver(getHandler());
}
- final ContentResolver resolver = getContext().getContentResolver();
- Uri uri = Settings.System.getUriFor(Settings.System.TIME_12_24);
- if (mShowCurrentUserTime) {
- resolver.registerContentObserver(uri, true,
- mFormatChangeObserver, UserHandle.USER_ALL);
- } else {
- // UserHandle.myUserId() is needed. This class is supported by the
- // remote views mechanism and as a part of that the remote views
- // can be inflated by a context for another user without the app
- // having interact users permission - just for loading resources.
- // For example, when adding widgets from a managed profile to the
- // home screen. Therefore, we register the ContentObserver with the user
- // the app is running (e.g. the launcher) and not the user of the
- // context (e.g. the widget's profile).
- resolver.registerContentObserver(uri, true,
- mFormatChangeObserver, UserHandle.myUserId());
- }
+ // UserHandle.myUserId() is needed. This class is supported by the
+ // remote views mechanism and as a part of that the remote views
+ // can be inflated by a context for another user without the app
+ // having interact users permission - just for loading resources.
+ // For example, when adding widgets from a managed profile to the
+ // home screen. Therefore, we register the ContentObserver with the user
+ // the app is running (e.g. the launcher) and not the user of the
+ // context (e.g. the widget's profile).
+ int userHandle = mShowCurrentUserTime ? UserHandle.USER_ALL : UserHandle.myUserId();
+ mClockEventDelegate.registerFormatChangeObserver(mFormatChangeObserver, userHandle);
}
}
- private void unregisterReceiver() {
- getContext().unregisterReceiver(mIntentReceiver);
- }
-
private void unregisterObserver() {
if (mFormatChangeObserver != null) {
- final ContentResolver resolver = getContext().getContentResolver();
- resolver.unregisterContentObserver(mFormatChangeObserver);
+ mClockEventDelegate.unregisterFormatChangeObserver(mFormatChangeObserver);
}
}
@@ -674,4 +659,59 @@
stream.addProperty("format", mFormat == null ? null : mFormat.toString());
stream.addProperty("hasSeconds", mHasSeconds);
}
+
+ /**
+ * Utility class to delegate some system event handling to allow overring the default behavior
+ *
+ * @hide
+ */
+ public static class ClockEventDelegate {
+
+ private final Context mContext;
+
+ public ClockEventDelegate(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Registers a receiver for actions {@link Intent#ACTION_TIME_CHANGED} and
+ * {@link Intent#ACTION_TIMEZONE_CHANGED}
+ *
+ * OK, this is gross but needed. This class is supported by the remote views mechanism and
+ * as a part of that the remote views can be inflated by a context for another user without
+ * the app having interact users permission - just for loading resources. For example,
+ * when adding widgets from a managed profile to the home screen. Therefore, we register
+ * the receiver as the user the app is running as not the one the context is for.
+ */
+ public void registerTimeChangeReceiver(BroadcastReceiver receiver, Handler handler) {
+ final IntentFilter filter = new IntentFilter();
+
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+
+ mContext.registerReceiverAsUser(receiver, myUserHandle(), filter, null, handler);
+ }
+
+ /**
+ * Unregisters a previously registered receiver
+ */
+ public void unregisterTimeChangeReceiver(BroadcastReceiver receiver) {
+ mContext.unregisterReceiver(receiver);
+ }
+
+ /**
+ * Registers an observer for time format changes
+ */
+ public void registerFormatChangeObserver(ContentObserver observer, int userHandle) {
+ Uri uri = Settings.System.getUriFor(Settings.System.TIME_12_24);
+ mContext.getContentResolver().registerContentObserver(uri, true, observer, userHandle);
+ }
+
+ /**
+ * Unregisters a previously registered observer
+ */
+ public void unregisterFormatChangeObserver(ContentObserver observer) {
+ mContext.getContentResolver().unregisterContentObserver(observer);
+ }
+ }
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2ad3f74..c990e94 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12888,6 +12888,15 @@
}
/**
+ * @return true if this TextView could be filled by an Autofill service. Note that disabled
+ * fields can still be filled.
+ */
+ @UnsupportedAppUsage
+ boolean isTextAutofillable() {
+ return mText instanceof Editable && onCheckIsTextEditor();
+ }
+
+ /**
* Returns true, only while processing a touch gesture, if the initial
* touch down event caused focus to move to the text view and as a result
* its selection changed. Only valid while processing the touch gesture
@@ -13610,7 +13619,7 @@
@Override
public void autofill(AutofillValue value) {
- if (!isTextEditable()) {
+ if (!isTextAutofillable()) {
Log.w(LOG_TAG, "cannot autofill non-editable TextView: " + this);
return;
}
@@ -13626,7 +13635,7 @@
@Override
public @AutofillType int getAutofillType() {
- return isTextEditable() ? AUTOFILL_TYPE_TEXT : AUTOFILL_TYPE_NONE;
+ return isTextAutofillable() ? AUTOFILL_TYPE_TEXT : AUTOFILL_TYPE_NONE;
}
/**
@@ -13640,7 +13649,7 @@
@Override
@Nullable
public AutofillValue getAutofillValue() {
- if (isTextEditable()) {
+ if (isTextAutofillable()) {
final CharSequence text = TextUtils.trimToParcelableSize(getText());
return AutofillValue.forText(text);
}
@@ -14042,7 +14051,8 @@
selectionStart, OffsetMapping.MAP_STRATEGY_CURSOR);
final int line = layout.getLineForOffset(offsetTransformed);
final float insertionMarkerX =
- layout.getPrimaryHorizontal(offsetTransformed)
+ layout.getPrimaryHorizontal(
+ offsetTransformed, layout.shouldClampCursor(line))
+ viewportToContentHorizontalOffset;
final float insertionMarkerTop = layout.getLineTop(line)
+ viewportToContentVerticalOffset;
diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java
index 7cb61fe..0a0071a 100644
--- a/core/java/android/widget/ToastPresenter.java
+++ b/core/java/android/widget/ToastPresenter.java
@@ -89,9 +89,10 @@
return view;
}
+ private final WeakReference<Context> mContext;
private final Resources mResources;
private final WeakReference<WindowManager> mWindowManager;
- private final WeakReference<AccessibilityManager> mAccessibilityManager;
+ private final IAccessibilityManager mAccessibilityManagerService;
private final INotificationManager mNotificationManager;
private final String mPackageName;
private final String mContextPackageName;
@@ -101,21 +102,14 @@
public ToastPresenter(Context context, IAccessibilityManager accessibilityManager,
INotificationManager notificationManager, String packageName) {
+ mContext = new WeakReference<>(context);
mResources = context.getResources();
mWindowManager = new WeakReference<>(context.getSystemService(WindowManager.class));
mNotificationManager = notificationManager;
mPackageName = packageName;
mContextPackageName = context.getPackageName();
mParams = createLayoutParams();
-
- // We obtain AccessibilityManager manually via its constructor instead of using method
- // AccessibilityManager.getInstance() for 2 reasons:
- // 1. We want to be able to inject IAccessibilityManager in tests to verify behavior.
- // 2. getInstance() caches the instance for the process even if we pass a different
- // context to it. This is problematic for multi-user because callers can pass a context
- // created via Context.createContextAsUser().
- mAccessibilityManager = new WeakReference<>(
- new AccessibilityManager(context, accessibilityManager, context.getUserId()));
+ mAccessibilityManagerService = accessibilityManager;
}
public String getPackageName() {
@@ -306,11 +300,20 @@
* enabled.
*/
public void trySendAccessibilityEvent(View view, String packageName) {
- final AccessibilityManager accessibilityManager = mAccessibilityManager.get();
- if (accessibilityManager == null) {
+ final Context context = mContext.get();
+ if (context == null) {
return;
}
+ // We obtain AccessibilityManager manually via its constructor instead of using method
+ // AccessibilityManager.getInstance() for 2 reasons:
+ // 1. We want to be able to inject IAccessibilityManager in tests to verify behavior.
+ // 2. getInstance() caches the instance for the process even if we pass a different
+ // context to it. This is problematic for multi-user because callers can pass a context
+ // created via Context.createContextAsUser().
+ final AccessibilityManager accessibilityManager = new AccessibilityManager(context,
+ mAccessibilityManagerService, context.getUserId());
+
if (!accessibilityManager.isEnabled()) {
accessibilityManager.removeClient();
return;
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index 5abb6e1..eaf037e 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -18,10 +18,7 @@
import android.annotation.IntRange;
import android.compat.annotation.UnsupportedAppUsage;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.TypedArray;
import android.os.Build;
import android.os.Message;
@@ -51,8 +48,6 @@
private boolean mRunning = false;
private boolean mStarted = false;
private boolean mVisible = false;
- @UnsupportedAppUsage
- private boolean mUserPresent = true;
public ViewFlipper(Context context) {
super(context);
@@ -70,39 +65,10 @@
a.recycle();
}
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (Intent.ACTION_SCREEN_OFF.equals(action)) {
- mUserPresent = false;
- updateRunning();
- } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
- mUserPresent = true;
- updateRunning(false);
- }
- }
- };
-
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- // Listen for broadcasts related to user-presence
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(Intent.ACTION_USER_PRESENT);
-
- // OK, this is gross but needed. This class is supported by the
- // remote views machanism and as a part of that the remote views
- // can be inflated by a context for another user without the app
- // having interact users permission - just for loading resources.
- // For exmaple, when adding widgets from a user profile to the
- // home screen. Therefore, we register the receiver as the current
- // user not the one the context is for.
- getContext().registerReceiverAsUser(mReceiver, android.os.Process.myUserHandle(),
- filter, null, getHandler());
-
if (mAutoStart) {
// Automatically start when requested
startFlipping();
@@ -113,8 +79,6 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mVisible = false;
-
- getContext().unregisterReceiver(mReceiver);
updateRunning();
}
@@ -186,7 +150,7 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void updateRunning(boolean flipNow) {
- boolean running = mVisible && mStarted && mUserPresent;
+ boolean running = mVisible && mStarted;
if (running != mRunning) {
if (running) {
showOnly(mWhichChild, flipNow);
@@ -198,7 +162,7 @@
}
if (LOGD) {
Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted=" + mStarted
- + ", mUserPresent=" + mUserPresent + ", mRunning=" + mRunning);
+ + ", mRunning=" + mRunning);
}
}
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index 5e2eceb..dee4935 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -177,7 +177,7 @@
* <code>1</code> would return the work profile {@link ProfileDescriptor}.</li>
* </ul>
*/
- abstract ProfileDescriptor getItem(int pageIndex);
+ public abstract ProfileDescriptor getItem(int pageIndex);
/**
* Returns the number of {@link ProfileDescriptor} objects.
@@ -438,8 +438,8 @@
&& isQuietModeEnabled(mWorkProfileUserHandle));
}
- protected class ProfileDescriptor {
- final ViewGroup rootView;
+ public static class ProfileDescriptor {
+ public final ViewGroup rootView;
private final ViewGroup mEmptyStateView;
ProfileDescriptor(ViewGroup rootView) {
this.rootView = rootView;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 2b39bb4..0a726d9 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -3023,28 +3023,31 @@
return shouldShowTabs()
&& (mMultiProfilePagerAdapter.getListAdapterForUserHandle(
UserHandle.of(UserHandle.myUserId())).getCount() > 0
- || shouldShowContentPreviewWhenEmpty())
+ || shouldShowStickyContentPreviewWhenEmpty())
&& shouldShowContentPreview();
}
/**
- * This method could be used to override the default behavior when we hide the preview area
- * when the current tab doesn't have any items.
+ * This method could be used to override the default behavior when we hide the sticky preview
+ * area when the current tab doesn't have any items.
*
- * @return true if we want to show the content preview area even if the tab for the current
- * user is empty
+ * @return {@code true} if we want to show the sticky content preview area even if the tab for
+ * the current user is empty
*/
- protected boolean shouldShowContentPreviewWhenEmpty() {
+ protected boolean shouldShowStickyContentPreviewWhenEmpty() {
return false;
}
- /**
- * @return true if we want to show the content preview area
- */
- protected boolean shouldShowContentPreview() {
+ @Override
+ public boolean shouldShowContentPreview() {
return isSendAction(getTargetIntent());
}
+ @Override
+ public boolean shouldShowServiceTargets() {
+ return shouldShowContentPreview() && !ActivityManager.isLowRamDeviceStatic();
+ }
+
private void updateStickyContentPreview() {
if (shouldShowStickyContentPreviewNoOrientationCheck()) {
// The sticky content preview is only shown when we show the work and personal tabs.
@@ -3406,11 +3409,7 @@
// There can be at most one row in the listview, that is internally
// a ViewGroup with 2 rows
public int getServiceTargetRowCount() {
- if (shouldShowContentPreview()
- && !ActivityManager.isLowRamDeviceStatic()) {
- return 1;
- }
- return 0;
+ return shouldShowServiceTargets() ? 1 : 0;
}
public int getAzLabelRowCount() {
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index 1eecb41..36038ae 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -19,7 +19,6 @@
import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE;
import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER;
-import android.app.ActivityManager;
import android.app.prediction.AppPredictor;
import android.content.ComponentName;
import android.content.Context;
@@ -425,11 +424,9 @@
}
public int getServiceTargetCount() {
- if (mChooserListCommunicator.isSendAction(mChooserListCommunicator.getTargetIntent())
- && !ActivityManager.isLowRamDeviceStatic()) {
+ if (mChooserListCommunicator.shouldShowServiceTargets()) {
return Math.min(mServiceTargets.size(), mChooserListCommunicator.getMaxRankedTargets());
}
-
return 0;
}
@@ -771,6 +768,10 @@
void sendListViewUpdateMessage(UserHandle userHandle);
boolean isSendAction(Intent targetIntent);
+
+ boolean shouldShowContentPreview();
+
+ boolean shouldShowServiceTargets();
}
/**
diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
index 7beb059..8197e26 100644
--- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
@@ -94,7 +94,7 @@
}
@Override
- ChooserProfileDescriptor getItem(int pageIndex) {
+ public ChooserProfileDescriptor getItem(int pageIndex) {
return mItems[pageIndex];
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ac15f11..7534d29 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -2623,13 +2623,13 @@
* An a11y delegate that expands resolver drawer when gesture navigation reaches a partially
* invisible target in the list.
*/
- private static class AppListAccessibilityDelegate extends View.AccessibilityDelegate {
+ public static class AppListAccessibilityDelegate extends View.AccessibilityDelegate {
private final ResolverDrawerLayout mDrawer;
@Nullable
private final View mBottomBar;
private final Rect mRect = new Rect();
- private AppListAccessibilityDelegate(ResolverDrawerLayout drawer) {
+ public AppListAccessibilityDelegate(ResolverDrawerLayout drawer) {
mDrawer = drawer;
mBottomBar = mDrawer.findViewById(R.id.button_bar_container);
}
diff --git a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
index 7677912..031f9d3 100644
--- a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
@@ -79,7 +79,7 @@
}
@Override
- ResolverProfileDescriptor getItem(int pageIndex) {
+ public ResolverProfileDescriptor getItem(int pageIndex) {
return mItems[pageIndex];
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index bbaaa47..a823c29 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -178,7 +178,7 @@
private boolean mHaveBatteryLevel;
private boolean mRecordingHistory;
- private static final int HISTORY_TAG_INDEX_LIMIT = 0x7ffe;
+ static final int HISTORY_TAG_INDEX_LIMIT = 0x7ffe;
private static final int MAX_HISTORY_TAG_STRING_LENGTH = 1024;
private final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<>();
@@ -1848,6 +1848,7 @@
}
return idx | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
} else {
+ tag.poolIdx = HistoryTag.HISTORY_TAG_POOL_OVERFLOW;
// Tag pool overflow: include the tag itself in the parcel
return HISTORY_TAG_INDEX_LIMIT | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
index ccc3454..4c2b2854 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
@@ -309,7 +309,11 @@
BatteryStats.HistoryTag tag = new BatteryStats.HistoryTag();
tag.readFromParcel(src);
tag.poolIdx = index & ~BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG;
- mHistoryTags.put(tag.poolIdx, tag);
+ if (tag.poolIdx < BatteryStatsHistory.HISTORY_TAG_INDEX_LIMIT) {
+ mHistoryTags.put(tag.poolIdx, tag);
+ } else {
+ tag.poolIdx = BatteryStats.HistoryTag.HISTORY_TAG_POOL_OVERFLOW;
+ }
outTag.setTo(tag);
} else {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 86ca077..a93e984 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1160,7 +1160,9 @@
mForceWindowDrawsBarBackgrounds, requestedVisibleTypes);
boolean oldDrawLegacy = mDrawLegacyNavigationBarBackground;
mDrawLegacyNavigationBarBackground =
- (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0;
+ ((requestedVisibleTypes | mLastForceConsumingTypes)
+ & WindowInsets.Type.navigationBars()) != 0
+ && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0;
if (oldDrawLegacy != mDrawLegacyNavigationBarBackground) {
mDrawLegacyNavigationBarBackgroundHandled =
mWindow.onDrawLegacyNavigationBarBackgroundChanged(
diff --git a/core/java/com/android/internal/usb/DumpUtils.java b/core/java/com/android/internal/usb/DumpUtils.java
index f974d9d..21c3e7b 100644
--- a/core/java/com/android/internal/usb/DumpUtils.java
+++ b/core/java/com/android/internal/usb/DumpUtils.java
@@ -16,6 +16,7 @@
package com.android.internal.usb;
+import static android.hardware.usb.UsbPort.FLAG_ALT_MODE_TYPE_DISPLAYPORT;
import static android.hardware.usb.UsbPortStatus.MODE_AUDIO_ACCESSORY;
import static android.hardware.usb.UsbPortStatus.MODE_DEBUG_ACCESSORY;
import static android.hardware.usb.UsbPortStatus.MODE_DFP;
@@ -26,6 +27,7 @@
import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
import android.annotation.NonNull;
+import android.hardware.usb.DisplayPortAltModeInfo;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbConfiguration;
import android.hardware.usb.UsbDevice;
@@ -177,6 +179,10 @@
dump.write("supports_compliance_warnings",
UsbPortProto.SUPPORTS_COMPLIANCE_WARNINGS,
port.supportsComplianceWarnings());
+ if (port.isAltModeSupported(FLAG_ALT_MODE_TYPE_DISPLAYPORT)) {
+ dump.write("supported_alt_modes", UsbPortProto.SUPPORTED_ALT_MODES,
+ FLAG_ALT_MODE_TYPE_DISPLAYPORT);
+ }
dump.end(token);
}
@@ -255,6 +261,12 @@
UsbPort.powerBrickConnectionStatusToString(status.getPowerBrickConnectionStatus()));
dump.write("compliance_warning_status", UsbPortStatusProto.COMPLIANCE_WARNINGS_STRING,
UsbPort.complianceWarningsToString(status.getComplianceWarnings()));
+ DisplayPortAltModeInfo displayPortAltModeInfo = status.getDisplayPortAltModeInfo();
+ if (displayPortAltModeInfo != null) {
+ dump.write("displayport_alt_mode_status",
+ UsbPortStatusProto.DISPLAYPORT_ALT_MODE_STATUS,
+ status.getDisplayPortAltModeInfo().toString());
+ }
dump.end(token);
}
}
diff --git a/core/java/com/android/internal/util/SettingsWrapper.java b/core/java/com/android/internal/util/SettingsWrapper.java
new file mode 100644
index 0000000..8cf6c18
--- /dev/null
+++ b/core/java/com/android/internal/util/SettingsWrapper.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+
+/**
+ * A wrapper class for accessing and modifying system settings that would help with testing.
+ */
+public class SettingsWrapper {
+
+ /** Retrieves the string value of a system setting */
+ public String getStringForUser(ContentResolver contentResolver, String name, int userHandle) {
+ return Settings.System.getStringForUser(contentResolver, name, userHandle);
+ }
+
+ /** Updates the string value of a system setting */
+ public String putStringForUser(ContentResolver contentResolver, String name, int userHandle) {
+ return Settings.System.getStringForUser(contentResolver, name, userHandle);
+ }
+}
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 52ffc98..a513ca5 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -21,6 +21,7 @@
import android.annotation.IdRes;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -53,10 +54,13 @@
private static final String TAG = "ResolverDrawerLayout";
private MetricsLogger mMetricsLogger;
+
+
/**
- * Max width of the whole drawer layout
+ * Max width of the whole drawer layout and its res id
*/
- private final int mMaxWidth;
+ private int mMaxWidthResId;
+ private int mMaxWidth;
/**
* Max total visible height of views not marked always-show when in the closed/initial state
@@ -152,6 +156,7 @@
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ResolverDrawerLayout,
defStyleAttr, 0);
+ mMaxWidthResId = a.getResourceId(R.styleable.ResolverDrawerLayout_maxWidth, -1);
mMaxWidth = a.getDimensionPixelSize(R.styleable.ResolverDrawerLayout_maxWidth, -1);
mMaxCollapsedHeight = a.getDimensionPixelSize(
R.styleable.ResolverDrawerLayout_maxCollapsedHeight, 0);
@@ -1042,6 +1047,18 @@
return mAlwaysShowHeight;
}
+ /**
+ * Max width of the drawer needs to be updated after the configuration is changed.
+ * For example, foldables have different layout width when the device is folded and unfolded.
+ */
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ if (mMaxWidthResId > 0) {
+ mMaxWidth = getResources().getDimensionPixelSize(mMaxWidthResId);
+ }
+ }
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int width = getWidth();
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c368fa8..56066b2 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1806,15 +1806,10 @@
if (!is_system_server && getuid() == 0) {
const int rc = createProcessGroup(uid, getpid());
if (rc != 0) {
- if (rc == -ESRCH) {
- // If process is dead, treat this as a non-fatal error
- ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc));
- } else {
- fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing "
- "CONFIG_CGROUP_CPUACCT?")
- : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid,
- /* pid= */ 0, strerror(-rc)));
- }
+ fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing "
+ "CONFIG_CGROUP_CPUACCT?")
+ : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid,
+ /* pid= */ 0, strerror(-rc)));
}
}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 481a2fb..f425c60 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -138,6 +138,7 @@
optional SettingProto touch_gesture_enabled = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto long_press_home_enabled = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto search_press_hold_nav_handle_enabled = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_long_press_home_enabled = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Assist assist = 7;
diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto
index 8889320..49b8450 100644
--- a/core/proto/android/service/usb.proto
+++ b/core/proto/android/service/usb.proto
@@ -238,10 +238,15 @@
MODE_DEBUG_ACCESSORY = 8;
}
+ enum AltMode {
+ ALT_MODE_DISPLAYPORT = 1;
+ }
+
// ID of the port. A device (eg: Chromebooks) might have multiple ports.
optional string id = 1;
repeated Mode supported_modes = 2;
optional bool supports_compliance_warnings = 3;
+ repeated AltMode supported_alt_modes = 4;
}
message UsbPortStatusProto {
@@ -271,6 +276,7 @@
optional bool is_power_transfer_limited = 8;
optional string usb_power_brick_status = 9;
optional string compliance_warnings_string = 10;
+ optional string displayport_alt_mode_status = 11;
}
message UsbPortStatusRoleCombinationProto {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7d1253c..8c9a3ff 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1467,10 +1467,9 @@
<!-- Allows an application to initiate a phone call without going through
the Dialer user interface for the user to confirm the call.
- <p>
- <em>Note: An app holding this permission can also call carrier MMI codes to change settings
- such as call forwarding or call waiting preferences.
- <p>Protection level: dangerous
+ <p class="note"><b>Note:</b> An app holding this permission can also call carrier MMI
+ codes to change settings such as call forwarding or call waiting preferences.</p>
+ <p>Protection level: dangerous</p>
-->
<permission android:name="android.permission.CALL_PHONE"
android:permissionGroup="android.permission-group.UNDEFINED"
diff --git a/core/res/res/layout/autofill_fill_dialog.xml b/core/res/res/layout/autofill_fill_dialog.xml
index d1a4935..37d2fa0 100644
--- a/core/res/res/layout/autofill_fill_dialog.xml
+++ b/core/res/res/layout/autofill_fill_dialog.xml
@@ -85,14 +85,18 @@
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:theme="@style/Theme.DeviceDefault.AutofillHalfScreenDialogButton"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
<Button
android:id="@+id/autofill_dialog_no"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp"
+ android:layout_height="40dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:paddingTop="0dp"
+ android:paddingBottom="0dp"
+ android:minWidth="0dp"
style="?android:attr/borderlessButtonStyle"
android:text="@string/autofill_save_no">
</Button>
@@ -107,9 +111,8 @@
<Button
android:id="@+id/autofill_dialog_yes"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp"
+ android:layout_height="40dp"
+ android:minWidth="0dp"
style="@style/AutofillHalfSheetTonalButton"
android:text="@string/autofill_save_yes"
android:visibility="gone" >
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index 85529d6..bed19a8 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -72,14 +72,18 @@
android:layout_marginTop="32dp"
android:layout_marginBottom="18dp"
android:theme="@style/Theme.DeviceDefault.AutofillHalfScreenDialogButton"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
<Button
android:id="@+id/autofill_save_no"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp"
+ android:layout_height="40dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:paddingTop="0dp"
+ android:paddingBottom="0dp"
+ android:minWidth="0dp"
style="?android:attr/borderlessButtonStyle"
android:text="@string/autofill_save_no">
</Button>
@@ -94,9 +98,8 @@
<Button
android:id="@+id/autofill_save_yes"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp"
+ android:layout_height="40dp"
+ android:minWidth="0dp"
style="@style/AutofillHalfSheetTonalButton"
android:text="@string/autofill_save_yes">
</Button>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index fa4b1a1..111451e 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -805,7 +805,7 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Dozvoljava vlasniku da ažurira aplikaciju koju je prethodno instalirala bez radnji korisnika"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Podešavanje pravila za lozinku"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontroliše dužinu i znakove dozvoljene u lozinkama i PIN-ovima za zaključavanje ekrana."</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadgledajte pokušaje otključavanja ekrana"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadzor pokušaja otključavanja ekrana"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Prati broj netačno unetih lozinki prilikom otključavanja ekrana i zaključava tablet ili briše podatke sa tableta ako je netačna lozinka uneta previše puta."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Nadgleda broj netačnih lozinki unetih pri otključavanju ekrana i zaključava Android TV uređaj ili briše sve podatke sa Android TV uređaja ako se unese previše netačnih lozinki."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Prati broj netačno unetih lozinki pri otključavanju ekrana i zaključava sistem za info-zabavu ili briše sve podatke sa sistema za info-zabavu ako je netačna lozinka uneta previše puta."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 9f33f501..9ab6ce9 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -810,7 +810,7 @@
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Сачыць за колькасцю няправільных набраных пароляў падчас разблакоўкі экрана і блакаваць планшэт або сціраць усе дадзеныя на ім, калі няправільны пароль набраны занадта шмат разоў."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і заблакіраваць прыладу Android TV або сцерці ўсе даныя на прыладзе, калі няправільны пароль набраны занадта шмат разоў."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Падчас разблакіроўкі экрана сачыць за колькасцю няправільна набраных пароляў і, калі няправільны пароль набраны занадта шмат разоў, заблакіраваць інфармацыйна-забаўляльную сістэму ці сцерці ў ёй усе даныя."</string>
- <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Сачыць за колькасцю няправільных набраных пароляў падчас разблакоўкі экрана і блакаваць тяэлефон або сціраць усе дадзеныя на ім, калі набрана занадта шмат няправільных пароляў."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і блакіраваць тэлефон або сціраць усе даныя на ім, калі набрана занадта шмат няправільных пароляў."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і блакіраваць планшэт або сцерці ўсе даныя гэтага карыстальніка, калі няправільны пароль набраны занадта шмат разоў."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і заблакіраваць прыладу Android TV або сцерці ўсе даныя карыстальніка, калі няправільны пароль набраны занадта шмат разоў."</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Падчас разблакіроўкі экрана сачыць за колькасцю няправільна набраных пароляў і, калі няправільны пароль набраны занадта шмат разоў, заблакіраваць інфармацыйна-забаўляльную сістэму ці сцерці ўсе даныя гэтага профілю."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index dd2a0ac..08e07dc 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1887,8 +1887,8 @@
<string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Durant 1 hora}many{Durant # hores}other{Durant # hores}}"</string>
<string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Durant 1 h}many{Durant # h}other{Durant # h}}"</string>
<string name="zen_mode_until_next_day" msgid="1403042784161725038">"Finalitza: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
- <string name="zen_mode_until" msgid="2250286190237669079">"Fins a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
- <string name="zen_mode_alarm" msgid="7046911727540499275">"Fins a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (propera alarma)"</string>
+ <string name="zen_mode_until" msgid="2250286190237669079">"Finalitza: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="7046911727540499275">"Finalitza: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (propera alarma)"</string>
<string name="zen_mode_forever" msgid="740585666364912448">"Fins que no el desactivis"</string>
<string name="zen_mode_forever_dnd" msgid="3423201955704180067">"Fins que desactivis el mode No molestis"</string>
<string name="zen_mode_rule_name_combination" msgid="7174598364351313725">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 6195110..fe82a73 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -670,12 +670,12 @@
<string name="device_unlock_notification_name" msgid="2632928999862915709">"Enhedsoplåsning"</string>
<string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Prøv en anden metode til oplåsning"</string>
<string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Brug ansigtsoplåsning, hvis dit fingeraftryk ikke genkendes, f.eks. når du har våde fingre"</string>
- <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Brug oplåsning med fingeraftryk, hvis dit ansigt ikke genkendes, f.eks. når der ikke er nok lys"</string>
+ <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Brug fingeroplåsning, hvis dit ansigt ikke genkendes, f.eks. når der ikke er nok lys"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansigtsoplåsning"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Der er et problem med Ansigtsoplåsning"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Tryk for at slette din ansigtsmodel, og tilføj derefter dit ansigt igen"</string>
<string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"Hvis du vil bruge ansigtsoplåsning, skal du aktivere "<b>"Kameraadgang"</b>" under Indstillinger > Privatliv"</string>
- <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Oplåsning med fingeraftryk"</string>
+ <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Fingeroplåsning"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"Fingeraftrykssensoren kan ikke bruges"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Få den repareret."</string>
<string name="face_acquired_insufficient" msgid="6889245852748492218">"Din ansigtsmodel kan ikke oprettes. Prøv igen."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 21aea82..f32c6e1 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -670,8 +670,8 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícono de huella dactilar"</string>
<string name="device_unlock_notification_name" msgid="2632928999862915709">"Desbloqueo del dispositivo"</string>
<string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Prueba otra forma para desbloquear el dispositivo"</string>
- <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Usa la función de Desbloqueo facial cuando no se reconoce tu huella dactilar (por ejemplo cuando tienes los dedos mojados)"</string>
- <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Usa la función de Desbloqueo facial cuando no se reconoce tu rostro (por ejemplo cuando no hay suficiente luz)"</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Usa el Desbloqueo facial si no se reconoce tu huella dactilar (p. ej., si tienes los dedos mojados)"</string>
+ <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Usa el Desbloqueo con huellas dactilares si no se reconoce tu rostro (p. ej., si hay poca luz)"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con el Desbloqueo facial"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Presiona para borrar el modelo de rostro y, luego, vuelve a agregar tu rostro"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ae55f42..5ed5e63 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -670,8 +670,8 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icono de huella digital"</string>
<string name="device_unlock_notification_name" msgid="2632928999862915709">"Desbloqueo del dispositivo"</string>
<string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Prueba otro método de desbloqueo"</string>
- <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Usa Desbloqueo facial cuando no se reconozca tu huella digital (por ejemplo, cuando tus dedos estén húmedos)"</string>
- <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Usa Desbloqueo con huella digital cuando no se reconozca tu cara (por ejemplo, cuando no haya suficiente luz)"</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Usa Desbloqueo facial cuando no se reconozca tu huella (p. ej., si tienes los dedos mojados)"</string>
+ <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Usa Desbloqueo con huella digital cuando no se reconozca tu cara (p. ej., si hay poca luz)"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con Desbloqueo facial"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Toca para eliminar tu modelo facial y luego añade de nuevo tu cara"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 4bf5e8e..6c3824b 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -821,7 +821,7 @@
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Kustutage tahvelarvuti andmed hoiatamata, lähtestades arvuti tehaseandmetele."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Kustutatakse teie Android TV seadme andmed ilma hoiatamata, lähtestades seadme tehase andmetele."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Teabe ja meelelahutuse süsteemi andmete hoiatamata kustutamine tehase andmetele lähtestamise abil."</string>
- <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Telefoniandmete hoiatuseta kustutamine, lähtestades telefoni tehaseseadetele."</string>
+ <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Kustutab telefoniandmed hoiatuseta, lähtestades telefoni tehaseseadetele."</string>
<string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profiili andmete kustutamine"</string>
<string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Kasutaja andmete kustutamine"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Kustutatakse selle kasutaja andmed sellest tahvelarvutist ilma hoiatamata."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 46268a6..44bb4a3 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -319,7 +319,7 @@
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"enregistrer des fichiers audio"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Activité physique"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"accéder à vos activités physiques"</string>
- <string name="permgrouplab_camera" msgid="9090413408963547706">"appareil photo"</string>
+ <string name="permgrouplab_camera" msgid="9090413408963547706">"Appareil photo"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"prendre des photos et filmer des vidéos"</string>
<string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"Appareils à proximité"</string>
<string name="permgroupdesc_nearby_devices" msgid="3213561597116913508">"découvrir les appareils à proximité et s\'y connecter"</string>
@@ -670,8 +670,8 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string>
<string name="device_unlock_notification_name" msgid="2632928999862915709">"Déverrouillage de l\'appareil"</string>
<string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Essayez une autre façon de déverrouiller"</string>
- <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Utilisez Déverrouillage par reconnaissance faciale lorsque votre empreinte digitale n\'est pas reconnue, par exemple lorsque vos doigts sont mouillés"</string>
- <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Utilisez Déverrouillage par empreinte digitale lorsque votre visage n\'est pas reconnu, par exemple lorsque la luminosité est insuffisante"</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Utilisez le Déverrouillage par reconnaissance faciale lorsque votre empreinte digitale n\'est pas reconnue, par exemple lorsque vos doigts sont mouillés"</string>
+ <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Utilisez le Déverrouillage par empreinte digitale lorsque votre visage n\'est pas reconnu, par exemple lorsque la luminosité est insuffisante"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Déverrouillage par reconnaissance faciale"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problème avec la fonctionnalité de déverrouillage par reconnaissance faciale"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Touchez pour supprimer votre modèle facial, puis ajoutez votre visage de nouveau"</string>
@@ -809,7 +809,7 @@
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller la tablette ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint"</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Surveillez le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouillez votre appareil Android TV ou effacez toutes les données qu\'il contient en cas d\'un nombre trop élevé de tentatives."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Surveillez le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouillez le système d\'infodivertissement ou effacez toutes ses données en cas d\'un nombre trop élevé de tentatives."</string>
- <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouille le téléphone ou efface toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran est contrôlé. Si le nombre maximal de tentatives de saisie du mot de passe est atteint, le téléphone est verrouillé ou toutes ses données sont effacées."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Surveille le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouille la tablette ou efface toutes les données de l\'utilisateur en cas d\'un nombre trop élevé de tentatives."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Surveillez le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouillez votre appareil Android TV ou effacez toutes les données de l\'utilisateur en cas d\'un nombre trop élevé de tentatives."</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Surveillez le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouillez le système d\'infodivertissement ou effacez toutes les données de ce profil en cas d\'un nombre trop élevé de tentatives."</string>
@@ -822,7 +822,7 @@
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Effacer les données de la tablette sans avertissement, en rétablissant les paramètres par défaut"</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Effacez les données de votre appareil Android TV sans avertissement en effectuant une réinitialisation des paramètres d\'usine."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Effacez les données du système d\'infodivertissement sans avertissement en rétablissant les paramètres par défaut."</string>
- <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Effacer les données du téléphone sans avertissement en rétablissant les paramètres par défaut."</string>
+ <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Les données du téléphone sont effacées sans avertissement en rétablissant les paramètres par défaut."</string>
<string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Effacer les données de profil"</string>
<string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Effacer les données de l\'utilisateur"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Effacer les données de l\'utilisateur sur cette tablette sans avertissement."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 702f774..1085219 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -2125,7 +2125,7 @@
<string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Le Bluetooth restera activé en mode Avion"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"Chargement…"</string>
<string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # fichier}one{{file_name} + # fichier}many{{file_name} + # fichiers}other{{file_name} + # fichiers}}"</string>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucune recommandation de personnes avec lesquelles effectuer un partage"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucun destinataire recommandé"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Liste des applications"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Cette application n\'a pas reçu l\'autorisation d\'enregistrer des contenus audio, mais peut le faire via ce périphérique USB."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Accueil"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f38db92..97f8c2d 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -804,11 +804,11 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"इससे होल्डर उस ऐप्लिकेशन को अपने-आप अपडेट कर पाएगा जो उसने पहले इंस्टॉल किया था"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियम सेट करना"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"स्क्रीन लॉक पासवर्ड और पिन की लंबाई और उनमें स्वीकृत वर्णों को नियंत्रित करना."</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रीन अनलॉक करने के की कोशिशों पर नज़र रखना"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रीन अनलॉक करने की कोशिशों पर नज़र रखना"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्क्रीन को अनलॉक करते समय गलत लिखे गए पासवर्ड की संख्या पर निगरानी करें, और बहुत ज़्यादा बार गलत पासवर्ड लिखे जाने पर टैबलेट लॉक करें या टैबलेट का संपूर्ण डेटा मिटाएं."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो अपने Android TV डिवाइस को तुरंत लॉक करें या इसका सभी डेटा मिटाएं."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो सूचना और मनोरंजन की सुविधा देने वाले डिवाइस को लॉक करें या इस डिवाइस का सारा डेटा मिटाएं."</string>
- <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रीन को अनलॉक करते समय जितनी बार गलत पासवर्ड लिखा गया है, उसकी संख्या पर नज़र रखना और अगर बहुत बार गलत पासवर्ड डाले गए हैं, तो फ़ोन को लॉक कर देना या फ़ोन का सारा डेटा मिटा देना."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो अपने फ़ोन को तुरंत लॉक करें या फ़ोन का सारा डेटा मिटा दें."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रीन का लॉक खोलते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें, और अगर बार-बार ज़्यादा पासवर्ड लिखे जाते हैं तो टैबलेट को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो अपने Android TV डिवाइस को तुरंत लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटाएं."</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो सूचना और मनोरंजन की सुविधा देने वाले डिवाइस को लॉक करें या इस प्रोफ़ाइल का सारा डेटा मिटाएं."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index d26f41d..c1add6c 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -805,7 +805,7 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Nositelju omogućuje ažuriranje aplikacije koju je prethodno instalirao bez radnje korisnika"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Postavi pravila zaporke"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Upravlja duljinom i znakovima koji su dopušteni u zaporkama i PIN-ovima zaključavanja zaslona."</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadziri pokušaje otključavanja zaslona"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadzor pokušaja otključavanja zaslona"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Nadziri broj netočnih zaporki unesenih pri otključavanju zaslona i zaključaj tabletno računalo ili izbriši sve podatke na njemu ako je uneseno previše netočnih zaporki."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava Android TV uređaj ili s njega briše sve podatke ako se unese previše netočnih zaporki."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava sustav za informiranje i zabavu ili briše sve njegove podatke ako se unese previše netočnih zaporki."</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 7b23dec..f1f2cc8 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -804,7 +804,7 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Mengizinkan pemegang mengupdate aplikasi yang sebelumnya diinstal tanpa tindakan pengguna"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Setel aturan sandi"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Mengontrol panjang dan karakter yang diizinkan dalam sandi dan PIN kunci layar."</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"Pantau upaya pembukaan kunci layar"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"Memantau upaya pembukaan kunci layar"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci tablet atau menghapus semua data tablet jika terjadi terlalu banyak kesalahan memasukkan sandi."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci perangkat Android TV atau menghapus semua data perangkat Android TV jika terlalu banyak sandi salah diketikkan."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci sistem infotainmen atau menghapus semua data sistem infotainmen jika terlalu banyak kesalahan memasukkan sandi."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index f475716..651927a 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -670,13 +670,13 @@
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona dell\'impronta"</string>
<string name="device_unlock_notification_name" msgid="2632928999862915709">"Sblocco dispositivo"</string>
<string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Prova un\'altra modalità di sblocco"</string>
- <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Usa lo sblocco con il volto se la tua impronta non viene riconosciuta, ad esempio quando hai le dita bagnate"</string>
- <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Usa lo sblocco con l\'impronta se il tuo volto non viene riconosciuto, ad esempio quando non c\'è abbastanza luce"</string>
- <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Sblocco con il volto"</string>
- <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con Sblocco con il volto"</string>
+ <string name="alternative_face_setup_notification_content" msgid="3384959224091897331">"Usa lo Sblocco con il Volto se la tua impronta non viene riconosciuta, ad esempio se hai le dita bagnate"</string>
+ <string name="alternative_fp_setup_notification_content" msgid="7454096947415721639">"Usa lo Sblocco con l\'Impronta se il tuo volto non viene riconosciuto, ad esempio se non c\'è abbastanza luce"</string>
+ <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Sblocco con il Volto"</string>
+ <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con Sblocco con il Volto"</string>
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Tocca per eliminare il tuo modello del volto e poi riaggiungi il tuo volto"</string>
- <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"Per utilizzare lo sblocco con il volto, attiva "<b>"l\'accesso alla fotocamera"</b>" in Impostazioni > Privacy"</string>
- <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Sblocco con l\'impronta"</string>
+ <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"Per utilizzare lo Sblocco con il Volto, attiva "<b>"l\'accesso alla fotocamera"</b>" in Impostazioni > Privacy"</string>
+ <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Sblocco con l\'Impronta"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"Impossibile utilizzare il sensore di impronte digitali"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Contatta un fornitore di servizi di riparazione."</string>
<string name="face_acquired_insufficient" msgid="6889245852748492218">"Impossibile creare il modello del volto. Riprova."</string>
@@ -709,20 +709,20 @@
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="5085202213036026288">"Imposs. verificare volto. Hardware non disponibile."</string>
- <string name="face_error_timeout" msgid="2598544068593889762">"Riprova lo sblocco con il volto"</string>
+ <string name="face_error_timeout" msgid="2598544068593889762">"Riprova lo Sblocco con il Volto"</string>
<string name="face_error_no_space" msgid="5649264057026021723">"Imposs. salvare dati nuovi volti. Elimina un volto vecchio."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Operazione associata al volto annullata."</string>
- <string name="face_error_user_canceled" msgid="5766472033202928373">"Sblocco con il volto annullato dall\'utente"</string>
+ <string name="face_error_user_canceled" msgid="5766472033202928373">"Sblocco con il Volto annullato dall\'utente"</string>
<string name="face_error_lockout" msgid="7864408714994529437">"Troppi tentativi. Riprova più tardi."</string>
- <string name="face_error_lockout_permanent" msgid="8533257333130473422">"Troppi tentativi. Sblocco con il volto non disponibile."</string>
+ <string name="face_error_lockout_permanent" msgid="8533257333130473422">"Troppi tentativi. Sblocco con il Volto non disponibile."</string>
<string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"Troppi tentativi. Inserisci il blocco schermo."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Impossibile verificare il volto. Riprova."</string>
- <string name="face_error_not_enrolled" msgid="1134739108536328412">"Non hai configurato lo sblocco con il volto"</string>
- <string name="face_error_hw_not_present" msgid="7940978724978763011">"Sblocco con il volto non è supportato su questo dispositivo"</string>
+ <string name="face_error_not_enrolled" msgid="1134739108536328412">"Non hai configurato lo Sblocco con il Volto"</string>
+ <string name="face_error_hw_not_present" msgid="7940978724978763011">"Sblocco con il Volto non è supportato su questo dispositivo"</string>
<string name="face_error_security_update_required" msgid="5076017208528750161">"Sensore temporaneamente disattivato."</string>
<string name="face_name_template" msgid="3877037340223318119">"Volto <xliff:g id="FACEID">%d</xliff:g>"</string>
- <string name="face_app_setting_name" msgid="5854024256907828015">"Usa lo sblocco con il volto"</string>
- <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usa lo sblocco con il volto o il blocco schermo"</string>
+ <string name="face_app_setting_name" msgid="5854024256907828015">"Usa lo Sblocco con il Volto"</string>
+ <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usa lo Sblocco con il Volto o il blocco schermo"</string>
<string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Usa il tuo volto per continuare"</string>
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Per continuare devi usare il tuo volto o il tuo blocco schermo"</string>
<string-array name="face_error_vendor">
@@ -974,7 +974,7 @@
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Riprova"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Riprova"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Sblocca per accedere a funzioni e dati"</string>
- <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Numero massimo di tentativi di sblocco con il volto superato"</string>
+ <string name="faceunlock_multiple_failures" msgid="681991538434031708">"Numero massimo di tentativi di Sblocco con il Volto superato"</string>
<string name="lockscreen_missing_sim_message_short" msgid="1229301273156907613">"Nessuna SIM presente"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="3986843848305639161">"Nessuna SIM presente nel tablet."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="3903140876952198273">"Nessuna SIM presente nel dispositivo Android TV."</string>
@@ -1044,7 +1044,7 @@
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"Espandi area di sblocco."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2968195219692413046">"Sblocco con scorrimento."</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="8669128146589233293">"Sblocco con sequenza."</string>
- <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Sblocco con il volto."</string>
+ <string name="keyguard_accessibility_face_unlock" msgid="4533832120787386728">"Sblocco con il Volto."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="4020864007967340068">"Sblocco con PIN."</string>
<string name="keyguard_accessibility_sim_pin_unlock" msgid="4895939120871890557">"Sblocco tramite PIN della SIM."</string>
<string name="keyguard_accessibility_sim_puk_unlock" msgid="3459003464041899101">"Sblocco tramite PUK della SIM."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index a710300..2a43258 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -804,7 +804,7 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Бұған дейін орнатылған қолданбаның автоматты түрде жаңартылуына мүмкіндік береді."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Құпия сөз ережелерін тағайындау"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Экран бекітпесінің құпия сөздерінің және PIN кодтарының ұзындығын және оларда рұқсат етілген таңбаларды басқару."</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"Экран құлпын ашу әркеттерін бақылау"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"Экран құлпын ашу әрекеттерін бақылау"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Экран бекітпесін ашқан кезде терілген қате құпия сөздердің санын бақылау және планшетті бекіту немесе тым көп қате құпия сөздер терілген болса, планшеттің бүкіл деректерін өшіру."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Экранның құлпын ашу кезінде қате енгізілген құпия сөздердің санын бақылау, құпия сөз тым көп қате енгізілген жағдайда, Android TV құрылғысын құлыптау және Android TV құрылғыңыздың барлық деректерінен тазарту."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Экран құлпын ашқан кезде, терілген қате құпия сөздердің саны бақыланады, сондай-ақ құпия сөздер бірнеше рет қате терілсе, ақпараттық-сауықтық жүйе құлыпталады немесе оның барлық дерегі жойылады."</string>
@@ -817,7 +817,7 @@
<string name="policydesc_resetPassword" msgid="4626419138439341851">"Экран құлпын өзгерте алады."</string>
<string name="policylab_forceLock" msgid="7360335502968476434">"Экранды құлыптау"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Экранның қашан және қалай құлыпталатынын басқара алады."</string>
- <string name="policylab_wipeData" msgid="1359485247727537311">"Барлық деректерді өшіру"</string>
+ <string name="policylab_wipeData" msgid="1359485247727537311">"Барлық деректі өшіру"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Планшет дерекқорын ескертусіз, зауыттық дерекқорын қайта реттеу арқылы өшіру."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Зауыттық деректерді қалпына келтіру арқылы Android TV құрылғыңыздың деректерін ескертусіз тазартыңыз."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Зауыттық деректерді қалпына келтіру арқылы ақпараттық-сауықтық жүйе дерегі ескертусіз өшіріледі."</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index eb4f2a7..b75fa4b 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -328,7 +328,7 @@
<string name="permgroupdesc_phone" msgid="270048070781478204">"ಫೋನ್ ಕರೆ ಮಾಡಲು ಹಾಗೂ ನಿರ್ವಹಿಸಲು"</string>
<string name="permgrouplab_sensors" msgid="9134046949784064495">"ಬಾಡಿ ಸೆನ್ಸರ್"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತು ಸೆನ್ಸಾರ್ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
- <string name="permgrouplab_notifications" msgid="5472972361980668884">"ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="permgrouplab_notifications" msgid="5472972361980668884">"ನೋಟಿಫಿಕೇಶನ್ಗಳು"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸಿ"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ವಿಂಡೋ ವಿಷಯವನ್ನು ಹಿಂಪಡೆಯುತ್ತದೆ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"ನೀವು ಬಳಸುತ್ತಿರುವ ವಿಂಡೋದ ವಿಷಯ ಪರೀಕ್ಷಿಸುತ್ತದೆ."</string>
@@ -2130,7 +2130,7 @@
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ಹೋಮ್"</string>
<string name="accessibility_system_action_back_label" msgid="4205361367345537608">"ಹಿಂದಕ್ಕೆ"</string>
<string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"ಇತ್ತೀಚಿನ ಆ್ಯಪ್ಗಳು"</string>
- <string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"ನೋಟಿಫಿಕೇಶನ್ಗಳು"</string>
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"ಪವರ್ ಡೈಲಾಗ್"</string>
<string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"ಲಾಕ್ ಸ್ಕ್ರೀನ್"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 2934728..78f6a34 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -763,7 +763,7 @@
<string name="permlab_readNetworkUsageHistory" msgid="8470402862501573795">"тармактын колдонулуш таржымалын окуу"</string>
<string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"Колдонмого белгилүү бир тармактарга жана колдонмолорго байланыштуу тармактын колдонулушу жөнүндө таржымалды окуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_manageNetworkPolicy" msgid="6872549423152175378">"тармак саясатын башкаруу"</string>
- <string name="permdesc_manageNetworkPolicy" msgid="1865663268764673296">"Колдонмого тармак саясаттарын башкаруу жана колдонмого мүнөздүү эрежелерди белгилөө мүмкүнчүлүгүн берет."</string>
+ <string name="permdesc_manageNetworkPolicy" msgid="1865663268764673296">"Колдонмого тармак эрежелерин башкаруу жана колдонмого мүнөздүү эрежелерди белгилөө мүмкүнчүлүгүн берет."</string>
<string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"тармактын колдонулуш эсеп-кысабын өзгөртүү"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"Колдонмого желени башка колдонмолордун пайдалануусун башкарган тууралоолорду киргизүү уруксатын берет. Жөнөкөй колдонмолор үчүн эмес."</string>
<string name="permlab_accessNotifications" msgid="7130360248191984741">"эскертүүлөр менен иштөө"</string>
@@ -808,7 +808,7 @@
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Экрандын кулпусу ачылып жатканда туура эмес терилген сырсөздөрдүн санын текшерип, эгер алардын саны өтө эле көп болсо, планшетти кулпулаңыз же планшеттеги бардык маалыматтарды тазалап салыңыз."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Экрандын кулпусун ачуу учурунда сырсөздөр канча жолу туура эмес терилгенин тескөө жана сырсөз өтө көп жолу туура эмес терилген болсо, Android TV түзмөгүңүздү кулпулап же Android TV түзмөгүңүздөгү бардык дайын-даректериңизди тазалап салуу."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Экрандын кулпусу ачылып жатканда туура эмес терилген сырсөздөрдүн саны текшерилип, эгер алардын саны өтө эле көп болсо, инфозоок тутуму кулпуланып же инфозоок тутумундагы бардык маалыматтар өчүрүлөт."</string>
- <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Экрандын кулпусу ачылып жатканда туура эмес терилген сырсөздөрдүн санын текшерип, эгер алардын саны өтө эле көп болсо, телефонду кулпулаңыз же телефондогу бардык маалыматтарды тазалап салыңыз."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Экрандын кулпусун ачуу аракеттерине көз салып, сырсөз өтө көп жолу туура эмес терилсе, телефонду кулпулайт же андагы бардык нерселерди өчүрүп салат."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Экрандын кулпусун ачуу учурунда туура эмес терилген сырсөздөрдү тескөө жана сырсөз өтө көп жолу туура эмес терилген болсо, планшетти кулпулап же бул колдонуучунун бардык дайындарын тазалап салуу."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Экрандын кулпусун ачуу учурунда сырсөздөр канча жолу туура эмес терилгенин тескөө жана сырсөз өтө көп жолу туура эмес терилген болсо, Android TV түзмөгүңүздү кулпулап же колдонуучунун бардык дайындарын тазалап салуу."</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Экрандын кулпусун ачуу учурунда туура эмес терилген сырсөздөрдү тескөө жана сырсөз өтө көп жолу туура эмес терилген болсо, инфозоок тутуму кулпуланып же бул профилдин бардык дайындары өчүрүлөт."</string>
@@ -1716,7 +1716,7 @@
<string name="color_inversion_feature_name" msgid="2672824491933264951">"Түстөрдү инверсиялоо"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Түстөрдү тууралоо"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Бир кол режими"</string>
- <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дагы караңгы"</string>
+ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Кошумча караңгылатуу"</string>
<string name="hearing_aids_feature_name" msgid="1125892105105852542">"Угуу түзмөктөрү"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> күйгүзүлдү."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өчүрүлдү."</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 43d7a0b..0ce7b13 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -808,7 +808,7 @@
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Дэлгэц түгжигдсэн үед нууц үг буруу оруулалтын тоог хянах ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал таблетыг түгжих болон таблетын бүх датаг арилгана"</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Дэлгэцийн түгжээг тайлахаар буруу оруулсан нууц үгийн тоог хянаж, нууц үгийг хэт олон удаа буруу оруулсан тохиолдолд таны Android TV төхөөрөмжийг түгжиж эсвэл үүний бүх өгөгдлийг устгана."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Дэлгэцийн түгжээг тайлахад буруу бичиж оруулсан нууц үгний тоог хянаж, инфотэйнмент системийг түгжих эсвэл хэт олон удаа нууц үгийг буруу бичиж оруулсан тохиолдолд инфотэйнмент системийн бүх өгөгдлийг устгана."</string>
- <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Дэлгэц түгжигдсэн үед нууц үг буруу оруулалтын тоог хянах, ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал утсыг түгжих болон утасны бүх датаг арилгана"</string>
+ <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Дэлгэц түгжигдсэн үед нууц үг буруу оруулалтын тоог хянах, ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал утсыг түгжиж эсвэл утасны бүх өгөгдлийг арилгана"</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Дэлгэцийн түгжээг тайлахад оруулсан буруу нууц үгийн давтамжийг хянаж таблетыг түгжих эсвэл буруу нууц үгийг хэт олон удаа оруулсан тохиолдолд энэ хэрэглэгчийн мэдээллийг устгах."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Дэлгэцийн түгжээг тайлахаар буруу оруулсан нууц үгийн тоог хянаж, нууц үгийг хэт олон удаа буруу оруулсан тохиолдолд таны Android TV төхөөрөмжийг түгжиж эсвэл энэ хэрэглэгчийн бүх өгөгдлийг устгана."</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Дэлгэцийн түгжээг тайлахад буруу бичиж оруулсан нууц үгний тоог хянаж, инфотэйнмент системийг түгжих эсвэл хэт олон удаа нууц үгийг буруу бичиж оруулсан тохиолдолд энэ профайлын бүх өгөгдлийг устгана."</string>
@@ -817,11 +817,11 @@
<string name="policydesc_resetPassword" msgid="4626419138439341851">"Дэлгэцийн түгжээг өөрчлөх."</string>
<string name="policylab_forceLock" msgid="7360335502968476434">"Дэлгэц түгжих"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Дэлгэц хэзээ яаж түгжихийг удирдах"</string>
- <string name="policylab_wipeData" msgid="1359485247727537311">"Бүх датаг арилгах"</string>
+ <string name="policylab_wipeData" msgid="1359485247727537311">"Бүх өгөгдлийг арилгах"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Үйлдвэрийн дата утгыг өгсөнөөр таблетын дата шууд арилгагдана."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Таны Android TV төхөөрөмжийн өгөгдлийг танд анхааруулалгүйгээр үйлдвэрээс гарсан төлөвт шилжүүлэн устгана."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Үйлдвэрийн өгөгдлийн төлөвт үйлдлийг гүйцэтгэснээр инфотэйнмент системийн өгөгдлийг сануулгагүйгээр устгана."</string>
- <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Сануулахгүйгээр утасны бүх мэдээллийг устгаж, үйлдвэрийн өгөгдмөл байдалд шилжүүлнэ"</string>
+ <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Сануулахгүйгээр утасны бүх өгөгдлийг арилгаж, үйлдвэрийн өгөгдлийн тохиргоонд шинэчилнэ"</string>
<string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Профайлын өгөгдлийг устгах"</string>
<string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Хэрэглэгчийн мэдээллийг арилгах"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Анхааруулга өгөхгүйгээр энэ хэрэглэгчийн энэ таблет дээрх мэдээллийг устгах."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 1550c04..570c499 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -804,11 +804,11 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"होल्डरला वापरकर्त्याच्या कृतीशिवाय पूर्वी इंस्टॉल केलेले अॅप अपडेट करण्याची अनुमती देते"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियम सेट करा"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"स्क्रीन लॉक पासवर्ड आणि पिन मध्ये अनुमती दिलेले लांबी आणि वर्ण नियंत्रित करा."</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रीन अनलॉक प्रयत्नांचे परीक्षण करा"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रीन अनलॉक प्रयत्नांवर लक्ष ठेवा"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"टाइप केलेल्या अयोग्य पासवर्डांच्या अंकांचे परीक्षण करा. स्क्रीन अनलॉक केली जाते, तेव्हा टॅबलेट लॉक करा किंवा बरेच पासवर्ड टाइप केले असल्यास टॅबलेटचा सर्व डेटा मिटवा."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या पासवर्ड संख्येचे परीक्षण करते आणि Android TV डिव्हाइस लॉक करते किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास Android TV डिव्हाइसचा सर्व डेटा मिटवते."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"टाइप केलेल्या चुकीच्या पासवर्डच्या संख्येचे निरीक्षण करा. स्क्रीन अनलॉक करताना, इंफोटेनमेंट सिस्टीम लॉक करा किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास, इंफोटेनमेंट सिस्टीमचा सर्व डेटा मिटवा."</string>
- <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"टाइप केलेल्या अयोग्य पासवर्डांच्या अंकांचे परीक्षण करा. स्क्रीन अनलॉक केली जाते, तेव्हा फोन लॉक करा किंवा बरेच पासवर्ड टाइप केले असल्यास फोनचा सर्व डेटा मिटवा."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रीन अनलॉक करताना टाइप केलेल्या अयोग्य पासवर्डच्या संख्येवर लक्ष ठेवा. बरेच पासवर्ड टाइप केले असल्यास फोन लॉक करा किंवा फोनचा सर्व डेटा मिटवा."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या पासवर्डांच्या संख्येचे परीक्षण करा आणि टॅबलेट लॉक करा किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास या वापरकर्त्याचा सर्व डेटा मिटवा."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या पासवर्ड संख्येचे परीक्षण करते आणि Android TV डिव्हाइस लॉक करते किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास वापरकर्त्याचा सर्व डेटा मिटवते."</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या पासवर्डच्या संख्येचे निरीक्षण करा आणि इंफोटेनमेंट सिस्टीम लॉक करा किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास, या प्रोफाइलचा सर्व डेटा मिटवा."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index f39bdf4..af07eaf 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -2124,7 +2124,7 @@
<string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Bluetooth akan kekal hidup semasa dalam mod pesawat"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"Memuatkan"</string>
<string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # fail}other{{file_name} + # fail}}"</string>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Tiada orang yang disyorkan untuk berkongsi"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Tiada orang yang disyorkan untuk membuat perkongsian"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Senarai apl"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Apl ini belum diberikan kebenaran merakam tetapi dapat merakam audio melalui peranti USB ini."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Skrin Utama"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 4ac0b2f..d4f08e4 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -808,7 +808,7 @@
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"မျက်နှာပြင်ကို သော့ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက်၊ စကားဝှက် ရိုက်ထည့်မှု သိပ်များနေလျှင် တက်ဘလက်ကို သော့ခတ်ရန် သို့မဟုတ် တက်ဘလက် ဒေတာ အားလုံးကို ဖျက်ရန်။"</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"မျက်နှာပြင်ကို လော့ခ်ဖွင့်သည့်အခါ စကားဝှက်မှားယွင်းစွာ ရိုက်သွင်းသည့်အကြိမ်ရေကို စောင့်ကြည့်ပြီး မှားယွင်းသည့်အကြိမ်ရေ အလွန်များလာပါက သင့် Android TV စက်ပစ္စည်းကို လော့ခ်ချခြင်း သို့မဟုတ် သင့် Android TV ရှိ အသုံးပြုသူဒေတာများအားလုံးကို ဖျက်ခြင်းတို့ ပြုလုပ်သွားပါမည်။"</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ဖန်သားပြင်လော့ခ်ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက် စကားဝှက် မမှန်မကန် ရိုက်ထည့်မှု များနေလျှင် သတင်းနှင့်ဖျော်ဖြေရေး စနစ်ကို လော့ခ်ချသည် (သို့) ၎င်း၏ ဒေတာအားလုံးကို ဖျက်သည်။"</string>
- <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"မျက်နှာပြင်ကို သော့ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက်၊ စကားဝှက် ရိုက်ထည့်မှု သိပ်များနေလျှင် ဖုန်းကို သော့ခတ်ရန် သို့မဟုတ် ဖုန်း ဒေတာ အားလုံးကို ဖျက်ရန်။"</string>
+ <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"မျက်နှာပြင်ကို လောခ်ဖွင့်ရန်အတွက် ရိုက်ထည့်သည့် မှားယွင်းသောစကားဝှက် အကြိမ်ရေကို စောင့်ကြည့်ပြီး မမှန်သောစကားဝှက် ရိုက်ထည့်မှု အလွန်များနေလျှင် ဖုန်းကိုလော့ခ်ချသည် (သို့) ဖုန်း ဒေတာအားလုံးကို ဖျက်သည်။"</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ဖန်မျက်နှာပြင်အား သော့ဖွင့်စဉ် လျှို့ဝှက်ကုဒ်အမှားများ ရိုက်သွင်းမှုအား စောင့်ကြည့်ရန်နှင့်၊ လျှို့ဝှက်ကုဒ်အမှားများ များစွာ ရိုက်သွင်းပါက တက်ဘလက်အား သော့ချခြင်း သို့မဟုတ် တက်ဘလက်၏ အချက်အလက်များအား ဖျက်ပစ်ခြင်းများ ပြုလုပ်မည်။"</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"မျက်နှာပြင်ကို လော့ခ်ဖွင့်သည့်အခါ စကားဝှက်မှားယွင်းစွာ ရိုက်သွင်းသည့်အကြိမ်ရေကို စောင့်ကြည့်ပြီး မှားယွင်းသည့်အကြိမ်ရေ အလွန်များလာပါက သင့် Android TV စက်ပစ္စည်းကို လော့ခ်ချခြင်း သို့မဟုတ် ဤအသုံးပြုသူဒေတာများအားလုံးကို ဖျက်ခြင်းတို့ ပြုလုပ်သွားပါမည်။"</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ဖန်သားပြင်လော့ခ်ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက် စကားဝှက် မမှန်မကန် ရိုက်ထည့်မှု များနေလျှင် သတင်းနှင့်ဖျော်ဖြေရေး စနစ်ကို လော့ခ်ချသည် (သို့) ဤပရိုဖိုင်၏ ဒေတာအားလုံးကို ဖျက်သည်။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 03d431ab..db88c64 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -804,7 +804,7 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Lar innehaveren oppdatere appen hen tidligere installerte, uten brukerhandling"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Angi passordregler"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrollerer tillatt lengde og tillatte tegn i passord og PIN-koder for opplåsing av skjermen."</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"Overvåk forsøk på å låse opp skjermen"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"Overvåking av forsøk på å låse opp skjermen"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Overvåk antall feil passordforsøk ved opplåsing av skjerm, og lås nettbrettet eller slett alle data fra nettbrettet ved for mange feil passordforsøk."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Følg med på hvor mange ganger feil passord skrives inn når skjermen skal låses opp, og lås Android TV-enheten eller tøm alle dataene når feil passord skrives inn for mange ganger."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Overvåk antall feil passord som er skrevet inn ved opplåsing av skjermen, og lås infotainment-systemet eller tøm alle dataene i infotainment-systemet hvis feil passord skrives inn for mange ganger."</string>
@@ -1286,13 +1286,13 @@
<string name="volume_call" msgid="7625321655265747433">"Samtalevolum"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"Bluetooth-samtalevolum"</string>
<string name="volume_alarm" msgid="4486241060751798448">"Alarmvolum"</string>
- <string name="volume_notification" msgid="6864412249031660057">"Varslingsvolum"</string>
+ <string name="volume_notification" msgid="6864412249031660057">"Varselvolum"</string>
<string name="volume_unknown" msgid="4041914008166576293">"Volum"</string>
<string name="volume_icon_description_bluetooth" msgid="7540388479345558400">"Bluetooth-volum"</string>
<string name="volume_icon_description_ringer" msgid="2187800636867423459">"Ringetonevolum"</string>
<string name="volume_icon_description_incall" msgid="4491255105381227919">"Samtalevolum"</string>
<string name="volume_icon_description_media" msgid="4997633254078171233">"Medievolum"</string>
- <string name="volume_icon_description_notification" msgid="579091344110747279">"Varslingsvolum"</string>
+ <string name="volume_icon_description_notification" msgid="579091344110747279">"Varselvolum"</string>
<string name="ringtone_default" msgid="9118299121288174597">"Standard ringetone"</string>
<string name="ringtone_default_with_actual" msgid="2709686194556159773">"Standard (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="397111123930141876">"Ingen"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 2597441..cd1669d 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -329,7 +329,7 @@
<string name="permgrouplab_sensors" msgid="9134046949784064495">"Lichaamssensoren"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"toegang krijgen tot sensorgegevens over je vitale functies"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Meldingen"</string>
- <string name="permgroupdesc_notifications" msgid="4608679556801506580">"meldingen laten zien"</string>
+ <string name="permgroupdesc_notifications" msgid="4608679556801506580">"meldingen tonen"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Content van vensters ophalen"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"De content inspecteren van een venster waarmee je interactie hebt."</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Verkennen via aanraking aanzetten"</string>
@@ -594,8 +594,8 @@
<string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Hiermee kan de app de toetsenblokkering en bijbehorende wachtwoordbeveiliging uitzetten. Zo kan de telefoon de toetsenblokkering uitzetten als je wordt gebeld en de toetsenblokkering weer aanzetten als het gesprek is beëindigd."</string>
<string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"complexiteit van schermvergrendeling opvragen"</string>
<string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Hiermee krijgt de app toestemming om het complexiteitsniveau van de schermvergrendeling te achterhalen (hoog, midden, laag of geen). Dat geeft een indicatie van het mogelijke lengtebereik en type van de schermvergrendeling. De app kan gebruikers ook voorstellen de schermvergrendeling naar een bepaald niveau te updaten, maar gebruikers kunnen dit altijd negeren en de app verlaten. De schermvergrendeling wordt niet opgeslagen als platte tekst, zodat de app het precieze wachtwoord niet weet."</string>
- <string name="permlab_postNotification" msgid="4875401198597803658">"meldingen laten zien"</string>
- <string name="permdesc_postNotification" msgid="5974977162462877075">"Hiermee kan de app meldingen laten zien"</string>
+ <string name="permlab_postNotification" msgid="4875401198597803658">"meldingen tonen"</string>
+ <string name="permdesc_postNotification" msgid="5974977162462877075">"Hiermee kan de app meldingen tonen"</string>
<string name="permlab_turnScreenOn" msgid="219344053664171492">"het scherm aanzetten"</string>
<string name="permdesc_turnScreenOn" msgid="4394606875897601559">"Hiermee kan de app het scherm aanzetten."</string>
<string name="permlab_useBiometric" msgid="6314741124749633786">"biometrische hardware gebruiken"</string>
@@ -2094,7 +2094,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Uitzetten"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Meer informatie"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"In Android 12 hebben verbeterde meldingen aanpasbare Android-meldingen vervangen. Deze functie laat voorgestelde acties en antwoorden zien en ordent je meldingen.\n\nVerbeterde meldingen hebben toegang tot meldingscontent, waaronder persoonlijke informatie zoals contactnamen en berichten. Deze functie kan ook meldingen sluiten of erop reageren, zoals telefoongesprekken aannemen, en Niet storen beheren."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"In Android 12 hebben verbeterde meldingen aanpasbare Android-meldingen vervangen. Deze functie toont voorgestelde acties en antwoorden en ordent je meldingen.\n\nVerbeterde meldingen hebben toegang tot meldingscontent, waaronder persoonlijke informatie zoals contactnamen en berichten. Deze functie kan ook meldingen sluiten of erop reageren, zoals telefoongesprekken aannemen, en Niet storen beheren."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Informatiemelding voor routinemodus"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"Batterijbesparing staat aan"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"Het batterijgebruik wordt beperkt om de batterijduur te verlengen"</string>
@@ -2295,7 +2295,7 @@
<string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Blokkeren van apparaatmicrofoon opheffen"</string>
<string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Blokkeren van apparaatcamera opheffen"</string>
<string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"Voor <b><xliff:g id="APP">%s</xliff:g></b> en alle andere apps en services"</string>
- <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"Blokkeren opheffen"</string>
+ <string name="sensor_privacy_start_use_dialog_turn_on_button" msgid="7089318886628390827">"Niet meer blokkeren"</string>
<string name="sensor_privacy_notification_channel_label" msgid="936036783155261349">"Sensorprivacy"</string>
<string name="splash_screen_view_icon_description" msgid="180638751260598187">"App-icoon"</string>
<string name="splash_screen_view_branding_description" msgid="7911129347402728216">"Merkafbeelding voor app"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 5102387..88d9d47 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -2124,7 +2124,7 @@
<string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ଏୟାରପ୍ଲେନ୍ ମୋଡରେ ବ୍ଲୁଟୁଥ୍ ଚାଲୁ ରହିବ"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"ଲୋଡ୍ ହେଉଛି"</string>
<string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + #ଟି ଫାଇଲ}other{{file_name} + #ଟି ଫାଇଲ}}"</string>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ଏହାକୁ ସେୟାର୍ କରିବା ପାଇଁ କୌଣସି ସୁପାରିଶ କରାଯାଇଥିବା ଲୋକ ନାହାଁନ୍ତି"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ଏହାକୁ ସେୟାର କରିବା ପାଇଁ କୌଣସି ସୁପାରିଶ କରାଯାଇଥିବା ଲୋକ ନାହାଁନ୍ତି"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"ଆପ୍ସ ତାଲିକା"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ଏହି ଆପ୍କୁ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ କିନ୍ତୁ ଏହି USB ଡିଭାଇସ୍ ଜରିଆରେ ଅଡିଓ କ୍ୟାପ୍ଚର୍ କରିପାରିବ।"</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ହୋମ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index ae152f5..3c1776e 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -2124,7 +2124,7 @@
<string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ ਵੇਲੇ ਬਲੂਟੁੱਥ ਹਾਲੇ ਵੀ ਚਾਲੂ ਹੋ ਜਾਵੇਗਾ"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # ਫ਼ਾਈਲ}one{{file_name} + # ਫ਼ਾਈਲ}other{{file_name} + # ਫ਼ਾਈਲਾਂ}}"</string>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ਸਾਂਝਾ ਕਰਨ ਲਈ ਕੋਈ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੇ ਲੋਕ ਨਹੀਂ"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ਸਾਂਝਾ ਕਰਨ ਲਈ ਕੋਈ ਸਿਫ਼ਾਰਸ਼ ਕੀਤਾ ਵਿਅਕਤੀ ਨਹੀਂ ਹੈ"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"ਐਪ ਸੂਚੀ"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ਇਸ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਪਰ ਇਹ USB ਡੀਵਾਈਸ ਰਾਹੀਂ ਆਡੀਓ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ਹੋਮ"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ffa3d4d..1d7b124 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1863,7 +1863,7 @@
<string name="select_day" msgid="2060371240117403147">"Выберите месяц и число"</string>
<string name="select_year" msgid="1868350712095595393">"Выберите год"</string>
<string name="deleted_key" msgid="9130083334943364001">"Цифра <xliff:g id="KEY">%1$s</xliff:g> удалена"</string>
- <string name="managed_profile_label_badge" msgid="6762559569999499495">"Рабочий <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (рабочий профиль)"</string>
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Задача 2: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Задача 3: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="clone_profile_label_badge" msgid="1871997694718793964">"Клонировать <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index acefd07..f537d68 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -806,7 +806,7 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Povolí vlastníkovi aktualizovať aplikáciu, ktorá bola nainštalovaná bez akcie používateľa"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Nastaviť pravidlá pre heslo"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Nastavte dĺžku hesiel na odomknutie obrazovky aj kódov PIN a v nich používané znaky."</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovanie pokusov o odomknutie obrazovky"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovať pokusy o odomknutie obrazovky"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Sledovať počet nesprávnych hesiel zadaných pri odomykaní obrazovky a zamknúť tablet alebo vymazať všetky údaje tabletu v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Sledovanie počtu nesprávnych hesiel zadaných pri odomykaní obrazovky a v prípade, že ich je zadaných príliš mnoho, uzamknutie zariadenia Android TV alebo vymazanie všetkých jeho údajov."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Sledujte počet nesprávnych hesiel zadaných pri odomykaní obrazovky a uzamknite palubný systém alebo vymažte všetky údaje v palubnom systéme v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c46b666..327de1f 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -810,7 +810,7 @@
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Nadzoruje število nepravilno vnesenih gesel pri odklepanju zaslona in zaklene tablični računalnik ali izbriše vse podatke v njem, če je vnesenih preveč nepravilnih gesel."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Nadzira število vnesenih nepravilnih gesel pri odklepanju zaslona in zaklene napravo Android TV ali izbriše vse podatke v napravi Android TV, če je vnesenih preveč nepravilnih gesel."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Spremljanje števila nepravilno vnesenih gesel pri odklepanju zaslona in zaklenitev informativno-razvedrilnega sistema ali izbris vseh podatkov v njem v primeru preveč vnosov nepravilnih gesel"</string>
- <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Spremljajte število vnesenih napačnih gesel, s katerimi želite odkleniti zaslon. Če je teh vnosov preveč, zaklenite telefon ali izbrišite vse podatke v njem."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Spremljanje števila vnosov napačnih gesel za odklepanje zaslona ter zaklenitev telefona ali izbris vseh podatkov v njem v primeru prevelikega števila vnosov napačnih gesel."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Nadzira število vnesenih nepravilnih gesel pri odklepanju zaslona in zaklene tablični računalnik ali izbriše vse podatke lastnika, če je vnesenih preveč nepravilnih gesel."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Nadzira število vnesenih nepravilnih gesel pri odklepanju zaslona in zaklene napravo Android TV ali izbriše vse podatke tega uporabnika, če je vnesenih preveč nepravilnih gesel."</string>
<string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Spremljanje števila nepravilno vnesenih gesel pri odklepanju zaslona in zaklenitev informativno-razvedrilnega sistema ali izbris vseh podatkov tega profila v primeru preveč vnosov nepravilnih gesel"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 0104c89..54983f3 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -981,7 +981,7 @@
<string name="lockscreen_missing_sim_instructions" msgid="5823469004536805423">"Shto një kartë SIM."</string>
<string name="lockscreen_missing_sim_instructions_long" msgid="4403843937236648032">"Karta SIM mungon ose është e palexueshme. Shto një kartë SIM."</string>
<string name="lockscreen_permanent_disabled_sim_message_short" msgid="1925200607820809677">"Kartë SIM e papërdorshme."</string>
- <string name="lockscreen_permanent_disabled_sim_instructions" msgid="6902979937802238429">"Karta jote SIM është çaktivizuar përgjithmonë.\n Kontakto me ofruesin e shërbimit me valë për një kartë tjetër SIM."</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="6902979937802238429">"Karta jote SIM është çaktivizuar përgjithmonë.\n Kontakto me ofruesin e shërbimit wireless për një tjetër kartë SIM."</string>
<string name="lockscreen_transport_prev_description" msgid="2879469521751181478">"Kënga e mëparshme"</string>
<string name="lockscreen_transport_next_description" msgid="2931509904881099919">"Kënga tjetër"</string>
<string name="lockscreen_transport_pause_description" msgid="6705284702135372494">"Pauzë"</string>
@@ -1196,7 +1196,7 @@
<string name="whichEditApplicationNamed" msgid="8096494987978521514">"Redakto me %1$s"</string>
<string name="whichEditApplicationLabel" msgid="1463288652070140285">"Redakto"</string>
<string name="whichSendApplication" msgid="4143847974460792029">"Ndaj"</string>
- <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Shpërndaj me %1$s"</string>
+ <string name="whichSendApplicationNamed" msgid="4470386782693183461">"Ndaj me %1$s"</string>
<string name="whichSendApplicationLabel" msgid="7467813004769188515">"Ndaj"</string>
<string name="whichSendToApplication" msgid="77101541959464018">"Dërgo me"</string>
<string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Dërgo me %1$s"</string>
@@ -1521,7 +1521,7 @@
<string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# përputhje}other{# nga {total}}}"</string>
<string name="action_mode_done" msgid="2536182504764803222">"U krye"</string>
<string name="progress_erasing" msgid="6891435992721028004">"Po fshin hapësirën ruajtëse të brendshme…"</string>
- <string name="share" msgid="4157615043345227321">"Shpërndaj"</string>
+ <string name="share" msgid="4157615043345227321">"Ndaj"</string>
<string name="find" msgid="5015737188624767706">"Gjej"</string>
<string name="websearch" msgid="5624340204512793290">"Kërkim në internet"</string>
<string name="find_next" msgid="5341217051549648153">"Gjej tjetrën"</string>
@@ -1566,8 +1566,8 @@
<string name="keyboardview_keycode_enter" msgid="168054869339091055">"Enter"</string>
<string name="activitychooserview_choose_application" msgid="3500574466367891463">"Zgjidh një aplikacion"</string>
<string name="activitychooserview_choose_application_error" msgid="6937782107559241734">"Nuk mundi ta hapte <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
- <string name="shareactionprovider_share_with" msgid="2753089758467748982">"Shpërndaj me"</string>
- <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"Shpërndaj me <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="shareactionprovider_share_with" msgid="2753089758467748982">"Ndaj me"</string>
+ <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"Ndaj me <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="content_description_sliding_handle" msgid="982510275422590757">"Dorezë me rrëshqitje. Preke dhe mbaje të shtypur."</string>
<string name="description_target_unlock_tablet" msgid="7431571180065859551">"Rrëshqit për të shkyçur."</string>
<string name="action_bar_home_description" msgid="1501655419158631974">"Orientohu për në shtëpi"</string>
@@ -1611,7 +1611,7 @@
<string name="sha1_fingerprint" msgid="2339915142825390774">"Gjurma e gishtit SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="3917045206812726099">"Shikoji të gjitha"</string>
<string name="activity_chooser_view_dialog_title_default" msgid="8880731437191978314">"Zgjidh aktivitetin"</string>
- <string name="share_action_provider_share_with" msgid="1904096863622941880">"Shpërndaj me"</string>
+ <string name="share_action_provider_share_with" msgid="1904096863622941880">"Ndaj me"</string>
<string name="sending" msgid="206925243621664438">"Po dërgon…"</string>
<string name="launchBrowserDefault" msgid="6328349989932924119">"Të hapet shfletuesi?"</string>
<string name="SetupCallDefault" msgid="5581740063237175247">"Dëshiron ta pranosh telefonatën?"</string>
@@ -1627,7 +1627,7 @@
<string name="default_audio_route_name_usb" msgid="895668743163316932">"USB"</string>
<string name="default_audio_route_category_name" msgid="5241740395748134483">"Sistemi"</string>
<string name="bluetooth_a2dp_audio_route_name" msgid="4214648773120426288">"Audioja e \"bluetooth-it\""</string>
- <string name="wireless_display_route_description" msgid="8297563323032966831">"Ekran pa tel"</string>
+ <string name="wireless_display_route_description" msgid="8297563323032966831">"Ekran wireless"</string>
<string name="media_route_button_content_description" msgid="2299223698196869956">"Transmeto"</string>
<string name="media_route_chooser_title" msgid="6646594924991269208">"Lidhu me pajisjen"</string>
<string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"Transmeto ekranin në pajisje"</string>
@@ -1885,9 +1885,9 @@
<string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Për 1 min.}other{Për # min.}}"</string>
<string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Për 1 orë}other{Për # orë}}"</string>
<string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Për 1 orë}other{Për # orë}}"</string>
- <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Deri në <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
- <string name="zen_mode_until" msgid="2250286190237669079">"Deri në <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
- <string name="zen_mode_alarm" msgid="7046911727540499275">"Deri në <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarmi tjetër)"</string>
+ <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Deri: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_until" msgid="2250286190237669079">"Deri: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="7046911727540499275">"Deri: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarmi tjetër)"</string>
<string name="zen_mode_forever" msgid="740585666364912448">"Derisa ta çaktivizosh"</string>
<string name="zen_mode_forever_dnd" msgid="3423201955704180067">"Deri sa të çaktivizosh gjendjen \"Mos shqetëso\""</string>
<string name="zen_mode_rule_name_combination" msgid="7174598364351313725">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
@@ -2157,9 +2157,9 @@
<string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Pamja personale"</string>
<string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Pamja e punës"</string>
<string name="resolver_cross_profile_blocked" msgid="3014597376026044840">"Bllokuar nga administratori yt i teknologjisë së informacionit"</string>
- <string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"Kjo përmbajtje nuk mund të shpërndahet me aplikacione pune"</string>
+ <string name="resolver_cant_share_with_work_apps_explanation" msgid="9071442683080586643">"Kjo përmbajtje nuk mund të ndahet me aplikacione pune"</string>
<string name="resolver_cant_access_work_apps_explanation" msgid="1129960195389373279">"Kjo përmbajtje nuk mund të hapet me aplikacione pune"</string>
- <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"Kjo përmbajtje nuk mund të shpërndahet me aplikacione personale"</string>
+ <string name="resolver_cant_share_with_personal_apps_explanation" msgid="6349766201904601544">"Kjo përmbajtje nuk mund të ndahet me aplikacione personale"</string>
<string name="resolver_cant_access_personal_apps_explanation" msgid="1679399548862724359">"Kjo përmbajtje nuk mund të hapet me aplikacione personale"</string>
<string name="resolver_turn_on_work_apps" msgid="1535946298236678122">"Aplikacionet e punës janë vendosur në pauzë"</string>
<string name="resolver_switch_on_work" msgid="4527096360772311894">"Hiq nga pauza"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 91da16c..da5c127 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -805,7 +805,7 @@
<string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Дозвољава власнику да ажурира апликацију коју је претходно инсталирала без радњи корисника"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Подешавање правила за лозинку"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролише дужину и знакове дозвољене у лозинкама и PIN-овима за закључавање екрана."</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"Надгледајте покушаје откључавања екрана"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"Надзор покушаја откључавања екрана"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Прати број нетачно унетих лозинки приликом откључавања екрана и закључава таблет или брише податке са таблета ако је нетачна лозинка унета превише пута."</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Надгледа број нетачних лозинки унетих при откључавању екрана и закључава Android TV уређај или брише све податке са Android TV уређаја ако се унесе превише нетачних лозинки."</string>
<string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Прати број нетачно унетих лозинки при откључавању екрана и закључава систем за инфо-забаву или брише све податке са система за инфо-забаву ако је нетачна лозинка унета превише пута."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 37cbfc9..6e999bd 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -322,7 +322,7 @@
<string name="permgroupdesc_camera" msgid="7585150538459320326">"చిత్రాలను తీయడానికి మరియు వీడియోను రికార్డ్ చేయడానికి"</string>
<string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"సమీపంలోని పరికరాలు"</string>
<string name="permgroupdesc_nearby_devices" msgid="3213561597116913508">"సమీప పరికరాలను కనుగొనండి అలాగే కనెక్ట్ చేయండి"</string>
- <string name="permgrouplab_calllog" msgid="7926834372073550288">"కాల్ లాగ్లు"</string>
+ <string name="permgrouplab_calllog" msgid="7926834372073550288">"కాల్ లాగ్స్"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ఫోన్ కాల్ లాగ్ని చదవండి మరియు రాయండి"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ఫోన్"</string>
<string name="permgroupdesc_phone" msgid="270048070781478204">"ఫోన్ కాల్స్ చేయడం మరియు నిర్వహించడం"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 5f62542..1136270 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -817,7 +817,7 @@
<string name="policydesc_resetPassword" msgid="4626419138439341851">"Ekran kilidini değiştirir."</string>
<string name="policylab_forceLock" msgid="7360335502968476434">"Ekranı kilitleme"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Ekranın nasıl ve ne zaman kilitleneceğini denetler."</string>
- <string name="policylab_wipeData" msgid="1359485247727537311">"Tüm verileri silme"</string>
+ <string name="policylab_wipeData" msgid="1359485247727537311">"Tüm verileri sil"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek tabletteki verileri uyarıda bulunmadan siler."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek Android TV cihazınızdaki verileri uyarıda bulunmadan siler."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek bilgi-eğlence sistemindeki veriler uyarıda bulunmadan silinir."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index c1510b9..dc1499f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -819,7 +819,7 @@
<string name="policydesc_resetPassword" msgid="4626419138439341851">"Змінити спосіб розблокування екрана."</string>
<string name="policylab_forceLock" msgid="7360335502968476434">"Блокувати екран"</string>
<string name="policydesc_forceLock" msgid="1008844760853899693">"Контролювати, як і коли блокується екран."</string>
- <string name="policylab_wipeData" msgid="1359485247727537311">"Видалити всі дані"</string>
+ <string name="policylab_wipeData" msgid="1359485247727537311">"Видаляти всі дані"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Стирати дані планшетного ПК без попередження, відновлюючи заводські налаштування."</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Видаляйте дані пристрою Android TV без попередження шляхом відновлення заводських налаштувань."</string>
<string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Видаляйте всі дані інформаційно-розважальної системи без попередження, відновлюючи заводські налаштування."</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 72e7459..8cec8f8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -925,6 +925,9 @@
without impacting power, performance, and app compatibility (e.g. protected content). -->
<bool name="config_reduceBrightColorsAvailable">@bool/config_setColorTransformAccelerated</bool>
+ <!-- Whether to show Fold lock behavior setting feature in Settings App -->
+ <bool name="config_fold_lock_behavior">false</bool>
+
<string-array name="config_reduceBrightColorsCoefficientsNonlinear">
<!-- a-coefficient --> <item>-0.4429953456</item>
<!-- b-coefficient --> <item>-0.2434077725</item>
@@ -5345,6 +5348,10 @@
to enroll the other eligible biometric. -->
<fraction name="config_biometricNotificationFrrThreshold">25%</fraction>
+ <!-- Whether to enable the biometric notification for dual-modality device that enrolled a
+ single biometric and experiences high FRR. -->
+ <bool name="config_biometricFrrNotificationEnabled">false</bool>
+
<!-- The component name for the default profile supervisor, which can be set as a profile owner
even after user setup is complete. The defined component should be used for supervision purposes
only. The component must be part of a system app. -->
@@ -5377,6 +5384,13 @@
of known compatibility issues. -->
<string-array name="config_highRefreshRateBlacklist"></string-array>
+ <!-- The list of packages to automatically opt in to refresh rate suppressing by small area
+ detection. Format of this array should be packageName:threshold and threshold value should
+ be between 0 to 1-->
+ <string-array name="config_smallAreaDetectionAllowlist" translatable="false">
+ <!-- Add packages:threshold here -->
+ </string-array>
+
<!-- The list of packages to force slowJpegMode for Apps using Camera API1 -->
<string-array name="config_forceSlowJpegModeList" translatable="false">
<!-- Add packages here -->
@@ -5608,13 +5622,13 @@
<!-- Blur radius for the Option 3 in R.integer.config_letterboxBackgroundType. Values < 0 are
ignored and 0 is used. -->
- <dimen name="config_letterboxBackgroundWallpaperBlurRadius">24dp</dimen>
+ <dimen name="config_letterboxBackgroundWallpaperBlurRadius">38dp</dimen>
<!-- Alpha of a black translucent scrim showed over wallpaper letterbox background when
the Option 3 is selected for R.integer.config_letterboxBackgroundType.
Values < 0 or >= 1 are ignored and 0.0 (transparent) is used instead. -->
<item name="config_letterboxBackgroundWallaperDarkScrimAlpha" format="float" type="dimen">
- 0.75
+ 0.54
</item>
<!-- Corners appearance of the letterbox background.
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 79964b3..d238a130 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1500,12 +1500,8 @@
<item name="fontFamily">google-sans-text-medium</item>
<item name="textStyle">normal</item>
<item name="textAllCaps">false</item>
- <item name="layout_marginTop">6dp</item>
- <item name="layout_marginBottom">6dp</item>
- <item name="paddingStart">16dp</item>
- <item name="paddingEnd">16dp</item>
- <item name="paddingTop">8dp</item>
- <item name="paddingBottom">8dp</item>
+ <item name="paddingStart">24dp</item>
+ <item name="paddingEnd">24dp</item>
</style>
<!-- @hide Tonal button for Autofill half screen dialog -->
<style name="AutofillHalfSheetTonalButton" parent="AutofillHalfSheetButton">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7eec74a..be43a4f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -343,6 +343,7 @@
<java-symbol type="string" name="config_defaultHealthConnectApp" />
<java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
<java-symbol type="bool" name="config_enableScreenshotChord" />
+ <java-symbol type="bool" name="config_fold_lock_behavior" />
<java-symbol type="bool" name="config_enableWifiDisplay" />
<java-symbol type="bool" name="config_allowAnimationsInLowPowerMode" />
<java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
@@ -2583,6 +2584,7 @@
<!-- Biometric FRR config -->
<java-symbol type="fraction" name="config_biometricNotificationFrrThreshold" />
+ <java-symbol type="bool" name="config_biometricFrrNotificationEnabled" />
<!-- Biometric FRR notification messages -->
<java-symbol type="string" name="device_unlock_notification_name" />
@@ -4239,6 +4241,8 @@
<java-symbol type="array" name="config_highRefreshRateBlacklist" />
<java-symbol type="array" name="config_forceSlowJpegModeList" />
+ <java-symbol type="array" name="config_smallAreaDetectionAllowlist" />
+
<java-symbol type="layout" name="chooser_dialog" />
<java-symbol type="layout" name="chooser_dialog_item" />
<java-symbol type="drawable" name="chooser_dialog_background" />
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
index 2ef923d..84a6c45 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
@@ -251,6 +251,20 @@
}
@Test
+ public void identifierToHalProgramIdentifier_withDeprecateDabId() {
+ long value = 0x98765ABCDL;
+ ProgramSelector.Identifier dabId = new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT, value);
+ ProgramIdentifier halDabIdExpected = AidlTestUtils.makeHalIdentifier(
+ IdentifierType.DAB_SID_EXT, 0x987650000ABCDL);
+
+ ProgramIdentifier halDabId = ConversionUtils.identifierToHalProgramIdentifier(dabId);
+
+ expect.withMessage("Converted 28-bit DAB identifier for HAL").that(halDabId)
+ .isEqualTo(halDabIdExpected);
+ }
+
+ @Test
public void identifierFromHalProgramIdentifier_withDabId() {
ProgramSelector.Identifier dabId =
ConversionUtils.identifierFromHalProgramIdentifier(TEST_HAL_DAB_SID_EXT_ID);
diff --git a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
index c46118d..f39bddd 100644
--- a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
+++ b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
@@ -88,8 +88,8 @@
}
private HandwritingInitiator mHandwritingInitiator;
- private View mTestView1;
- private View mTestView2;
+ private EditText mTestView1;
+ private EditText mTestView2;
private Context mContext;
@Before
@@ -123,6 +123,9 @@
@Test
public void onTouchEvent_startHandwriting_when_stylusMoveOnce_withinHWArea() {
+ mTestView1.setText("hello");
+ when(mTestView1.getOffsetForPosition(anyFloat(), anyFloat())).thenReturn(4);
+
mHandwritingInitiator.onInputConnectionCreated(mTestView1);
final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
final int y1 = (sHwArea1.top + sHwArea1.bottom) / 2;
@@ -141,6 +144,9 @@
// After IMM.startHandwriting is triggered, onTouchEvent should return true for ACTION_MOVE
// events so that the events are not dispatched to the view tree.
assertThat(onTouchEventResult2).isTrue();
+ // Since the stylus down point was inside the TextView's bounds, the handwriting initiator
+ // does not need to set the cursor position.
+ verify(mTestView1, never()).setSelection(anyInt());
}
@Test
@@ -185,6 +191,9 @@
@Test
public void onTouchEvent_startHandwriting_when_stylusMove_withinExtendedHWArea() {
+ mTestView1.setText("hello");
+ when(mTestView1.getOffsetForPosition(anyFloat(), anyFloat())).thenReturn(4);
+
mHandwritingInitiator.onInputConnectionCreated(mTestView1);
final int x1 = sHwArea1.left - HW_BOUNDS_OFFSETS_LEFT_PX / 2;
final int y1 = sHwArea1.top - HW_BOUNDS_OFFSETS_TOP_PX / 2;
@@ -199,6 +208,9 @@
// Stylus movement within extended HandwritingArea should trigger IMM.startHandwriting once.
verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView1);
+ // Since the stylus down point was outside the TextView's bounds, the handwriting initiator
+ // sets the cursor position.
+ verify(mTestView1).setSelection(4);
}
@Test
@@ -221,6 +233,8 @@
@Test
public void onTouchEvent_startHandwriting_inputConnectionBuilt_stylusMoveInExtendedHWArea() {
+ mTestView1.setText("hello");
+ when(mTestView1.getOffsetForPosition(anyFloat(), anyFloat())).thenReturn(4);
// The stylus down point is between mTestView1 and mTestView2, but it is within the
// extended handwriting area of both views. It is closer to mTestView1.
final int x1 = sHwArea1.right + HW_BOUNDS_OFFSETS_RIGHT_PX / 2;
@@ -241,6 +255,9 @@
// the stylus down point is closest to this view.
mHandwritingInitiator.onInputConnectionCreated(mTestView1);
verify(mHandwritingInitiator).startHandwriting(mTestView1);
+ // Since the stylus down point was outside the TextView's bounds, the handwriting initiator
+ // sets the cursor position.
+ verify(mTestView1).setSelection(4);
}
@Test
diff --git a/core/tests/coretests/src/android/view/stylus/HandwritingTestUtil.java b/core/tests/coretests/src/android/view/stylus/HandwritingTestUtil.java
index b4c72ca..3b2ab4c 100644
--- a/core/tests/coretests/src/android/view/stylus/HandwritingTestUtil.java
+++ b/core/tests/coretests/src/android/view/stylus/HandwritingTestUtil.java
@@ -16,6 +16,9 @@
package android.view.stylus;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -26,22 +29,23 @@
import android.graphics.Region;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.EditText;
import androidx.test.platform.app.InstrumentationRegistry;
public class HandwritingTestUtil {
- public static View createView(Rect handwritingArea) {
+ public static EditText createView(Rect handwritingArea) {
return createView(handwritingArea, true /* autoHandwritingEnabled */,
true /* isStylusHandwritingAvailable */);
}
- public static View createView(Rect handwritingArea, boolean autoHandwritingEnabled,
+ public static EditText createView(Rect handwritingArea, boolean autoHandwritingEnabled,
boolean isStylusHandwritingAvailable) {
return createView(handwritingArea, autoHandwritingEnabled, isStylusHandwritingAvailable,
0, 0, 0, 0);
}
- public static View createView(Rect handwritingArea, boolean autoHandwritingEnabled,
+ public static EditText createView(Rect handwritingArea, boolean autoHandwritingEnabled,
boolean isStylusHandwritingAvailable,
float handwritingBoundsOffsetLeft, float handwritingBoundsOffsetTop,
float handwritingBoundsOffsetRight, float handwritingBoundsOffsetBottom) {
@@ -68,7 +72,7 @@
}
};
- View view = spy(new View(context));
+ EditText view = spy(new EditText(context));
when(view.isAttachedToWindow()).thenReturn(true);
when(view.isAggregatedVisible()).thenReturn(true);
when(view.isStylusHandwritingAvailable()).thenReturn(isStylusHandwritingAvailable);
@@ -77,6 +81,13 @@
when(view.getHandwritingBoundsOffsetTop()).thenReturn(handwritingBoundsOffsetTop);
when(view.getHandwritingBoundsOffsetRight()).thenReturn(handwritingBoundsOffsetRight);
when(view.getHandwritingBoundsOffsetBottom()).thenReturn(handwritingBoundsOffsetBottom);
+ doAnswer(invocation -> {
+ int[] outLocation = invocation.getArgument(0);
+ outLocation[0] = handwritingArea.left;
+ outLocation[1] = handwritingArea.top;
+ return null;
+ }).when(view).getLocationInWindow(any());
+ when(view.getOffsetForPosition(anyFloat(), anyFloat())).thenReturn(0);
view.setAutoHandwritingEnabled(autoHandwritingEnabled);
parent.addView(view);
return view;
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt b/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt
index 2eeaf53..1c9f04a 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt
@@ -19,8 +19,12 @@
import android.content.ComponentName
import android.content.Context
import android.content.Intent
+import android.content.pm.ActivityInfo
+import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
+import android.content.pm.ShortcutInfo
+import android.graphics.drawable.Icon
import android.os.Bundle
import android.os.UserHandle
import android.service.chooser.ChooserTarget
@@ -32,12 +36,15 @@
import androidx.test.platform.app.InstrumentationRegistry
import com.android.internal.R
import com.android.internal.app.ChooserListAdapter.LoadDirectShareIconTask
+import com.android.internal.app.chooser.DisplayResolveInfo
import com.android.internal.app.chooser.SelectableTargetInfo
import com.android.internal.app.chooser.SelectableTargetInfo.SelectableTargetInfoCommunicator
import com.android.internal.app.chooser.TargetInfo
import com.android.server.testutils.any
import com.android.server.testutils.mock
import com.android.server.testutils.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.anyInt
@@ -46,22 +53,25 @@
@RunWith(AndroidJUnit4::class)
class ChooserListAdapterTest {
- private val packageManager = mock<PackageManager> {
- whenever(resolveActivity(any(), anyInt())).thenReturn(mock())
- }
+ private val packageManager =
+ mock<PackageManager> { whenever(resolveActivity(any(), anyInt())).thenReturn(mock()) }
private val context = InstrumentationRegistry.getInstrumentation().getContext()
private val resolverListController = mock<ResolverListController>()
- private val chooserListCommunicator = mock<ChooserListAdapter.ChooserListCommunicator> {
- whenever(maxRankedTargets).thenReturn(0)
- }
- private val selectableTargetInfoCommunicator =
- mock<SelectableTargetInfoCommunicator> {
- whenever(targetIntent).thenReturn(mock())
+ private val chooserListCommunicator =
+ mock<ChooserListAdapter.ChooserListCommunicator> {
+ whenever(maxRankedTargets).thenReturn(0)
}
+ private val selectableTargetInfoCommunicator =
+ mock<SelectableTargetInfoCommunicator> { whenever(targetIntent).thenReturn(mock()) }
private val chooserActivityLogger = mock<ChooserActivityLogger>()
+ @Before
+ fun setUp() {
+ whenever(resolverListController.userHandle).thenReturn(UserHandle.CURRENT)
+ }
+
private fun createChooserListAdapter(
- taskProvider: (SelectableTargetInfo?) -> LoadDirectShareIconTask
+ taskProvider: (SelectableTargetInfo?) -> LoadDirectShareIconTask = createTaskProvider()
) =
ChooserListAdapterOverride(
context,
@@ -98,9 +108,8 @@
view.tag = viewHolderOne
val targetInfo = createSelectableTargetInfo()
val iconTaskOne = mock<LoadDirectShareIconTask>()
- val testTaskProvider = mock<() -> LoadDirectShareIconTask> {
- whenever(invoke()).thenReturn(iconTaskOne)
- }
+ val testTaskProvider =
+ mock<() -> LoadDirectShareIconTask> { whenever(invoke()).thenReturn(iconTaskOne) }
val testSubject = createChooserListAdapter { testTaskProvider.invoke() }
testSubject.testViewBind(view, targetInfo, 0)
@@ -114,6 +123,65 @@
verify(testTaskProvider, times(1)).invoke()
}
+ @Test
+ fun getServiceTargetCount_shouldNotShowServiceTargets_returnsZero() {
+ whenever(chooserListCommunicator.shouldShowServiceTargets()).thenReturn(false)
+ val adapter = createChooserListAdapter()
+ whenever(chooserListCommunicator.maxRankedTargets).thenReturn(10)
+ addServiceTargets(adapter, targetCount = 50)
+
+ assertThat(adapter.serviceTargetCount).isEqualTo(0)
+ }
+
+ private fun createTaskProvider(): (SelectableTargetInfo?) -> LoadDirectShareIconTask {
+ val iconTaskOne = mock<LoadDirectShareIconTask>()
+ val testTaskProvider =
+ mock<() -> LoadDirectShareIconTask> { whenever(invoke()).thenReturn(iconTaskOne) }
+ return { testTaskProvider.invoke() }
+ }
+
+ private fun addServiceTargets(adapter: ChooserListAdapter, targetCount: Int) {
+ val origTarget =
+ DisplayResolveInfo(
+ Intent(),
+ createResolveInfo(),
+ Intent(),
+ ResolverListAdapter.ResolveInfoPresentationGetter(context, 200, createResolveInfo())
+ )
+ val targets = mutableListOf<ChooserTarget>()
+ for (i in 1..targetCount) {
+ val score = 1f
+ val componentName = ComponentName("chooser.list.adapter", "Test$i")
+ val extras = Bundle()
+ val icon: Icon? = null
+ targets += ChooserTarget("Title $i", icon, score, componentName, extras)
+ }
+ val directShareToShortcutInfos = mapOf<ChooserTarget, ShortcutInfo>()
+ adapter.addServiceResults(
+ origTarget,
+ targets,
+ ChooserActivity.TARGET_TYPE_DEFAULT,
+ directShareToShortcutInfos
+ )
+ }
+
+ private fun createResolveInfo(): ResolveInfo {
+ val applicationInfo =
+ ApplicationInfo().apply {
+ packageName = "chooser.list.adapter"
+ name = "ChooserListAdapterTestApplication"
+ }
+ val activityInfo =
+ ActivityInfo().apply {
+ packageName = applicationInfo.packageName
+ name = "ChooserListAdapterTest"
+ }
+ activityInfo.applicationInfo = applicationInfo
+ val resolveInfo = ResolveInfo()
+ resolveInfo.activityInfo = activityInfo
+ return resolveInfo
+ }
+
private fun createSelectableTargetInfo(): SelectableTargetInfo =
SelectableTargetInfo(
context,
@@ -125,13 +193,7 @@
)
private fun createChooserTarget(): ChooserTarget =
- ChooserTarget(
- "Title",
- null,
- 1f,
- ComponentName("package", "package.Class"),
- Bundle()
- )
+ ChooserTarget("Title", null, 1f, ComponentName("package", "package.Class"), Bundle())
private fun createView(): View {
val view = FrameLayout(context)
@@ -164,23 +226,23 @@
chooserActivityLogger: ChooserActivityLogger?,
initialIntentsUserHandle: UserHandle?,
private val taskProvider: (SelectableTargetInfo?) -> LoadDirectShareIconTask
-) : ChooserListAdapter(
- context,
- payloadIntents,
- initialIntents,
- rList,
- filterLastUsed,
- resolverListController,
- chooserListCommunicator,
- selectableTargetInfoCommunicator,
- packageManager,
- chooserActivityLogger,
- initialIntentsUserHandle,
-) {
+) :
+ ChooserListAdapter(
+ context,
+ payloadIntents,
+ initialIntents,
+ rList,
+ filterLastUsed,
+ resolverListController,
+ chooserListCommunicator,
+ selectableTargetInfoCommunicator,
+ packageManager,
+ chooserActivityLogger,
+ initialIntentsUserHandle,
+ ) {
override fun createLoadDirectShareIconTask(
info: SelectableTargetInfo?
- ): LoadDirectShareIconTask =
- taskProvider.invoke(info)
+ ): LoadDirectShareIconTask = taskProvider.invoke(info)
fun testViewBind(view: View?, info: TargetInfo?, position: Int) {
onBindView(view, info, position)
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 71e9263..7d5c06c 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -253,12 +253,6 @@
"group": "WM_DEBUG_BOOT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "-1883484959": {
- "message": "Content Recording: Display %d state is now (%d), so update recording?",
- "level": "VERBOSE",
- "group": "WM_DEBUG_CONTENT_RECORDING",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"-1872288685": {
"message": "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b Callers=%s",
"level": "VERBOSE",
@@ -445,6 +439,12 @@
"group": "WM_DEBUG_TASKS",
"at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java"
},
+ "-1700778361": {
+ "message": "Content Recording: Going ahead with updating recording for display %d to new bounds %s and\/or orientation %d and\/or surface size %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/ContentRecorder.java"
+ },
"-1699018375": {
"message": "Adding activity %s to task %s callers: %s",
"level": "INFO",
@@ -643,12 +643,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
- "-1480264178": {
- "message": "Content Recording: Unable to update recording for display %d to new bounds %s and\/or orientation %d, since the surface is not available.",
- "level": "VERBOSE",
- "group": "WM_DEBUG_CONTENT_RECORDING",
- "at": "com\/android\/server\/wm\/ContentRecorder.java"
- },
"-1478175541": {
"message": "No longer animating wallpaper targets!",
"level": "VERBOSE",
@@ -1015,6 +1009,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java"
},
+ "-1152771606": {
+ "message": "Content Recording: Display %d was already recording, but pause capture since the task is in PIP",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/ContentRecorder.java"
+ },
"-1145384901": {
"message": "shouldWaitAnimatingExit: isTransition: %s",
"level": "DEBUG",
@@ -1837,12 +1837,6 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/Task.java"
},
- "-452750194": {
- "message": "Content Recording: Going ahead with updating recording for display %d to new bounds %s and\/or orientation %d.",
- "level": "VERBOSE",
- "group": "WM_DEBUG_CONTENT_RECORDING",
- "at": "com\/android\/server\/wm\/ContentRecorder.java"
- },
"-451552570": {
"message": "Current focused window being animated by recents. Overriding back callback to recents controller callback.",
"level": "DEBUG",
@@ -2323,6 +2317,12 @@
"group": "WM_DEBUG_SYNC_ENGINE",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "1877956": {
+ "message": "Content Recording: Display %d should start recording, but don't yet since the task is in PIP",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/ContentRecorder.java"
+ },
"3593205": {
"message": "commitVisibility: %s: visible=%b mVisibleRequested=%b",
"level": "VERBOSE",
@@ -2353,6 +2353,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
},
+ "34106798": {
+ "message": "Content Recording: Display %d state was (%d), is now (%d), so update recording?",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"34682671": {
"message": "Not moving display (displayId=%d) to top. Top focused displayId=%d. Reason: FLAG_STEAL_TOP_FOCUS_DISABLED",
"level": "INFO",
@@ -4075,6 +4081,12 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1687944543": {
+ "message": "Content Recording: Unable to update recording for display %d to new bounds %s and\/or orientation %d and\/or surface size %s, since the surface is not available.",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/ContentRecorder.java"
+ },
"1699269281": {
"message": "Don't organize or trigger events for untrusted displayId=%d",
"level": "WARN",
@@ -4297,6 +4309,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "1936800105": {
+ "message": "Content Recording: Apply transformations of shift %d x %d, scale %f, crop (aka recorded content size) %d x %d for display %d; display has size %d x %d; surface has size %d x %d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/ContentRecorder.java"
+ },
"1945495497": {
"message": "Focused window didn't have a valid surface drawn.",
"level": "DEBUG",
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 0112e32..15d14e8 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -213,9 +213,6 @@
if (mRearDisplayStateRequest != null || isRearDisplayActive()) {
mRearDisplayStateRequest = null;
mDeviceStateManager.cancelStateRequest();
- } else {
- throw new IllegalStateException(
- "Unable to cancel a rear display session as there is no active session");
}
}
}
@@ -432,10 +429,6 @@
synchronized (mLock) {
if (mRearDisplayPresentationController != null) {
mDeviceStateManager.cancelStateRequest();
- } else {
- throw new IllegalStateException(
- "Unable to cancel a rear display presentation session as there is no "
- + "active session");
}
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 896fe61..d894487 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -651,7 +651,8 @@
if (minDimensionsPair == null) {
return splitAttributes;
}
- final FoldingFeature foldingFeature = getFoldingFeature(taskProperties);
+ final FoldingFeature foldingFeature = getFoldingFeatureForHingeType(
+ taskProperties, splitAttributes);
final Configuration taskConfiguration = taskProperties.getConfiguration();
final Rect primaryBounds = getPrimaryBounds(taskConfiguration, splitAttributes,
foldingFeature);
@@ -726,7 +727,8 @@
Rect getRelBoundsForPosition(@Position int position, @NonNull TaskProperties taskProperties,
@NonNull SplitAttributes splitAttributes) {
final Configuration taskConfiguration = taskProperties.getConfiguration();
- final FoldingFeature foldingFeature = getFoldingFeature(taskProperties);
+ final FoldingFeature foldingFeature = getFoldingFeatureForHingeType(
+ taskProperties, splitAttributes);
if (!shouldShowSplit(splitAttributes)) {
return new Rect();
}
@@ -933,6 +935,17 @@
}
@Nullable
+ private FoldingFeature getFoldingFeatureForHingeType(
+ @NonNull TaskProperties taskProperties,
+ @NonNull SplitAttributes splitAttributes) {
+ SplitType splitType = splitAttributes.getSplitType();
+ if (!(splitType instanceof HingeSplitType)) {
+ return null;
+ }
+ return getFoldingFeature(taskProperties);
+ }
+
+ @Nullable
@VisibleForTesting
FoldingFeature getFoldingFeature(@NonNull TaskProperties taskProperties) {
final int displayId = taskProperties.getDisplayId();
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index 2eacaaf..6db2ae4 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -17,7 +17,6 @@
package androidx.window.extensions.layout;
import static android.view.Display.DEFAULT_DISPLAY;
-
import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT;
import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED;
import static androidx.window.util.ExtensionHelper.isZero;
@@ -327,13 +326,17 @@
return features;
}
+ // We will transform the feature bounds to the Activity window, so using the rotation
+ // from the same source (WindowConfiguration) to make sure they are synchronized.
+ final int rotation = windowConfiguration.getDisplayRotation();
+
for (CommonFoldingFeature baseFeature : storedFeatures) {
Integer state = convertToExtensionState(baseFeature.getState());
if (state == null) {
continue;
}
Rect featureRect = baseFeature.getRect();
- rotateRectToDisplayRotation(displayId, featureRect);
+ rotateRectToDisplayRotation(displayId, rotation, featureRect);
transformToWindowSpaceRect(windowConfiguration, featureRect);
if (isZero(featureRect)) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
index 5bfb0ebd..a836e05 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
@@ -17,7 +17,6 @@
package androidx.window.sidecar;
import static android.view.Display.DEFAULT_DISPLAY;
-
import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation;
import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect;
@@ -120,10 +119,12 @@
}
List<SidecarDisplayFeature> features = new ArrayList<>();
+ final int rotation = activity.getResources().getConfiguration().windowConfiguration
+ .getDisplayRotation();
for (CommonFoldingFeature baseFeature : mStoredFeatures) {
SidecarDisplayFeature feature = new SidecarDisplayFeature();
Rect featureRect = baseFeature.getRect();
- rotateRectToDisplayRotation(displayId, featureRect);
+ rotateRectToDisplayRotation(displayId, rotation, featureRect);
transformToWindowSpaceRect(activity, featureRect);
feature.setRect(featureRect);
feature.setType(baseFeature.getType());
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
index 9e2611f..a08db79 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
@@ -16,21 +16,22 @@
package androidx.window.util;
-import static android.view.Surface.ROTATION_0;
-import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
+import android.annotation.SuppressLint;
import android.app.WindowConfiguration;
import android.content.Context;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
+import android.util.RotationUtils;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.UiContext;
+import androidx.annotation.VisibleForTesting;
/**
* Util class for both Sidecar and Extensions.
@@ -44,47 +45,39 @@
/**
* Rotates the input rectangle specified in default display orientation to the current display
* rotation.
+ *
+ * @param displayId the display id.
+ * @param rotation the target rotation relative to the default display orientation.
+ * @param inOutRect the input/output Rect as specified in the default display orientation.
*/
- public static void rotateRectToDisplayRotation(int displayId, Rect inOutRect) {
- DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
- DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
- int rotation = displayInfo.rotation;
+ public static void rotateRectToDisplayRotation(
+ int displayId, @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
+ final DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
+ final DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
- boolean isSideRotation = rotation == ROTATION_90 || rotation == ROTATION_270;
- int displayWidth = isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
- int displayHeight = isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
-
- inOutRect.intersect(0, 0, displayWidth, displayHeight);
-
- rotateBounds(inOutRect, displayWidth, displayHeight, rotation);
+ rotateRectToDisplayRotation(displayInfo, rotation, inOutRect);
}
- /**
- * Rotates the input rectangle within parent bounds for a given delta.
- */
- private static void rotateBounds(Rect inOutRect, int parentWidth, int parentHeight,
- @Surface.Rotation int delta) {
- int origLeft = inOutRect.left;
- switch (delta) {
- case ROTATION_0:
- return;
- case ROTATION_90:
- inOutRect.left = inOutRect.top;
- inOutRect.top = parentWidth - inOutRect.right;
- inOutRect.right = inOutRect.bottom;
- inOutRect.bottom = parentWidth - origLeft;
- return;
- case ROTATION_180:
- inOutRect.left = parentWidth - inOutRect.right;
- inOutRect.right = parentWidth - origLeft;
- return;
- case ROTATION_270:
- inOutRect.left = parentHeight - inOutRect.bottom;
- inOutRect.bottom = inOutRect.right;
- inOutRect.right = parentHeight - inOutRect.top;
- inOutRect.top = origLeft;
- return;
- }
+ // We suppress the Lint error CheckResult for Rect#intersect because in case the displayInfo and
+ // folding features are out of sync, e.g. when a foldable devices is unfolding, it is acceptable
+ // to provide the original folding feature Rect even if they don't intersect.
+ @SuppressLint("RectIntersectReturnValueIgnored")
+ @VisibleForTesting
+ static void rotateRectToDisplayRotation(@NonNull DisplayInfo displayInfo,
+ @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
+ // The inOutRect is specified in the default display orientation, so here we need to get
+ // the display width and height in the default orientation to perform the intersection and
+ // rotation.
+ final boolean isSideRotation =
+ displayInfo.rotation == ROTATION_90 || displayInfo.rotation == ROTATION_270;
+ final int baseDisplayWidth =
+ isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
+ final int baseDisplayHeight =
+ isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
+
+ inOutRect.intersect(0, 0, baseDisplayWidth, baseDisplayHeight);
+
+ RotationUtils.rotateBounds(inOutRect, baseDisplayWidth, baseDisplayHeight, rotation);
}
/** Transforms rectangle from absolute coordinate space to the window coordinate space. */
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
index d189ae2..a0590dc 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
@@ -29,7 +29,7 @@
import org.junit.runner.RunWith;
/**
- * Test class for {@link WindowExtensionsTest}.
+ * Test class for {@link WindowExtensions}.
*
* Build/Install/Run:
* atest WMJetpackUnitTests:WindowExtensionsTest
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java
new file mode 100644
index 0000000..3278cdf
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.util;
+
+import static org.junit.Assert.assertEquals;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.DisplayInfo;
+import android.view.Surface;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link ExtensionHelper}.
+ *
+ * Build/Install/Run:
+ * atest WMJetpackUnitTests:ExtensionHelperTest
+ */
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ExtensionHelperTest {
+
+ private static final int MOCK_DISPLAY_HEIGHT = 1000;
+ private static final int MOCK_DISPLAY_WIDTH = 2000;
+ private static final int MOCK_FEATURE_LEFT = 100;
+ private static final int MOCK_FEATURE_RIGHT = 200;
+
+ private static final int[] ROTATIONS = {
+ Surface.ROTATION_0,
+ Surface.ROTATION_90,
+ Surface.ROTATION_180,
+ Surface.ROTATION_270
+ };
+
+ private static final DisplayInfo[] MOCK_DISPLAY_INFOS = {
+ getMockDisplayInfo(Surface.ROTATION_0),
+ getMockDisplayInfo(Surface.ROTATION_90),
+ getMockDisplayInfo(Surface.ROTATION_180),
+ getMockDisplayInfo(Surface.ROTATION_270),
+ };
+
+ @Test
+ public void testRotateRectToDisplayRotation() {
+ for (int rotation : ROTATIONS) {
+ final Rect expectedResult = getExpectedFeatureRectAfterRotation(rotation);
+ // The method should return correctly rotated Rect even if the requested rotation value
+ // differs from the rotation in DisplayInfo. This is because the WindowConfiguration is
+ // not always synced with DisplayInfo.
+ for (DisplayInfo displayInfo : MOCK_DISPLAY_INFOS) {
+ final Rect rect = getMockFeatureRect();
+ ExtensionHelper.rotateRectToDisplayRotation(displayInfo, rotation, rect);
+ assertEquals(
+ "Result Rect should equal to expected for rotation: " + rotation
+ + "; displayInfo: " + displayInfo,
+ expectedResult, rect);
+ }
+ }
+ }
+
+ @NonNull
+ private static DisplayInfo getMockDisplayInfo(@Surface.Rotation int rotation) {
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.rotation = rotation;
+ if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
+ displayInfo.logicalWidth = MOCK_DISPLAY_WIDTH;
+ displayInfo.logicalHeight = MOCK_DISPLAY_HEIGHT;
+ } else {
+ displayInfo.logicalWidth = MOCK_DISPLAY_HEIGHT;
+ displayInfo.logicalHeight = MOCK_DISPLAY_WIDTH;
+ }
+ return displayInfo;
+ }
+
+ @NonNull
+ private static Rect getMockFeatureRect() {
+ return new Rect(MOCK_FEATURE_LEFT, 0, MOCK_FEATURE_RIGHT, MOCK_DISPLAY_HEIGHT);
+ }
+
+ @NonNull
+ private static Rect getExpectedFeatureRectAfterRotation(@Surface.Rotation int rotation) {
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ return new Rect(
+ MOCK_FEATURE_LEFT, 0, MOCK_FEATURE_RIGHT, MOCK_DISPLAY_HEIGHT);
+ case Surface.ROTATION_90:
+ return new Rect(0, MOCK_DISPLAY_WIDTH - MOCK_FEATURE_RIGHT,
+ MOCK_DISPLAY_HEIGHT, MOCK_DISPLAY_WIDTH - MOCK_FEATURE_LEFT);
+ case Surface.ROTATION_180:
+ return new Rect(MOCK_DISPLAY_WIDTH - MOCK_FEATURE_RIGHT, 0,
+ MOCK_DISPLAY_WIDTH - MOCK_FEATURE_LEFT, MOCK_DISPLAY_HEIGHT);
+ case Surface.ROTATION_270:
+ return new Rect(0, MOCK_FEATURE_LEFT, MOCK_DISPLAY_HEIGHT,
+ MOCK_FEATURE_RIGHT);
+ default:
+ throw new IllegalArgumentException("Unknown rotation value: " + rotation);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index eef363b..85ae1c1 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Зразумела"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Няма нядаўніх усплывальных апавяшчэнняў"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Нядаўнія і адхіленыя ўсплывальныя апавяшчэнні будуць паказаны тут"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Кіруйце наладамі ўсплывальных апавяшчэнняў у любы час"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Каб кіраваць усплывальнымі апавяшчэннямі для праграм і размоў, націсніце тут"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Усплывальнае апавяшчэнне"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Кіраваць"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Усплывальнае апавяшчэнне адхілена."</string>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index 485a895..34fad3c 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -81,12 +81,9 @@
<string name="notification_bubble_title" msgid="6082910224488253378">"Burbulla"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Xestionar"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ignorouse a burbulla."</string>
- <!-- no translation found for restart_button_description (4564728020654658478) -->
- <skip />
- <!-- no translation found for user_aspect_ratio_settings_button_hint (734835849600713016) -->
- <skip />
- <!-- no translation found for user_aspect_ratio_settings_button_description (4315566801697411684) -->
- <skip />
+ <string name="restart_button_description" msgid="4564728020654658478">"Toca o botón para reiniciar esta aplicación e gozar dunha mellor visualización"</string>
+ <string name="user_aspect_ratio_settings_button_hint" msgid="734835849600713016">"Cambia a proporción desta aplicación en Configuración"</string>
+ <string name="user_aspect_ratio_settings_button_description" msgid="4315566801697411684">"Cambiar a proporción"</string>
<string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Tes problemas coa cámara?\nToca para reaxustala"</string>
<string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Non se solucionaron os problemas?\nToca para reverter o seu tratamento"</string>
<string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Non hai problemas coa cámara? Tocar para ignorar."</string>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index 54b1213..2d5d371 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Եղավ"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Ամպիկներ չկան"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Այստեղ կցուցադրվեն վերջերս օգտագործված և փակված ամպիկները, որոնք կկարողանաք հեշտությամբ վերաբացել"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Ամպիկների կարգավորումներ"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Հպեք այստեղ՝ ընտրելու, թե որ հավելվածների և զրույցների համար ամպիկներ ցուցադրել"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Պղպջակ"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Կառավարել"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ամպիկը փակվեց։"</string>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index 8918821..58601b7 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -90,7 +90,7 @@
<string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Visualizza più contenuti e fai di più"</string>
<string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Trascina in un\'altra app per usare lo schermo diviso"</string>
<string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tocca due volte fuori da un\'app per riposizionarla"</string>
- <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
+ <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ok"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Espandi per avere ulteriori informazioni."</string>
<string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Vuoi riavviare per migliorare la visualizzazione?"</string>
<string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Puoi riavviare l\'app affinché venga visualizzata meglio sullo schermo, ma potresti perdere i tuoi progressi o eventuali modifiche non salvate"</string>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 0777abc..0a0205d 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Đã hiểu"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Không có bong bóng trò chuyện nào gần đây"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Bong bóng trò chuyện đã đóng và bong bóng trò chuyện gần đây sẽ xuất hiện ở đây"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kiểm soát bong bóng bất cứ lúc nào"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"Nhấn vào đây để quản lý việc dùng bong bóng cho các ứng dụng và cuộc trò chuyện"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"Bong bóng"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"Quản lý"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Đã đóng bong bóng."</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index f272e91..f931883 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -76,10 +76,8 @@
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"我知道了"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"最近沒有任何對話框"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"最近的對話框和已關閉的對話框會顯示在這裡"</string>
- <!-- no translation found for bubble_bar_education_manage_title (6148404487810835924) -->
- <skip />
- <!-- no translation found for bubble_bar_education_manage_text (3199732148641842038) -->
- <skip />
+ <string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"你隨時可以控管對話框的各項設定"</string>
+ <string name="bubble_bar_education_manage_text" msgid="3199732148641842038">"輕觸這裡即可管理哪些應用程式和對話可顯示對話框"</string>
<string name="notification_bubble_title" msgid="6082910224488253378">"泡泡"</string>
<string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
<string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"已關閉泡泡。"</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 9aac694..0479576 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -103,7 +103,7 @@
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {}
/** Whether this task listener supports compat UI. */
default boolean supportCompatUI() {
- // All TaskListeners should support compat UI except PIP.
+ // All TaskListeners should support compat UI except PIP and StageCoordinator.
return true;
}
/** Attaches a child window surface to the task surface. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
index 9b80063..4640106 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
@@ -245,8 +245,8 @@
private boolean shouldShowBackdrop(@NonNull TransitionInfo info,
@NonNull TransitionInfo.Change change) {
- final Animation a = loadAttributeAnimation(info.getType(), info, change,
- WALLPAPER_TRANSITION_NONE, mTransitionAnimation, false);
+ final Animation a = loadAttributeAnimation(info, change, WALLPAPER_TRANSITION_NONE,
+ mTransitionAnimation, false);
return a != null && a.getShowBackdrop();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
index cbff464..77aefc8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
@@ -208,7 +208,7 @@
}
private boolean getHasUserAspectRatioSettingsButton(@NonNull TaskInfo taskInfo) {
- return taskInfo.topActivityEligibleForUserAspectRatioButton
+ return taskInfo.topActivityEligibleForUserAspectRatioButton
&& (taskInfo.topActivityBoundsLetterboxed
|| taskInfo.isUserFullscreenOverrideEnabled);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index a11d952..50ba897 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -219,6 +219,13 @@
private ArrayList<TaskState> mPausingTasks = null;
/**
+ * List of tasks were pausing but closed in a subsequent merged transition. If a
+ * closing task is reopened, the leash is not initially hidden since it is already
+ * visible.
+ */
+ private ArrayList<TaskState> mClosingTasks = null;
+
+ /**
* List of tasks that we are switching to. Upon finish, these will remain visible and
* on top.
*/
@@ -369,6 +376,7 @@
}
mFinishTransaction = null;
mPausingTasks = null;
+ mClosingTasks = null;
mOpeningTasks = null;
mInfo = null;
mTransition = null;
@@ -413,6 +421,7 @@
mFinishCB = finishCB;
mFinishTransaction = finishT;
mPausingTasks = new ArrayList<>();
+ mClosingTasks = new ArrayList<>();
mOpeningTasks = new ArrayList<>();
mLeashMap = new ArrayMap<>();
mKeyguardLocked = (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0;
@@ -659,7 +668,10 @@
final TransitionInfo.Change change = closingTasks.get(i);
final int pausingIdx = TaskState.indexOf(mPausingTasks, change);
if (pausingIdx >= 0) {
- mPausingTasks.remove(pausingIdx);
+ // We are closing the pausing task, but it is still visible and can be
+ // restart by another transition prior to this transition finishing
+ final TaskState closingTask = mPausingTasks.remove(pausingIdx);
+ mClosingTasks.add(closingTask);
didMergeThings = true;
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
" closing pausing taskId=%d", change.getTaskInfo().taskId);
@@ -695,7 +707,12 @@
for (int i = 0; i < openingTasks.size(); ++i) {
final TransitionInfo.Change change = openingTasks.get(i);
final boolean isLeaf = openingTaskIsLeafs.get(i) == 1;
- int pausingIdx = TaskState.indexOf(mPausingTasks, change);
+ final int closingIdx = TaskState.indexOf(mClosingTasks, change);
+ if (closingIdx >= 0) {
+ // Remove opening tasks from closing set
+ mClosingTasks.remove(closingIdx);
+ }
+ final int pausingIdx = TaskState.indexOf(mPausingTasks, change);
if (pausingIdx >= 0) {
// Something is showing/opening a previously-pausing app.
if (isLeaf) {
@@ -718,12 +735,23 @@
appearedTargets[nextTargetIdx++] = target;
// reparent into the original `mInfo` since that's where we are animating.
final int rootIdx = TransitionUtil.rootIndexFor(change, mInfo);
+ final boolean wasClosing = closingIdx >= 0;
t.reparent(target.leash, mInfo.getRoot(rootIdx).getLeash());
t.setLayer(target.leash, layer);
- // Hide the animation leash, let listener show it.
- t.hide(target.leash);
+ if (wasClosing) {
+ // App was previously visible and is closing
+ t.show(target.leash);
+ t.setAlpha(target.leash, 1f);
+ // Also override the task alpha as it was set earlier when dispatching
+ // the transition and setting up the leash to hide the
+ t.setAlpha(change.getLeash(), 1f);
+ } else {
+ // Hide the animation leash, let the listener show it
+ t.hide(target.leash);
+ }
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
- " opening new leaf taskId=%d", target.taskId);
+ " opening new leaf taskId=%d wasClosing=%b",
+ target.taskId, wasClosing);
mOpeningTasks.add(new TaskState(change, target.leash));
} else {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 842b1bf..94fa485 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -228,6 +228,15 @@
private final Toast mSplitUnsupportedToast;
private SplitRequest mSplitRequest;
+ /**
+ * Since StageCoordinator only coordinates MainStage and SideStage, it shouldn't support
+ * CompatUI layouts. CompatUI is handled separately by MainStage and SideStage.
+ */
+ @Override
+ public boolean supportCompatUI() {
+ return false;
+ }
+
class SplitRequest {
@SplitPosition
int mActivatePosition;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java
index 20c4d5a..e7e1e0a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java
@@ -35,13 +35,14 @@
void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, TaskSnapshot snapshot) {
final int taskId = startingWindowInfo.taskInfo.taskId;
// Remove any existing starting window for this task before adding.
- mStartingWindowRecordManager.removeWindow(taskId, true);
+ mStartingWindowRecordManager.removeWindow(taskId);
final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo,
startingWindowInfo.appToken, snapshot, mMainExecutor,
- () -> mStartingWindowRecordManager.removeWindow(taskId, true));
+ () -> mStartingWindowRecordManager.removeWindow(taskId));
if (surface != null) {
final SnapshotWindowRecord tView = new SnapshotWindowRecord(surface,
- startingWindowInfo.taskInfo.topActivityType, mMainExecutor);
+ startingWindowInfo.taskInfo.topActivityType, mMainExecutor,
+ taskId, mStartingWindowRecordManager);
mStartingWindowRecordManager.addRecord(taskId, tView);
}
}
@@ -50,8 +51,9 @@
private final TaskSnapshotWindow mTaskSnapshotWindow;
SnapshotWindowRecord(TaskSnapshotWindow taskSnapshotWindow,
- int activityType, ShellExecutor removeExecutor) {
- super(activityType, removeExecutor);
+ int activityType, ShellExecutor removeExecutor, int id,
+ StartingSurfaceDrawer.StartingWindowRecordManager recordManager) {
+ super(activityType, removeExecutor, id, recordManager);
mTaskSnapshotWindow = taskSnapshotWindow;
mBGColor = mTaskSnapshotWindow.getBackgroundColor();
}
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 4cfbbd9..31fc98b 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
@@ -358,7 +358,7 @@
}
}
if (shouldSaveView) {
- mStartingWindowRecordManager.removeWindow(taskId, true);
+ mStartingWindowRecordManager.removeWindow(taskId);
saveSplashScreenRecord(appToken, taskId, view, suggestType);
}
return shouldSaveView;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 7cbf263..e2be153 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -188,7 +188,7 @@
final SnapshotRecord record = sRecord instanceof SnapshotRecord
? (SnapshotRecord) sRecord : null;
if (record != null && record.hasImeSurface()) {
- records.removeWindow(taskId, true);
+ records.removeWindow(taskId);
}
}
@@ -256,10 +256,15 @@
@WindowConfiguration.ActivityType protected final int mActivityType;
protected final ShellExecutor mRemoveExecutor;
+ private final int mTaskId;
+ private final StartingWindowRecordManager mRecordManager;
- SnapshotRecord(int activityType, ShellExecutor removeExecutor) {
+ SnapshotRecord(int activityType, ShellExecutor removeExecutor, int taskId,
+ StartingWindowRecordManager recordManager) {
mActivityType = activityType;
mRemoveExecutor = removeExecutor;
+ mTaskId = taskId;
+ mRecordManager = recordManager;
}
@Override
@@ -301,6 +306,7 @@
@CallSuper
protected void removeImmediately() {
mRemoveExecutor.removeCallbacks(mScheduledRunnable);
+ mRecordManager.onRecordRemoved(mTaskId);
}
}
@@ -316,7 +322,7 @@
taskIds[i] = mStartingWindowRecords.keyAt(i);
}
for (int i = taskSize - 1; i >= 0; --i) {
- removeWindow(taskIds[i], true);
+ removeWindow(taskIds[i]);
}
}
@@ -335,9 +341,13 @@
}
}
- void removeWindow(int taskId, boolean immediately) {
+ void removeWindow(int taskId) {
mTmpRemovalInfo.taskId = taskId;
- removeWindow(mTmpRemovalInfo, immediately);
+ removeWindow(mTmpRemovalInfo, true/* immediately */);
+ }
+
+ void onRecordRemoved(int taskId) {
+ mStartingWindowRecords.remove(taskId);
}
StartingWindowRecord getRecord(int taskId) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
index 1445478..fed2f34 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
@@ -92,7 +92,8 @@
final SnapshotWindowRecord record = new SnapshotWindowRecord(mViewHost, wlw.mChildSurface,
taskDescription.getBackgroundColor(), snapshot.hasImeSurface(),
- runningTaskInfo.topActivityType, removeExecutor);
+ runningTaskInfo.topActivityType, removeExecutor,
+ taskId, mStartingWindowRecordManager);
mStartingWindowRecordManager.addRecord(taskId, record);
info.notifyAddComplete(wlw.mChildSurface);
}
@@ -104,8 +105,9 @@
SnapshotWindowRecord(SurfaceControlViewHost viewHost, SurfaceControl childSurface,
int bgColor, boolean hasImeSurface, int activityType,
- ShellExecutor removeExecutor) {
- super(activityType, removeExecutor);
+ ShellExecutor removeExecutor, int id,
+ StartingSurfaceDrawer.StartingWindowRecordManager recordManager) {
+ super(activityType, removeExecutor, id, recordManager);
mViewHost = viewHost;
mChildSurface = childSurface;
mBGColor = bgColor;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
index adae21b..93d7636 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
@@ -54,12 +54,13 @@
private static final String TAG = TaskViewTaskController.class.getSimpleName();
private final CloseGuard mGuard = new CloseGuard();
-
+ private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+ /** Used to inset the activity content to allow space for a caption bar. */
+ private final Binder mCaptionInsetsOwner = new Binder();
private final ShellTaskOrganizer mTaskOrganizer;
private final Executor mShellExecutor;
private final SyncTransactionQueue mSyncQueue;
private final TaskViewTransitions mTaskViewTransitions;
- private TaskViewBase mTaskViewBase;
private final Context mContext;
/**
@@ -70,21 +71,19 @@
* in this situation to allow us to notify listeners correctly if the task failed to open.
*/
private ActivityManager.RunningTaskInfo mPendingInfo;
- /* Indicates that the task we attempted to launch in the task view failed to launch. */
- private boolean mTaskNotFound;
+ private TaskViewBase mTaskViewBase;
protected ActivityManager.RunningTaskInfo mTaskInfo;
private WindowContainerToken mTaskToken;
private SurfaceControl mTaskLeash;
- private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+ /* Indicates that the task we attempted to launch in the task view failed to launch. */
+ private boolean mTaskNotFound;
private boolean mSurfaceCreated;
private SurfaceControl mSurfaceControl;
private boolean mIsInitialized;
private boolean mNotifiedForInitialized;
+ private boolean mHideTaskWithSurface = true;
private TaskView.Listener mListener;
private Executor mListenerExecutor;
-
- /** Used to inset the activity content to allow space for a caption bar. */
- private final Binder mCaptionInsetsOwner = new Binder();
private Rect mCaptionInsets;
public TaskViewTaskController(Context context, ShellTaskOrganizer organizer,
@@ -102,6 +101,19 @@
mGuard.open("release");
}
+ /**
+ * Specifies if the task should be hidden when the surface is destroyed.
+ * <p>This is {@code true} by default.
+ *
+ * @param hideTaskWithSurface {@code false} if task needs to remain visible even when the
+ * surface is destroyed, {@code true} otherwise.
+ */
+ public void setHideTaskWithSurface(boolean hideTaskWithSurface) {
+ // TODO(b/299535374): Remove mHideTaskWithSurface once the taskviews with launch root tasks
+ // are moved to a window in SystemUI in auto.
+ mHideTaskWithSurface = hideTaskWithSurface;
+ }
+
SurfaceControl getSurfaceControl() {
return mSurfaceControl;
}
@@ -257,9 +269,17 @@
mTaskNotFound = false;
}
+ /** This method shouldn't be called when shell transitions are enabled. */
private void updateTaskVisibility() {
+ boolean visible = mSurfaceCreated;
+ if (!visible && !mHideTaskWithSurface) {
+ return;
+ }
WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.setHidden(mTaskToken, !mSurfaceCreated /* hidden */);
+ wct.setHidden(mTaskToken, !visible /* hidden */);
+ if (!visible) {
+ wct.reorder(mTaskToken, false /* onTop */);
+ }
mSyncQueue.queue(wct);
if (mListener == null) {
return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index d310ae3..7df658e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -37,12 +37,8 @@
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
-import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_RELAUNCH;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
-import static android.window.TransitionInfo.FLAGS_IS_NON_APP_WINDOW;
import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_OWNER_THUMBNAIL;
import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL;
@@ -338,10 +334,6 @@
boolean isDisplayRotationAnimationStarted = false;
final boolean isDreamTransition = isDreamTransition(info);
final boolean isOnlyTranslucent = isOnlyTranslucent(info);
- final boolean isActivityReplace = checkActivityReplacement(info, startTransaction);
- // Some patterns (eg. activity "replacement") require us to re-interpret the type
- @WindowManager.TransitionType final int transitType =
- isActivityReplace ? TRANSIT_OPEN : info.getType();
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
@@ -438,8 +430,7 @@
// Don't animate anything that isn't independent.
if (!TransitionInfo.isIndependent(change, info)) continue;
- Animation a = loadAnimation(transitType, info, change, wallpaperTransit,
- isDreamTransition);
+ Animation a = loadAnimation(info, change, wallpaperTransit, isDreamTransition);
if (a != null) {
if (isTask) {
final boolean isTranslucent = (change.getFlags() & FLAG_TRANSLUCENT) != 0;
@@ -613,53 +604,6 @@
return (translucentOpen + translucentClose) > 0;
}
- /**
- * Checks for an edge-case where an activity calls finish() followed immediately by
- * startActivity() to "replace" itself. If in this case, it will swap the layer of the
- * close/open activities and return `true`. This way, we pretend like we are just "opening"
- * the new activity.
- */
- private static boolean checkActivityReplacement(@NonNull TransitionInfo info,
- SurfaceControl.Transaction t) {
- if (info.getType() != TRANSIT_CLOSE) {
- return false;
- }
- int closing = -1;
- int opening = -1;
- for (int i = info.getChanges().size() - 1; i >= 0; --i) {
- final TransitionInfo.Change change = info.getChanges().get(i);
- if ((change.getTaskInfo() != null || change.hasFlags(FLAG_IS_DISPLAY))
- && !TransitionUtil.isOrderOnly(change)) {
- // This isn't an activity-level transition.
- return false;
- }
- if (change.getTaskInfo() != null
- && change.hasFlags(FLAG_IS_DISPLAY | FLAGS_IS_NON_APP_WINDOW)) {
- // Ignore non-activity containers.
- continue;
- }
- if (TransitionUtil.isClosingType(change.getMode())) {
- closing = i;
- } else if (change.getMode() == TRANSIT_OPEN) {
- // OPEN implies that it is a new launch. If going "back" the opening app will be
- // TO_FRONT
- opening = i;
- } else if (change.getMode() == TRANSIT_TO_FRONT) {
- // Normal "going back", so not a replacement.
- return false;
- }
- }
- if (closing < 0 || opening < 0) {
- return false;
- }
- // Swap the opening and closing z-orders since we're swapping the transit type.
- final int numChanges = info.getChanges().size();
- final int zSplitLine = numChanges + 1;
- t.setLayer(info.getChanges().get(opening).getLeash(), zSplitLine + numChanges - opening);
- t.setLayer(info.getChanges().get(closing).getLeash(), zSplitLine - closing);
- return true;
- }
-
@Override
public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
@@ -712,11 +656,12 @@
}
@Nullable
- private Animation loadAnimation(int type, @NonNull TransitionInfo info,
+ private Animation loadAnimation(@NonNull TransitionInfo info,
@NonNull TransitionInfo.Change change, int wallpaperTransit,
boolean isDreamTransition) {
Animation a;
+ final int type = info.getType();
final int flags = info.getFlags();
final int changeMode = change.getMode();
final int changeFlags = change.getFlags();
@@ -771,8 +716,8 @@
// If there's a scene-transition, then jump-cut.
return null;
} else {
- a = loadAttributeAnimation(type, info, change, wallpaperTransit, mTransitionAnimation,
- isDreamTransition);
+ a = loadAttributeAnimation(
+ info, change, wallpaperTransit, mTransitionAnimation, isDreamTransition);
}
if (a != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
index 7b1ce2f..d978eaf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
@@ -45,7 +45,6 @@
import android.graphics.Shader;
import android.view.Surface;
import android.view.SurfaceControl;
-import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.window.ScreenCapture;
@@ -62,10 +61,10 @@
/** Loads the animation that is defined through attribute id for the given transition. */
@Nullable
- public static Animation loadAttributeAnimation(@WindowManager.TransitionType int type,
- @NonNull TransitionInfo info, @NonNull TransitionInfo.Change change,
- int wallpaperTransit, @NonNull TransitionAnimation transitionAnimation,
- boolean isDreamTransition) {
+ public static Animation loadAttributeAnimation(@NonNull TransitionInfo info,
+ @NonNull TransitionInfo.Change change, int wallpaperTransit,
+ @NonNull TransitionAnimation transitionAnimation, boolean isDreamTransition) {
+ final int type = info.getType();
final int changeMode = change.getMode();
final int changeFlags = change.getFlags();
final boolean enter = TransitionUtil.isOpeningType(changeMode);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
index d098d33..0088051 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
@@ -221,6 +221,20 @@
}
@Test
+ public void testSurfaceDestroyed_withTask_shouldNotHideTask_legacyTransitions() {
+ assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
+ mTaskViewTaskController.setHideTaskWithSurface(false);
+
+ SurfaceHolder sh = mock(SurfaceHolder.class);
+ mTaskViewTaskController.onTaskAppeared(mTaskInfo, mLeash);
+ mTaskView.surfaceCreated(sh);
+ reset(mViewListener);
+ mTaskView.surfaceDestroyed(sh);
+
+ verify(mViewListener, never()).onTaskVisibilityChanged(anyInt(), anyBoolean());
+ }
+
+ @Test
public void testSurfaceDestroyed_withTask_legacyTransitions() {
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
SurfaceHolder sh = mock(SurfaceHolder.class);
diff --git a/packages/CarrierDefaultApp/res/values-sq/strings.xml b/packages/CarrierDefaultApp/res/values-sq/strings.xml
index 238921a..d8a1ed7 100644
--- a/packages/CarrierDefaultApp/res/values-sq/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sq/strings.xml
@@ -5,7 +5,7 @@
<string name="android_system_label" msgid="2797790869522345065">"Operatori celular"</string>
<string name="portal_notification_id" msgid="5155057562457079297">"Të dhënat celulare kanë përfunduar"</string>
<string name="no_data_notification_id" msgid="668400731803969521">"Të dhënat celulare janë çaktivizuar"</string>
- <string name="portal_notification_detail" msgid="2295729385924660881">"Trokit për të vizituar sajtin e uebit të %s"</string>
+ <string name="portal_notification_detail" msgid="2295729385924660881">"Trokit për të vizituar uebsajtin e %s"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"Kontakto me ofruesin e shërbimit %s"</string>
<string name="no_mobile_data_connection_title" msgid="7449525772416200578">"Nuk ka lidhje të të dhënave celulare"</string>
<string name="no_mobile_data_connection" msgid="544980465184147010">"Shto plan të dhënash ose plan roaming përmes %s"</string>
@@ -16,7 +16,7 @@
<string name="ssl_error_continue" msgid="1138548463994095584">"Vazhdo gjithsesi nëpërmjet shfletuesit"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Përforcimi i performancës"</string>
<string name="performance_boost_notification_title" msgid="3126203390685781861">"Opsionet 5G nga operatori yt celular"</string>
- <string name="performance_boost_notification_detail" msgid="216569851036236346">"Vizito sajtin e uebit të %s për të parë opsione për përvojën tënde me aplikacionin"</string>
+ <string name="performance_boost_notification_detail" msgid="216569851036236346">"Vizito uebsajtin e %s për të parë opsione për përvojën tënde me aplikacionin"</string>
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Jo tani"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Menaxho"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Bli një paketë përforcimi të performancës."</string>
diff --git a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
index 89e48f9..780274c 100644
--- a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
@@ -49,7 +49,7 @@
<string name="sign_ins" msgid="4710739369149469208">"prijavljivanja"</string>
<string name="sign_in_info" msgid="2627704710674232328">"podaci za prijavljivanje"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvaj <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> u"</string>
- <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Želite da napravite pristupni kôd na drugom uređaju?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Želite da napravite pristupni ključ na drugom uređaju?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Želite da sačuvate lozinku na drugom uređaju?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Želite da sačuvate akreditive za prijavu na drugom uređaju?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Želite da za sva prijavljivanja koristite: <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
@@ -72,7 +72,7 @@
<string name="get_dialog_title_use_password_for" msgid="625828023234318484">"Želite da koristite sačuvanu lozinku za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Želite li da koristite svoje podatke za prijavljivanje za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Želite da otključate opcije prijavljivanja za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
- <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Izaberite sačuvan pristupni kôd za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Izaberite sačuvan pristupni ključ za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Izaberite sačuvanu lozinku za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Izaberite sačuvane podatke za prijavljivanje za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Odaberite podatke za prijavljivanje za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-in/strings.xml b/packages/CredentialManager/res/values-in/strings.xml
index e47cf7b..d6bf946 100644
--- a/packages/CredentialManager/res/values-in/strings.xml
+++ b/packages/CredentialManager/res/values-in/strings.xml
@@ -54,7 +54,7 @@
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Simpan info login di perangkat lain?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Gunakan <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> untuk semua info login Anda?"</string>
<string name="use_provider_for_all_description" msgid="1998772715863958997">"Pengelola sandi untuk <xliff:g id="USERNAME">%1$s</xliff:g> ini akan menyimpan sandi dan kunci sandi guna membantu Anda login dengan mudah"</string>
- <string name="set_as_default" msgid="4415328591568654603">"Setel sebagai default"</string>
+ <string name="set_as_default" msgid="4415328591568654603">"Jadikan default"</string>
<string name="settings" msgid="6536394145760913145">"Setelan"</string>
<string name="use_once" msgid="9027366575315399714">"Gunakan sekali"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> sandi • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> kunci sandi"</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index 40f8dc4..bf6bc8b 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -34,7 +34,7 @@
<string name="public_key_cryptography_title" msgid="6751970819265298039">"Kriptografia e çelësit publik"</string>
<string name="public_key_cryptography_detail" msgid="6937631710280562213">"Bazuar në aleancën FIDO (e cila përfshin Google, Apple, Microsoft e të tjera) dhe standardet W3C, çelësat e kalimit përdorin çifte çelësash kriptografikë. Ndryshe nga emri i përdoruesit dhe vargu i karaktereve që përdorim për fjalëkalime, një çift çelësash privat-publik krijohet për aplikacion ose sajtin e uebit. Çelësi privat ruhet i sigurt në pajisjen tënde ose në menaxherin e fjalëkalimeve dhe konfirmon identitetin tënd. Çelësi publik ndahet me aplikacionin ose serverin e sajtit të uebit. Me çelësat përkatës, mund të regjistrohesh dhe të identifikohesh në çast."</string>
<string name="improved_account_security_title" msgid="1069841917893513424">"Siguri e përmirësuar e llogarisë"</string>
- <string name="improved_account_security_detail" msgid="9123750251551844860">"Secili çelës është i lidhur ekskluzivisht me aplikacionin ose sajtin e uebit për të cilin është krijuar, kështu që nuk do të identifikohesh asnjëherë gabimisht në një aplikacion ose sajt uebi mashtrues. Gjithashtu, me serverët që mbajnë vetëm çelësa publikë, pirateria informatike është shumë më e vështirë."</string>
+ <string name="improved_account_security_detail" msgid="9123750251551844860">"Secili çelës është i lidhur ekskluzivisht me aplikacionin ose uebsajtin për të cilin është krijuar, kështu që nuk do të identifikohesh asnjëherë gabimisht në një aplikacion ose uebsajt mashtrues. Gjithashtu, me serverët që mbajnë vetëm çelësa publikë, pirateria informatike është shumë më e vështirë."</string>
<string name="seamless_transition_title" msgid="5335622196351371961">"Kalim i thjeshtuar"</string>
<string name="seamless_transition_detail" msgid="4475509237171739843">"Teksa shkojmë drejt një të ardhmeje pa fjalëkalime, këto të fundit do të ofrohen ende së bashku me çelësat e kalimit."</string>
<string name="choose_provider_title" msgid="8870795677024868108">"Zgjidh se ku t\'i ruash <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-sr/strings.xml b/packages/CredentialManager/res/values-sr/strings.xml
index f5a29a2..b83c698 100644
--- a/packages/CredentialManager/res/values-sr/strings.xml
+++ b/packages/CredentialManager/res/values-sr/strings.xml
@@ -49,7 +49,7 @@
<string name="sign_ins" msgid="4710739369149469208">"пријављивања"</string>
<string name="sign_in_info" msgid="2627704710674232328">"подаци за пријављивање"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Сачувај <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> у"</string>
- <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Желите да направите приступни кôд на другом уређају?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Желите да направите приступни кључ на другом уређају?"</string>
<string name="save_password_on_other_device_title" msgid="5829084591948321207">"Желите да сачувате лозинку на другом уређају?"</string>
<string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Желите да сачувате акредитиве за пријаву на другом уређају?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Желите да за сва пријављивања користите: <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
@@ -72,7 +72,7 @@
<string name="get_dialog_title_use_password_for" msgid="625828023234318484">"Желите да користите сачувану лозинку за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="790049858275131785">"Желите ли да користите своје податке за пријављивање за апликацију <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_unlock_options_for" msgid="7605568190597632433">"Желите да откључате опције пријављивања за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
- <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Изаберите сачуван приступни кôд за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Изаберите сачуван приступни кључ за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Изаберите сачувану лозинку за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Изаберите сачуване податке за пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="3048870756117876514">"Одаберите податке за пријављивање за апликацију <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
index 3505cfb..74f04e0 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
@@ -33,8 +33,6 @@
import androidx.annotation.Nullable;
-import java.io.File;
-
/**
* Installation failed: Return status code to the caller or display failure UI to user
*/
@@ -101,14 +99,8 @@
// Set header icon and title
PackageUtil.AppSnippet as;
PackageManager pm = getPackageManager();
-
- if ("package".equals(packageURI.getScheme())) {
- as = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
- pm.getApplicationIcon(appInfo));
- } else {
- final File sourceFile = new File(packageURI.getPath());
- as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
- }
+ as = intent.getParcelableExtra(PackageInstallerActivity.EXTRA_APP_SNIPPET,
+ PackageUtil.AppSnippet.class);
// Store label for dialog
mLabel = as.label;
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
index 7bea339..1088ace 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
@@ -16,6 +16,7 @@
package com.android.packageinstaller;
+import static com.android.packageinstaller.PackageInstallerActivity.EXTRA_APP_SNIPPET;
import static com.android.packageinstaller.PackageInstallerActivity.EXTRA_STAGED_SESSION_ID;
import android.app.PendingIntent;
@@ -86,7 +87,8 @@
// ContentResolver.SCHEME_FILE
// STAGED_SESSION_ID extra contains an ID of a previously staged install session.
final File sourceFile = new File(mPackageURI.getPath());
- PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
+ PackageUtil.AppSnippet as = getIntent()
+ .getParcelableExtra(EXTRA_APP_SNIPPET, PackageUtil.AppSnippet.class);
mAlert.setIcon(as.icon);
mAlert.setTitle(as.label);
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
index ff991d2..fbc9525 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
@@ -22,7 +22,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
@@ -30,7 +29,6 @@
import androidx.annotation.Nullable;
-import java.io.File;
import java.util.List;
/**
@@ -65,18 +63,8 @@
ApplicationInfo appInfo =
intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mAppPackageName = appInfo.packageName;
- Uri packageURI = intent.getData();
-
- // Set header icon and title
- PackageManager pm = getPackageManager();
-
- if ("package".equals(packageURI.getScheme())) {
- mAppSnippet = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
- pm.getApplicationIcon(appInfo));
- } else {
- File sourceFile = new File(packageURI.getPath());
- mAppSnippet = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
- }
+ mAppSnippet = intent.getParcelableExtra(PackageInstallerActivity.EXTRA_APP_SNIPPET,
+ PackageUtil.AppSnippet.class);
mLaunchIntent = getPackageManager().getLaunchIntentForPackage(mAppPackageName);
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index c4780b7..86aaba0 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -80,6 +80,7 @@
static final String EXTRA_CALLING_ATTRIBUTION_TAG = "EXTRA_CALLING_ATTRIBUTION_TAG";
static final String EXTRA_ORIGINAL_SOURCE_INFO = "EXTRA_ORIGINAL_SOURCE_INFO";
static final String EXTRA_STAGED_SESSION_ID = "EXTRA_STAGED_SESSION_ID";
+ static final String EXTRA_APP_SNIPPET = "EXTRA_APP_SNIPPET";
private static final String ALLOW_UNKNOWN_SOURCES_KEY =
PackageInstallerActivity.class.getName() + "ALLOW_UNKNOWN_SOURCES_KEY";
@@ -692,6 +693,9 @@
if (stagedSessionId > 0) {
newIntent.putExtra(EXTRA_STAGED_SESSION_ID, stagedSessionId);
}
+ if (mAppSnippet != null) {
+ newIntent.putExtra(EXTRA_APP_SNIPPET, mAppSnippet);
+ }
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
if (mLocalLOGV) Log.i(TAG, "downloaded app uri=" + mPackageURI);
startActivity(newIntent);
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
index ff0e5fb..6ab2def 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
@@ -27,8 +27,13 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.UserHandle;
import android.util.Log;
import android.view.View;
@@ -115,7 +120,7 @@
icon);
}
- static final class AppSnippet {
+ static final class AppSnippet implements Parcelable {
@NonNull public CharSequence label;
@Nullable public Drawable icon;
public AppSnippet(@NonNull CharSequence label, @Nullable Drawable icon) {
@@ -123,10 +128,52 @@
this.icon = icon;
}
+ private AppSnippet(Parcel in) {
+ label = in.readString();
+ Bitmap bmp = in.readParcelable(getClass().getClassLoader(), Bitmap.class);
+ icon = new BitmapDrawable(Resources.getSystem(), bmp);
+ }
+
@Override
public String toString() {
return "AppSnippet[" + label + (icon != null ? "(has" : "(no ") + " icon)]";
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(label.toString());
+ Bitmap bmp = getBitmapFromDrawable(icon);
+ dest.writeParcelable(bmp, 0);
+ }
+
+ private Bitmap getBitmapFromDrawable(Drawable drawable) {
+ // Create an empty bitmap with the dimensions of our drawable
+ final Bitmap bmp = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+ drawable.getIntrinsicHeight(),
+ Bitmap.Config.ARGB_8888);
+ // Associate it with a canvas. This canvas will draw the icon on the bitmap
+ final Canvas canvas = new Canvas(bmp);
+ // Draw the drawable in the canvas. The canvas will ultimately paint the drawable in the
+ // bitmap held within
+ drawable.draw(canvas);
+
+ return bmp;
+ }
+
+ public static final Parcelable.Creator<AppSnippet> CREATOR = new Parcelable.Creator<>() {
+ public AppSnippet createFromParcel(Parcel in) {
+ return new AppSnippet(in);
+ }
+
+ public AppSnippet[] newArray(int size) {
+ return new AppSnippet[size];
+ }
+ };
}
/**
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
index 90a723f..b77368a 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
@@ -253,6 +253,7 @@
hideTitleSemantics = false,
navigationIcon = navigationIcon,
actions = actionsRow,
+ titleScaleDisabled = false,
)
}
}
@@ -426,6 +427,7 @@
* accessibility services at the same time, when animating between collapsed / expanded states.
* @param navigationIcon a navigation icon [Composable]
* @param actions actions [Composable]
+ * @param titleScaleDisabled whether the title font scaling is disabled. Default is disabled.
*/
@Composable
private fun TopAppBarLayout(
@@ -443,6 +445,7 @@
hideTitleSemantics: Boolean,
navigationIcon: @Composable () -> Unit,
actions: @Composable () -> Unit,
+ titleScaleDisabled: Boolean = true,
) {
Layout(
{
@@ -466,9 +469,12 @@
ProvideTextStyle(value = titleTextStyle) {
CompositionLocalProvider(
LocalContentColor provides titleContentColor,
- // Disable the title font scaling by only passing the density but not the
- // font scale.
- LocalDensity provides Density(density = LocalDensity.current.density),
+ LocalDensity provides with(LocalDensity.current) {
+ Density(
+ density = density,
+ fontScale = if (titleScaleDisabled) 1f else fontScale,
+ )
+ },
content = title
)
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
index 67f4418..0a33b9b 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
@@ -18,6 +18,7 @@
import androidx.activity.compose.BackHandler
import androidx.appcompat.R
+import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.RowScope
@@ -96,7 +97,8 @@
Modifier
.padding(paddingValues.horizontalValues())
.padding(top = paddingValues.calculateTopPadding())
- .fillMaxSize(),
+ .focusable()
+ .fillMaxSize()
) {
content(
bottomPadding = paddingValues.calculateBottomPadding(),
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index e46db75..33907ec 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -344,7 +344,9 @@
continue;
}
final ProviderInfo providerInfo = resolved.providerInfo;
- final List<Bundle> entryData = getEntryDataFromProvider(context,
+ final List<Bundle> entryData = getEntryDataFromProvider(
+ // Build new context so the entry data is retrieved for the queried user.
+ context.createContextAsUser(user, 0 /* flags */),
providerInfo.authority);
if (entryData == null || entryData.isEmpty()) {
continue;
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index a005693..c5880a3 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -581,7 +581,7 @@
<string name="user_add_profile_item_title" msgid="3111051717414643029">"Beperkte profiel"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"Voeg nuwe gebruiker by?"</string>
<string name="user_add_user_message_long" msgid="1527434966294733380">"Jy kan hierdie toestel met ander mense deel deur bykomende gebruikers te skep. Elke gebruiker het hulle eie spasie wat hulle kan pasmaak met programme, muurpapier en so meer. Gebruikers kan ook toestelinstellings wat almal raak, soos wi-fi, aanpas.\n\nWanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul eie spasie opstel.\n\nEnige gebruiker kan programme vir alle ander gebruikers opdateer. Toeganklikheidinstellings en -dienste sal dalk nie na die nuwe gebruiker oorgedra word nie."</string>
- <string name="user_add_user_message_short" msgid="3295959985795716166">"Wanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel.\n\nEnige gebruiker kan programme vir al die ander gebruikers opdateer."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Wanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel.\n\nEnige gebruiker kan apps vir al die ander gebruikers opdateer."</string>
<string name="user_grant_admin_title" msgid="5157031020083343984">"Maak hierdie gebruiker ’n admin?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"Admins het spesiale voorregte wat ander gebruikers nie het nie. ’n Admin kan alle gebruikers bestuur, hierdie toestel opdateer of terugstel, instellings wysig, alle geïnstalleerde apps sien, en adminvoorregte vir ander mense gee of herroep."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"Maak admin"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 57b4694..f351770 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -677,7 +677,7 @@
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"Defolt"</string>
<string name="turn_screen_on_title" msgid="3266937298097573424">"Ekranı aktiv etmək"</string>
<string name="allow_turn_screen_on" msgid="6194845766392742639">"Ekranı aktiv etməyə icazə verin"</string>
- <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Tətbiqin ekranı aktiv etməsinə icazə verin. İcazə verilərsə, tətbiq istənilən vaxt sizə soruşmadan ekranı aktiv edə bilər."</string>
+ <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Tətbiqin ekranı aktiv etməsinə icazə verin. İcazə verilərsə, tətbiq istənilən vaxt sizdən soruşmadan ekranı aktiv edə bilər."</string>
<string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinin yayımlanması dayandırılsın?"</string>
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> tətbiqini yayımlasanız və ya nəticəni dəyişsəniz, cari yayımınız dayandırılacaq"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> tətbiqini yayımlayın"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index e9e0e90..7472fff 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -141,7 +141,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Otkaži"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Uparivanje omogućava pristup kontaktima i istoriji poziva nakon povezivanja."</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Uparivanje sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> nije moguće."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Uparivanje sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g> nije moguće zbog netačnog PIN-a ili pristupnog koda."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Uparivanje sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g> nije moguće zbog netačnog PIN-a ili pristupnog ključa."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Nije moguće komunicirati sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> je odbio/la uparivanje"</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Računar"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index b037b13..e38729eb 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -174,7 +174,7 @@
<string name="launch_defaults_some" msgid="3631650616557252926">"কিছু ডিফল্ট সেট করা রয়েছে"</string>
<string name="launch_defaults_none" msgid="8049374306261262709">"কোনও ডিফল্ট সেট করা নেই"</string>
<string name="tts_settings" msgid="8130616705989351312">"পাঠ্য থেকে ভাষ্য আউটপুট সেটিংস"</string>
- <string name="tts_settings_title" msgid="7602210956640483039">"টেক্সট-টু-স্পিচ"</string>
+ <string name="tts_settings_title" msgid="7602210956640483039">"টেক্সট-টু-স্পিচ আউটপুট"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"কথা বলার হার"</string>
<string name="tts_default_rate_summary" msgid="3781937042151716987">"যে গতিতে পাঠ্য উচ্চারিত হয়"</string>
<string name="tts_default_pitch_title" msgid="6988592215554485479">"পিচ"</string>
@@ -356,7 +356,7 @@
<string name="show_touches" msgid="8437666942161289025">"আলতো চাপ দেখান"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"আলতো চাপ দিলে ভিজ্যুয়াল প্রতিক্রিয়া দেখান"</string>
<string name="show_key_presses" msgid="6360141722735900214">"প্রেস করা কী দেখুন"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"প্রেস করা ফিজিকাল কীয়ের জন্য ভিস্যুয়াল মতামত দেখুন"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"ফিজিক্যাল কী প্রেস করা হলে ভিজুয়াল ফিডব্যাক দেখুন"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"সারফেস আপডেটগুলি দেখান"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"সম্পূর্ণ উইন্ডোর সারফেস আপডেট হয়ে গেলে সেটিকে ফ্ল্যাশ করুন"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"ভিউয়ের আপডেট দেখুন"</string>
@@ -675,7 +675,7 @@
<string name="physical_keyboard_title" msgid="4811935435315835220">"ফিজিক্যাল কীবোর্ড"</string>
<string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"কীবোর্ড লেআউট বেছে নিন"</string>
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"ডিফল্ট"</string>
- <string name="turn_screen_on_title" msgid="3266937298097573424">"স্ক্রিন চালু করুন"</string>
+ <string name="turn_screen_on_title" msgid="3266937298097573424">"স্ক্রিন চালু করা"</string>
<string name="allow_turn_screen_on" msgid="6194845766392742639">"স্ক্রিন চালু করার অনুমতি দিন"</string>
<string name="allow_turn_screen_on_description" msgid="43834403291575164">"অ্যাপকে স্ক্রিন চালু করার অনুমতি দিন। অনুমতি দেওয়া হলে, অ্যাপ আপনার এক্সপ্লিসিট ইনটেন্ট ছাড়াই যেকোনও সময় স্ক্রিন চালু করতে পারবে।"</string>
<string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> সম্প্রচার বন্ধ করবেন?"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 1a37a3f..67dbc1b 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -676,8 +676,8 @@
<string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Odaberite raspored tastature"</string>
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"Zadano"</string>
<string name="turn_screen_on_title" msgid="3266937298097573424">"Uključivanje ekrana"</string>
- <string name="allow_turn_screen_on" msgid="6194845766392742639">"Dozvolite uključivanje ekrana"</string>
- <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Dozvolite aplikaciji da uključi ekran. Ako se odobri, aplikacija može uključiti ekran bilo kada bez vaše izričite namjere."</string>
+ <string name="allow_turn_screen_on" msgid="6194845766392742639">"Dozvoli uključivanje ekrana"</string>
+ <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Dozvolite aplikaciji da uključuje ekran. Ako se odobri, aplikacija može uključiti ekran bilo kada bez vaše izričite namjere."</string>
<string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Zaustaviti emitiranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ako emitirate aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promijenite izlaz, trenutno emitiranje će se zaustaviti"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emitiraj aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 233b3e1..af13c27 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -306,7 +306,7 @@
<string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quan aquest mode està activat, és possible que l’adreça MAC d\'aquest dispositiu canviï cada vegada que es connecti a una xarxa amb l\'aleatorització d\'adreces MAC activada"</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"D\'ús mesurat"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"D\'ús no mesurat"</string>
- <string name="select_logd_size_title" msgid="1604578195914595173">"Mides de la memòria intermèdia del registrador"</string>
+ <string name="select_logd_size_title" msgid="1604578195914595173">"Mides de la memòria intermèdia del registre"</string>
<string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Selecciona la mida de la memòria intermèdia del registre"</string>
<string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"Vols esborrar l\'emmagatzematge persistent del registrador?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Quan deixem de supervisar amb el registrador persistent, hem d\'esborrar les dades del registrador que hi ha al teu dispositiu."</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 114742a..bb69a84 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -586,7 +586,7 @@
<string name="user_grant_admin_message" msgid="1673791931033486709">"Οι διαχειριστές έχουν ειδικά προνόμια που δεν έχουν οι υπόλοιποι χρήστες Ένας διαχειριστής μπορεί να διαχειριστεί όλους τους χρήστες, να ενημερώσει ή να επαναφέρει αυτήν τη συσκευή, να τροποποιήσει τις ρυθμίσεις, να δει όλες τις εγκατεστημένες εφαρμογές και να εκχωρήσει ή να ανακαλέσει προνόμια διαχειριστή άλλων χρηστών."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"Εκχώρηση δικαιωμάτων διαχειριστή"</string>
<string name="user_setup_dialog_title" msgid="8037342066381939995">"Να γίνει ρύθμιση χρήστη τώρα;"</string>
- <string name="user_setup_dialog_message" msgid="269931619868102841">"Βεβαιωθείτε ότι ο χρήστης μπορεί να πάρει τη συσκευή και ρυθμίστε τον χώρο του"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Βεβαιωθείτε ότι ο χρήστης μπορεί να πάρει τη συσκευή για τη ρύθμιση του χώρου του"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Να γίνει ρύθμιση προφίλ τώρα;"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"Ρύθμιση τώρα"</string>
<string name="user_setup_button_setup_later" msgid="8712980133555493516">"Όχι τώρα"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index df256e5..0d13658 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -355,8 +355,8 @@
<string name="pointer_location_summary" msgid="957120116989798464">"Superpone los datos de las pulsaciones en la pantalla"</string>
<string name="show_touches" msgid="8437666942161289025">"Mostrar toques"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"Muestra la ubicación de los toques en la pantalla"</string>
- <string name="show_key_presses" msgid="6360141722735900214">"Ver pulsación de teclas"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"Ver respuestas visuales al pulsar teclas físicas"</string>
+ <string name="show_key_presses" msgid="6360141722735900214">"Ver teclas pulsadas"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"Muestra respuestas visuales al pulsar teclas físicas"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"Mostrar cambios de superficies"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"Hace parpadear todas las superficies de la ventana cuando se actualizan"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"Ver actualizaciones de vista"</string>
@@ -581,7 +581,7 @@
<string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restringido"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"¿Añadir nuevo usuario?"</string>
<string name="user_add_user_message_long" msgid="1527434966294733380">"Puedes compartir este dispositivo si creas más usuarios. Cada uno tendrá su propio espacio y podrá personalizarlo con aplicaciones, un fondo de pantalla y mucho más. Los usuarios también pueden ajustar opciones del dispositivo, como la conexión Wi‑Fi, que afectan a todos los usuarios.\n\nCuando añadas un usuario, tendrá que configurar su espacio.\n\nCualquier usuario puede actualizar aplicaciones de todos los usuarios. Es posible que no se transfieran los servicios y opciones de accesibilidad al nuevo usuario."</string>
- <string name="user_add_user_message_short" msgid="3295959985795716166">"Al añadir un nuevo usuario, dicha persona debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de usuarios."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Al añadir un nuevo usuario, dicha persona debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de los usuarios."</string>
<string name="user_grant_admin_title" msgid="5157031020083343984">"¿Convertir a este usuario en administrador?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"Los administradores tienen privilegios especiales que otros usuarios no tienen. Los administradores pueden gestionar todos los usuarios, actualizar o restablecer este dispositivo, modificar los ajustes, ver todas las aplicaciones instaladas y conceder o revocar privilegios de administrador a otros usuarios."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"Convertir en administrador"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index be847b3..d13d022 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -586,7 +586,7 @@
<string name="user_grant_admin_message" msgid="1673791931033486709">"Administraatoritel on eriõigused, mida teistel kasutajatel pole. Administraator saab hallata kõiki kasutajaid, värskendada või lähtestada seda seadet, muuta seadeid, vaadata kõiki installitud rakendusi ja anda teistele kasutajatele administraatoriõigused või need eemaldada."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"Määra administraatoriks"</string>
<string name="user_setup_dialog_title" msgid="8037342066381939995">"Kas seadistada kasutaja kohe?"</string>
- <string name="user_setup_dialog_message" msgid="269931619868102841">"Veenduge, et isik saaks seadet kasutada ja oma ruumi seadistada"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Veenduge, et isik saaks seadet kasutada ja oma ruumi seadistada."</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Kas soovite kohe profiili seadistada?"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"Seadista kohe"</string>
<string name="user_setup_button_setup_later" msgid="8712980133555493516">"Mitte praegu"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 9f33fa4..a474ef5 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -676,7 +676,7 @@
<string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"انتخاب طرحبندی صفحهکلید"</string>
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"پیشفرض"</string>
<string name="turn_screen_on_title" msgid="3266937298097573424">"روشن کردن صفحهنمایش"</string>
- <string name="allow_turn_screen_on" msgid="6194845766392742639">"اعطای اجازه برای روشن کردن صفحهنمایش"</string>
+ <string name="allow_turn_screen_on" msgid="6194845766392742639">"اجازه روشن کردن صفحهنمایش"</string>
<string name="allow_turn_screen_on_description" msgid="43834403291575164">"به برنامه اجازه میدهد صفحهنمایش را روشن کند. اگر اجازه داده شود، ممکن است این برنامه در هر زمانی بدون هدف صریح شما صفحهنمایش را روشن کند."</string>
<string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"همهفرستی <xliff:g id="APP_NAME">%1$s</xliff:g> متوقف شود؟"</string>
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"اگر <xliff:g id="SWITCHAPP">%1$s</xliff:g> را همهفرستی کنید یا خروجی را تغییر دهید، همهفرستی کنونی متوقف خواهد شد"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index c54e8a9..5099da4 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -355,8 +355,8 @@
<string name="pointer_location_summary" msgid="957120116989798464">"Superposition à l\'écran indiquant l\'emplacement actuel du curseur"</string>
<string name="show_touches" msgid="8437666942161289025">"Indicateurs visuels"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"Afficher un indicateur visuel là où l\'utilisateur appuie sur l\'écran"</string>
- <string name="show_key_presses" msgid="6360141722735900214">"Afficher appuis touche"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"Afficher retour visuel pour appuis de touches"</string>
+ <string name="show_key_presses" msgid="6360141722735900214">"Afficher les pressions sur les touches"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"Afficher un retour visuel des pressions sur les touches"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"Mises à jour de la surface"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"Faire clignoter les endroits où des mises à jour sont effectuées"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"Mises à jour de fenêtres"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index bd508d9..8644852 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -214,7 +214,7 @@
</string-array>
<string name="choose_profile" msgid="343803890897657450">"प्रोफ़ाइल चुनें"</string>
<string name="category_personal" msgid="6236798763159385225">"निजी"</string>
- <string name="category_work" msgid="4014193632325996115">"वर्क ऐप्लिकेशन"</string>
+ <string name="category_work" msgid="4014193632325996115">"वर्क"</string>
<string name="category_clone" msgid="1554511758987195974">"क्लोन"</string>
<string name="development_settings_title" msgid="140296922921597393">"डेवलपर के लिए सेटिंग और टूल"</string>
<string name="development_settings_enable" msgid="4285094651288242183">"डेवलपर के लिए सेटिंग और टूल चालू करें"</string>
@@ -356,7 +356,7 @@
<string name="show_touches" msgid="8437666942161289025">"टैप दिखाएं"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"टैप के लिए विज़ुअल फ़ीडबैक दिखाएं"</string>
<string name="show_key_presses" msgid="6360141722735900214">"दबाए गए बटन दिखाएं"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"दबाए गए बटन के लिए विज़ुअल फ़ीडबैक दिखाएं"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"दबाए गए बटन का विज़ुअल फ़ीडबैक दिखाएं"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"सर्फ़ेस अपडेट दिखाएं"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"अपडेट होने पर पूरे विंडो सर्फ़ेस फ़्लैश करें"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"जीपीयू व्यू के अपडेट दिखाएं"</string>
@@ -585,10 +585,10 @@
<string name="user_grant_admin_title" msgid="5157031020083343984">"क्या इस व्यक्ति को एडमिन बनाना है?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"एडमिन के पास अन्य लोगों के मुकाबले खास अधिकार होते हैं. एडमिन के पास ये अधिकार होते हैं: सभी लोगों को मैनेज करना, इस डिवाइस को अपडेट या रीसेट करना, सेटिंग में बदलाव करना, इंस्टॉल किए गए सभी ऐप्लिकेशन देखना, और अन्य लोगों को एडमिन के खास अधिकार देना या उन्हें वापस लेना."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"एडमिन बनाएं"</string>
- <string name="user_setup_dialog_title" msgid="8037342066381939995">"उपयोगकर्ता को अभी सेट करें?"</string>
- <string name="user_setup_dialog_message" msgid="269931619868102841">"पक्का करें कि व्यक्ति डिवाइस का इस्तेमाल करने और अपनी जगह सेट करने के लिए मौजूद है"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"उपयोगकर्ता खाता सेटअप करना है?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"पक्का करें कि उपयोगकर्ता, डिवाइस पर अपने खाते को पसंद के हिसाब से सेट अप करने के लिए मौजूद हो"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"प्रोफ़ाइल अभी सेट करें?"</string>
- <string name="user_setup_button_setup_now" msgid="1708269547187760639">"अभी सेट करें"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"अभी सेट अप करें"</string>
<string name="user_setup_button_setup_later" msgid="8712980133555493516">"रद्द करें"</string>
<string name="user_add_user_type_title" msgid="551279664052914497">"जोड़ें"</string>
<string name="user_new_user_name" msgid="60979820612818840">"नया उपयोगकर्ता"</string>
@@ -675,7 +675,7 @@
<string name="physical_keyboard_title" msgid="4811935435315835220">"फ़िज़िकल कीबोर्ड"</string>
<string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"कीबोर्ड का लेआउट चुनें"</string>
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"डिफ़ॉल्ट"</string>
- <string name="turn_screen_on_title" msgid="3266937298097573424">"स्क्रीन चालू करें"</string>
+ <string name="turn_screen_on_title" msgid="3266937298097573424">"स्क्रीन चालू करने की अनुमति"</string>
<string name="allow_turn_screen_on" msgid="6194845766392742639">"स्क्रीन चालू करने की अनुमति दें"</string>
<string name="allow_turn_screen_on_description" msgid="43834403291575164">"ऐप्लिकेशन को स्क्रीन चालू करने की अनुमति दें. ऐसा करने पर, ऐप्लिकेशन आपकी अनुमति लिए बिना भी, जब चाहे स्क्रीन चालू कर सकता है."</string>
<string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर ब्रॉडकास्ट करना रोकें?"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 07dd53a..729e91f 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -599,7 +599,7 @@
<string name="user_set_lock_button" msgid="1427128184982594856">"Setel kunci"</string>
<string name="user_switch_to_user" msgid="6975428297154968543">"Beralih ke <xliff:g id="USER_NAME">%s</xliff:g>"</string>
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Membuat pengguna baru …"</string>
- <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Membuat tamu baru …"</string>
+ <string name="creating_new_guest_dialog_message" msgid="1114905602181350690">"Membuat tamu baru…"</string>
<string name="add_user_failed" msgid="4809887794313944872">"Gagal membuat pengguna baru"</string>
<string name="add_guest_failed" msgid="8074548434469843443">"Gagal membuat tamu baru"</string>
<string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index d15b4ef..1f61bbf 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -356,7 +356,7 @@
<string name="show_touches" msgid="8437666942161289025">"タップを表示"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"タップを視覚表示する"</string>
<string name="show_key_presses" msgid="6360141722735900214">"キーの押下を表示"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"物理キーの押下に関する視覚的フィードバックを表示"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"物理キーが押下されたことを視覚的に表示"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"表示面の更新を通知"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"更新時にウィンドウの表示面全体を点滅させる"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"画面の更新を表示"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index f7a8bfd..047c4cd 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -356,7 +356,7 @@
<string name="show_touches" msgid="8437666942161289025">"បង្ហាញការចុច"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"បង្ហាញដានចុច នៅពេលចុច"</string>
<string name="show_key_presses" msgid="6360141722735900214">"បង្ហាញការចុចគ្រាប់ចុច"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"បង្ហាញព័ត៌មានឆ្លើយតបជារូបភាពសម្រាប់ការចុចគ្រាប់ចុចរូបវន្ត"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"បង្ហាញរូបភាពប្រតិកម្មសម្រាប់ការចុចគ្រាប់ចុចរូបវន្ត"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"បង្ហាញបច្ចុប្បន្នភាពផ្ទៃ"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"ផ្ទៃវីនដូទាំងមូលបញ្ចេញពន្លឺនៅពេលធ្វើបច្ចុប្បន្នភាព"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"បង្ហាញបច្ចុប្បន្នភាពទិដ្ឋភាព"</string>
@@ -586,7 +586,7 @@
<string name="user_grant_admin_message" msgid="1673791931033486709">"អ្នកគ្រប់គ្រងមានសិទ្ធិពិសេសដែលអ្នកប្រើប្រាស់ផ្សេងទៀតមិនមាន។ អ្នកគ្រប់គ្រងអាចគ្រប់គ្រងអ្នកប្រើប្រាស់ទាំងអស់ ធ្វើបច្ចុប្បន្នភាពឬកំណត់ឧបករណ៍នេះឡើងវិញ កែសម្រួលការកំណត់ មើលកម្មវិធីដែលបានដំឡើងទាំងអស់ និងផ្ដល់ឬដកសិទ្ធិជាអ្នកគ្រប់គ្រងសម្រាប់អ្នកផ្សេងទៀត។"</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"ផ្ដល់សិទ្ធិជាអ្នកគ្រប់គ្រង"</string>
<string name="user_setup_dialog_title" msgid="8037342066381939995">"រៀបចំអ្នកប្រើប្រាស់ឥឡូវនេះ?"</string>
- <string name="user_setup_dialog_message" msgid="269931619868102841">"សូមប្រាកដថាអ្នកប្រើប្រាស់នេះអាចយកឧបករណ៍ និងរៀបចំទំហំផ្ទុករបស់គេបាន"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"សូមប្រាកដថាអ្នកប្រើប្រាស់នេះអាចយកឧបករណ៍ និងរៀបចំទំហំផ្ទុករបស់គាត់បាន"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"រៀបចំប្រវត្តិរូបឥឡូវ?"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"រៀបចំឥឡូវ"</string>
<string name="user_setup_button_setup_later" msgid="8712980133555493516">"កុំទាន់"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 818af41..1c3053d 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -580,7 +580,7 @@
<string name="user_add_user_item_title" msgid="2394272381086965029">"ಬಳಕೆದಾರ"</string>
<string name="user_add_profile_item_title" msgid="3111051717414643029">"ನಿರ್ಬಂಧಿಸಿದ ಪ್ರೊಫೈಲ್"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಬೇಕೆ?"</string>
- <string name="user_add_user_message_long" msgid="1527434966294733380">"ನೀವು ಹೆಚ್ಚುವರಿ ಬಳಕೆದಾರರನ್ನು ರಚಿಸುವ ಮೂಲಕ ಇತರ ಜನರ ಜೊತೆಗೆ ಈ ಸಾಧನವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು. ಪ್ರತಿ ಬಳಕೆದಾರರು ತಮ್ಮದೇ ಸ್ಥಳವನ್ನು ಹೊಂದಿರುತ್ತಾರೆ, ಇದರಲ್ಲಿ ಅವರು ತಮ್ಮದೇ ಅಪ್ಲಿಕೇಶನ್ಗಳು, ವಾಲ್ಪೇಪರ್ ಮತ್ತು ಮುಂತಾದವುಗಳ ಮೂಲಕ ಕಸ್ಟಮೈಸ್ ಮಾಡಿಕೊಳ್ಳಬಹುದು. ಎಲ್ಲರ ಮೇಲೂ ಪರಿಣಾಮ ಬೀರುವಂತೆ ವೈ-ಫೈ ರೀತಿಯ ಸಾಧನ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬಳಕೆದಾರರು ಸರಿಹೊಂದಿಸಬಹುದು.\n\nನೀವು ಒಬ್ಬ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ತಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಟಪ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ.\n\nಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗೆ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು. ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಸೇವೆಗಳು ಹೊಸ ಬಳಕೆದಾರರಿಗೆ ವರ್ಗಾವಣೆ ಆಗದಿರಬಹುದು."</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"ನೀವು ಹೆಚ್ಚುವರಿ ಬಳಕೆದಾರರನ್ನು ರಚಿಸುವ ಮೂಲಕ ಇತರ ಜನರ ಜೊತೆಗೆ ಈ ಸಾಧನವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು. ಪ್ರತಿ ಬಳಕೆದಾರರು ತಮ್ಮದೇ ಸ್ಥಳವನ್ನು ಹೊಂದಿರುತ್ತಾರೆ, ಇದರಲ್ಲಿ ಅವರು ತಮ್ಮದೇ ಆ್ಯಪ್ಗಳು, ವಾಲ್ಪೇಪರ್ ಮತ್ತು ಮುಂತಾದವುಗಳ ಮೂಲಕ ಕಸ್ಟಮೈಸ್ ಮಾಡಿಕೊಳ್ಳಬಹುದು. ಎಲ್ಲರ ಮೇಲೂ ಪರಿಣಾಮ ಬೀರುವಂತೆ ವೈ-ಫೈ ರೀತಿಯ ಸಾಧನ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬಳಕೆದಾರರು ಸರಿಹೊಂದಿಸಬಹುದು.\n\nನೀವು ಒಬ್ಬ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ತಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಟಪ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ.\n\nಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗೆ ಆ್ಯಪ್ಗಳನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು. ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಸೇವೆಗಳು ಹೊಸ ಬಳಕೆದಾರರಿಗೆ ವರ್ಗಾವಣೆ ಆಗದಿರಬಹುದು."</string>
<string name="user_add_user_message_short" msgid="3295959985795716166">"ನೀವು ಒಬ್ಬ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ತಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಟಪ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ.\n\nಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು."</string>
<string name="user_grant_admin_title" msgid="5157031020083343984">"ಈ ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಾಹಕರನ್ನಾಗಿ ಮಾಡಬೇಕೆ?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"ನಿರ್ವಾಹಕರು ಇತರ ಬಳಕೆದಾರರಿಗೆ ಇಲ್ಲದ ವಿಶೇಷ ಸೌಲಭ್ಯಗಳನ್ನು ಹೊಂದಿದ್ದಾರೆ. ನಿರ್ವಾಹಕರು ಎಲ್ಲಾ ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸಬಹುದು, ಈ ಸಾಧನವನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು ಅಥವಾ ರೀಸೆಟ್ ಮಾಡಬಹುದು, ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಹೊಂದಿಸಬಹುದು, ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾದ ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳನ್ನು ವೀಕ್ಷಿಸಬಹುದು ಮತ್ತು ಇತರರಿಗೆ ನಿರ್ವಾಹಕರಿಗೆ ನೀಡಿರುವ ಸೌಲಭ್ಯಗಳನ್ನು ನೀಡಬಹುದು ಅಥವಾ ಹಿಂತೆಗೆದುಕೊಳ್ಳಬಹುದು."</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 653ac23..6b99e52 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -581,7 +581,7 @@
<string name="user_add_profile_item_title" msgid="3111051717414643029">"제한된 프로필"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"신규 사용자를 추가할까요?"</string>
<string name="user_add_user_message_long" msgid="1527434966294733380">"추가 사용자를 만들어 다른 사용자와 기기를 공유할 수 있습니다. 각 사용자는 앱, 배경화면 등으로 맞춤설정할 수 있는 자신만의 공간을 갖게 됩니다. 또한 모든 사용자에게 영향을 미치는 Wi‑Fi와 같은 기기 설정도 조정할 수 있습니다.\n\n추가된 신규 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자가 앱을 업데이트할 수 있으며, 업데이트는 다른 사용자에게도 적용됩니다. 접근성 설정 및 서비스는 신규 사용자에게 이전되지 않을 수도 있습니다."</string>
- <string name="user_add_user_message_short" msgid="3295959985795716166">"추가된 새로운 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자는 다른 사용자들을 위하여 앱을 업데이트할 수 있습니다."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"추가된 신규 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자가 앱을 업데이트할 수 있으며, 업데이트는 다른 사용자에게도 적용됩니다."</string>
<string name="user_grant_admin_title" msgid="5157031020083343984">"이 사용자에게 관리자 권한을 부여하시겠습니까?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"관리자는 다른 사용자가 가지지 못한 특별한 권한을 보유합니다. 관리자는 모든 사용자를 관리하고, 기기를 업데이트하거나 재설정하고, 설정을 변경하고, 설치된 모든 앱을 확인하고, 다른 사용자에게 관리자 권한을 부여하거나 취소할 수 있습니다."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"관리자 권한 부여"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index c2aa652..e2cb3ed 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -351,10 +351,10 @@
<string name="debug_monitoring_category" msgid="1597387133765424994">"Мониторинг"</string>
<string name="strict_mode" msgid="889864762140862437">"Катаал режим иштетилди"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Узак операцияларда экран күйүп-өчүп турат"</string>
- <string name="pointer_location" msgid="7516929526199520173">"Көрсөткүчтүн жайгшкн жери"</string>
+ <string name="pointer_location" msgid="7516929526199520173">"Көрсөткүчтүн турган жери"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"Басылган жерлер жана жаңсоолор экранда көрүнүп турат"</string>
<string name="show_touches" msgid="8437666942161289025">"Басылган жерлерди көрсөтүү"</string>
- <string name="show_touches_summary" msgid="3692861665994502193">"Экранда басылган жерлер көрүнүп турат"</string>
+ <string name="show_touches_summary" msgid="3692861665994502193">"Экрандын басылган жерлери көрүнүп турат"</string>
<string name="show_key_presses" msgid="6360141722735900214">"Баскычтардын басылганын көрсөтүү"</string>
<string name="show_key_presses_summary" msgid="725387457373015024">"Баскычтар басылганда визуалдык сигнал көрүнөт"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"Экран жаңыруусун көрсөтүү"</string>
@@ -585,8 +585,8 @@
<string name="user_grant_admin_title" msgid="5157031020083343984">"Бул колдонуучуну админ кыласызбы?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"Админдердин өзгөчө укуктары бар. Админ бардык колдонуучуларды тескеп, бул түзмөктү жаңыртып же баштапкы абалга келтирип, параметрлерди өзгөртүп, орнотулган колдонмолордун баарын көрүп, башкаларга админ укуктарын берип же жокко чыгара алат."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"Админ кылуу"</string>
- <string name="user_setup_dialog_title" msgid="8037342066381939995">"Профилди жөндөйсүзбү?"</string>
- <string name="user_setup_dialog_message" msgid="269931619868102841">"Өз мейкиндигин жөндөп алышы үчүн, түзмөктү колдонуучуга беришиңиз керек."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Профиль түзөсүзбү?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Колдонуучу өз мейкиндигин түзүп алышы үчүн түзмөктү ага беришиңиз керек."</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Профайл азыр түзүлсүнбү?"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"Азыр түзүү"</string>
<string name="user_setup_button_setup_later" msgid="8712980133555493516">"Азыр эмес"</string>
@@ -677,7 +677,7 @@
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"Демейки"</string>
<string name="turn_screen_on_title" msgid="3266937298097573424">"Экранды күйгүзүү"</string>
<string name="allow_turn_screen_on" msgid="6194845766392742639">"Экранды күйгүзүүгө уруксат берүү"</string>
- <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Колдонмого экранды күйгүзүүгө уруксат бериңиз. Уруксат берилсе, колдонмо экранды каалаган убакта сизден уруксат сурабастан күйгүзүшү мүмкүн."</string>
+ <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Колдонмого экранды күйгүзүүгө уруксат бересиз. Колдонмо экранды каалаган убакта сизден уруксат сурабастан күйгүзө берет."</string>
<string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда кабарлоо токтотулсунбу?"</string>
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Эгер <xliff:g id="SWITCHAPP">%1$s</xliff:g> колдонмосунда кабарласаңыз же аудионун чыгуусун өзгөртсөңүз, учурдагы кабарлоо токтотулат"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> колдонмосунда кабарлоо"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 0a429fd..b61a28e 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -356,7 +356,7 @@
<string name="show_touches" msgid="8437666942161289025">"ສະແດງການແຕະ"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"ສະແດງຄໍາຕິຊົມທາງຮູບພາບສຳລັບການແຕະ"</string>
<string name="show_key_presses" msgid="6360141722735900214">"ສະແດງການກົດປຸ່ມ"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"ສະແດງຄຳຕິຊົມພາບສຳລັບການກົດປຸ່ມຈິງ"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"ສະແດງການຕອບສະໜອງທີ່ເປັນພາບສຳລັບການກົດປຸ່ມຈິງ"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"ສະແດງການອັບເດດພື້ນຜິວ"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"ກະພິບໜ້າຈໍທັງໜ້າເມື່ອມີການອັບເດດ"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"ສະແດງອັບເດດມຸມມອງ"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 29fb6d4..08ec898 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -356,7 +356,7 @@
<string name="show_touches" msgid="8437666942161289025">"Товшилтыг харуулах"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"Товшилтын визуал хариу үйлдлийг харуулах"</string>
<string name="show_key_presses" msgid="6360141722735900214">"Түлхүүрийн даралт харуул"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"Биет түлхүүрийн даралтын визуал санал хүсэлт харуул"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"Биет түлхүүрийн даралтын визуал хариу үйлдлийг харуул"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"Гадаргын шинэчлэлтүүдийг харуулах"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"Шинэчлэгдэх үед цонхны гадаргыг бүхэлд нь анивчуулах"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"Шинэчлэлт харахыг харуулах"</string>
@@ -676,7 +676,7 @@
<string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Гарын бүдүүвчийг сонгох"</string>
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"Өгөгдмөл"</string>
<string name="turn_screen_on_title" msgid="3266937298097573424">"Дэлгэцийг асаах"</string>
- <string name="allow_turn_screen_on" msgid="6194845766392742639">"Дэлгэцийг асаахыг зөвшөөрнө үү"</string>
+ <string name="allow_turn_screen_on" msgid="6194845766392742639">"Дэлгэцийг асаахыг зөвшөөрөх"</string>
<string name="allow_turn_screen_on_description" msgid="43834403291575164">"Аппад дэлгэцийг асаахыг зөвшөөрнө үү. Зөвшөөрсөн тохиолдолд тухайн апп таны тодорхой оролцоогүйгээр ямар ч үед дэлгэцийг асааж болно."</string>
<string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г нэвтрүүлэхээ зогсоох уу?"</string>
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Хэрэв та <xliff:g id="SWITCHAPP">%1$s</xliff:g>-г нэвтрүүлсэн эсвэл гаралтыг өөрчилсөн бол таны одоогийн нэвтрүүлэлтийг зогсооно"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 0a41c0f..c924543 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -581,12 +581,12 @@
<string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil terhad"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"Tambah pengguna baharu?"</string>
<string name="user_add_user_message_long" msgid="1527434966294733380">"Anda boleh berkongsi peranti ini dengan orang lain dengan membuat pengguna tambahan. Setiap pengguna mempunyai ruang mereka sendiri, yang boleh diperibadikan dengan apl, kertas dinding dan sebagainya. Pengguna juga boleh melaraskan tetapan peranti seperti Wi-Fi yang akan memberi kesan kepada semua orang.\n\nApabila anda menambah pengguna baharu, orang itu perlu menyediakan ruang mereka.\n\nMana-mana pengguna boleh mengemaskinikan apl untuk semua pengguna lain. Tetapan dan perkhidmatan kebolehaksesan tidak boleh dipindahkan kepada pengguna baharu."</string>
- <string name="user_add_user_message_short" msgid="3295959985795716166">"Apabila anda menambah pengguna baharu, orang itu perlu menyediakan ruangnya sendiri.\n\nMana-mana pengguna boleh mengemaskinikan apl untuk semua pengguna lain."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Apabila anda menambahkan pengguna baharu, orang itu perlu menyediakan ruangnya sendiri.\n\nMana-mana pengguna boleh mengemaskinikan apl untuk semua pengguna lain."</string>
<string name="user_grant_admin_title" msgid="5157031020083343984">"Jadikan pengguna ini pentadbir?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"Pentadbir mempunyai keistimewaan khas yang tiada pada pengguna lain. Pentadbir boleh mengurus semua pengguna, mengemaskinikan atau menetapkan semula peranti ini, mengubah suai tetapan, melihat semua apl yang telah dipasang dan memberikan atau membatalkan keistimewaan pentadbir untuk pengguna lain."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"Jadikan pentadbir"</string>
<string name="user_setup_dialog_title" msgid="8037342066381939995">"Sediakan pengguna sekarang?"</string>
- <string name="user_setup_dialog_message" msgid="269931619868102841">"Pastikan orang itu tersedia untuk mengambil peranti dan menyediakan ruangan"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Pastikan individu itu bersedia untuk mengambil peranti dan menyediakan ruangannya"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Sediakan profil sekarang?"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"Sediakan sekarang"</string>
<string name="user_setup_button_setup_later" msgid="8712980133555493516">"Bukan sekarang"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 598304b..1483adc 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -449,8 +449,8 @@
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> igjen"</string>
<string name="power_discharging_duration" msgid="1076561255466053220">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> igjen (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
- <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår basert på bruken din"</string>
- <string name="power_discharging_duration_enhanced" msgid="1800465736237672323">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår basert på bruken din (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
+ <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> igjen basert på bruken din"</string>
+ <string name="power_discharging_duration_enhanced" msgid="1800465736237672323">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> igjen basert på bruken din (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<!-- no translation found for power_remaining_duration_only_short (7438846066602840588) -->
<skip />
<string name="power_discharge_by_enhanced" msgid="563438403581662942">"Skal vare til omtrent <xliff:g id="TIME">%1$s</xliff:g>, basert på bruken din (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 5d61132..4d9f119 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -58,10 +58,10 @@
<string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' मा जडान गर्न सकिँदैन"</string>
<string name="wifi_check_password_try_again" msgid="8817789642851605628">"पासवर्ड जाँच गरेर फेरि प्रयास गर्नुहोस्"</string>
<string name="wifi_not_in_range" msgid="1541760821805777772">"दायराभित्र छैन"</string>
- <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"स्वतः जडान हुने छैन"</string>
+ <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"अटो कनेक्ट हुने छैन"</string>
<string name="wifi_no_internet" msgid="1774198889176926299">"इन्टरनेटमाथिको पहुँच छैन"</string>
<string name="saved_network" msgid="7143698034077223645">"<xliff:g id="NAME">%1$s</xliff:g> द्वारा सेभ गरियो"</string>
- <string name="connected_via_network_scorer" msgid="7665725527352893558">"%1$s मार्फत् स्वतः जडान गरिएको"</string>
+ <string name="connected_via_network_scorer" msgid="7665725527352893558">"%1$s मार्फत् अटो कनेक्ट गरिएको"</string>
<string name="connected_via_network_scorer_default" msgid="7973529709744526285">"नेटवर्क मूल्याङ्कनकर्ता मार्फत स्वत: जडान गरिएको"</string>
<string name="connected_via_app" msgid="3532267661404276584">"<xliff:g id="NAME">%1$s</xliff:g> मार्फत जडान गरिएको"</string>
<string name="tap_to_sign_up" msgid="5356397741063740395">"साइन अप गर्न ट्याप गर्नुहोस्"</string>
@@ -581,12 +581,12 @@
<string name="user_add_profile_item_title" msgid="3111051717414643029">"प्रतिबन्धित प्रोफाइल"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"नयाँ प्रयोगकर्ता हाल्ने हो?"</string>
<string name="user_add_user_message_long" msgid="1527434966294733380">"तपाईं थप प्रयोगकर्ताहरू सिर्जना गरेर ती प्रयोगकर्तालाई यो डिभाइस प्रयोग गर्न दिन सक्नुहुन्छ। हरेक प्रयोगकर्ताको आफ्नै ठाउँ हुन्छ। उनीहरू यो ठाउँमा आफ्नै एप, वालपेपर आदिका लागि प्रयोग गर्न सक्छन्। उनीहरू सबैजनालाई असर पार्ने Wi-Fi जस्ता डिभाइसका सेटिङहरू पनि परिवर्तन गर्न सक्छन्।\n\nतपाईंले नयाँ प्रयोगकर्ता थप्दा उक्त व्यक्तिले आफ्नो ठाउँ सेटअप गर्नु पर्ने हुन्छ।\n\nसबै प्रयोगकर्ता अन्य सबै प्रयोगकर्ताले प्रयोग गर्ने एपहरू अद्यावधिक गर्न सक्छन्। तपाईं थप प्रयोगकर्ताहरू सिर्जना गरेर ती प्रयोगकर्तालाई यो डिभाइस प्रयोग गर्न दिन सक्नुहुन्छ। हरेक प्रयोगकर्ताको आफ्नै ठाउँ हुन्छ। उनीहरू यो ठाउँमा आफ्नै एप, वालपेपर आदिका लागि प्रयोग गर्न सक्छन्। उनीहरू सबैजनालाई असर पार्ने Wi-Fi जस्ता डिभाइसका सेटिङहरू पनि परिवर्तन गर्न सक्छन्।BREAK_0BREAK_1तपाईंले नयाँ प्रयोगकर्ता थप्दा उक्त व्यक्तिले आफ्नो ठाउँ सेटअप गर्नु पर्ने हुन्छ।BREAK_2BREAK_3सबै प्रयोगकर्ता अन्य सबै प्रयोगकर्ताले प्रयोग गर्ने एपहरू अद्यावधिक गर्न सक्छन्। तर पहुँचसम्बन्धी सेटिङ तथा सेवाहरू नयाँ प्रयोगकर्तामा नसर्न सक्छन्।"</string>
- <string name="user_add_user_message_short" msgid="3295959985795716166">"तपाईंले नयाँ प्रयोगकर्ता थप्नुभयो भने ती प्रयोगकर्ताले आफ्नो स्पेस सेट गर्नु पर्ने हुन्छ।\n\nसबै प्रयोगकर्ताले अरू प्रयोगकर्ताका एपहरू अपडेट गर्न सक्छन्।"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"तपाईंले नयाँ प्रयोगकर्ता हाल्नुभयो भने ती प्रयोगकर्ताले आफ्नो स्पेस सेट गर्नु पर्ने हुन्छ।\n\nसबै प्रयोगकर्ताले अरू प्रयोगकर्ताका एपहरू अपडेट गर्न सक्छन्।"</string>
<string name="user_grant_admin_title" msgid="5157031020083343984">"यी प्रयोगकर्तालाई एड्मिन बनाउने हो?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"एड्मिनहरूसँग अन्य प्रयोगकर्तासँग नभएका विशेषाधिकारहरू हुन्छन्। एड्मिन सबै प्रयोगकर्ताहरूलाई व्यवस्थापन गर्न, यो डिभाइस अपडेट वा रिसेट गर्न, सेटिङ परिमार्जन गर्न, इन्स्टल गरिएका सबै एपहरू हेर्न र अरूलाई एड्मिनका विशेषाधिकारहरू दिन वा अरूलाई दिइएका एड्मिनका विशेषाधिकारहरू खारेज गर्न सक्नुहुन्छ।"</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"एड्मिन बनाउनुहोस्"</string>
<string name="user_setup_dialog_title" msgid="8037342066381939995">"अहिले प्रयोगकर्ता सेटअप गर्ने हो?"</string>
- <string name="user_setup_dialog_message" msgid="269931619868102841">"यी व्यक्ति यन्त्र यो डिभाइस चलाउन र आफ्नो ठाउँ सेट गर्न उपलब्ध छन् भन्ने कुरा सुनिश्चित गर्नुहोस्"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"यी व्यक्ति यो डिभाइस चलाउन र आफ्नो ठाउँ सेट गर्न उपलब्ध छन् भन्ने कुरा सुनिश्चित गर्नुहोस्"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"अहिले प्रोफाइल सेटअप गर्ने हो?"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"अब सेटअप गर्नुहोस्"</string>
<string name="user_setup_button_setup_later" msgid="8712980133555493516">"अहिले होइन"</string>
@@ -603,8 +603,8 @@
<string name="add_user_failed" msgid="4809887794313944872">"नयाँ प्रयोगकर्ता सिर्जना गर्न सकिएन"</string>
<string name="add_guest_failed" msgid="8074548434469843443">"नयाँ अतिथि बनाउन सकिएन"</string>
<string name="user_nickname" msgid="262624187455825083">"उपनाम"</string>
- <string name="user_add_user" msgid="7876449291500212468">"प्रयोगकर्ता थप्नुहोस्"</string>
- <string name="guest_new_guest" msgid="3482026122932643557">"अतिथि थप्नुहोस्"</string>
+ <string name="user_add_user" msgid="7876449291500212468">"प्रयोगकर्ता कनेक्ट गर्नुहोस्"</string>
+ <string name="guest_new_guest" msgid="3482026122932643557">"अतिथि कनेक्ट गर्नुहोस्"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"गेस्ट मोडबाट बाहिर निस्कियोस्"</string>
<string name="guest_reset_guest" msgid="6110013010356013758">"अतिथि सत्र रिसेट गर्नुहोस्"</string>
<string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"अतिथिका रूपमा ब्राउज गर्ने सेसन रिसेट गर्ने हो?"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 80945c7..93f3461 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -585,10 +585,10 @@
<string name="user_grant_admin_title" msgid="5157031020083343984">"ଏହି ୟୁଜରଙ୍କୁ ଜଣେ ଆଡମିନ କରିବେ?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"ଆଡମିନମାନଙ୍କର ବିଶେଷ ଅଧିକାରଗୁଡ଼ିକ ଥାଏ ଯାହା ଅନ୍ୟ ୟୁଜରମାନଙ୍କର ନଥାଏ। ଜଣେ ଆଡମିନ ସମସ୍ତ ୟୁଜରଙ୍କୁ ପରିଚାଳନା କରିପାରିବେ, ଏହି ଡିଭାଇସକୁ ଅପଡେଟ କିମ୍ବା ରିସେଟ କରିପାରିବେ, ସେଟିଂସ ପରିବର୍ତ୍ତନ କରିପାରିବେ, ଇନଷ୍ଟଲ କରାଯାଇଥିବା ସମସ୍ତ ଆପ୍ସ ଦେଖିପାରିବେ ଏବଂ ଅନ୍ୟମାନଙ୍କ ପାଇଁ ଆଡମିନଙ୍କ ବିଶେଷ ଅଧିକାରଗୁଡ଼ିକୁ ଅନୁମତି ଦେଇପାରିବେ କିମ୍ବା ପ୍ରତ୍ୟାହାର କରିପାରିବେ।"</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"ଆଡମିନ କରନ୍ତୁ"</string>
- <string name="user_setup_dialog_title" msgid="8037342066381939995">"ଏବେ ଉପଯୋଗକର୍ତ୍ତା ସେଟଅପ କରିବେ?"</string>
- <string name="user_setup_dialog_message" msgid="269931619868102841">"ସୁନିଶ୍ଚିତ କରନ୍ତୁ ଯେ, ବ୍ୟକ୍ତି ଜଣକ ଡିଭାଇସ୍ ଓ ନିଜର ସ୍ଥାନ ସେଟଅପ୍ କରିବା ପାଇଁ ଉପଲବ୍ଧ ଅଛନ୍ତି।"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ଏବେ ୟୁଜର ସେଟଅପ କରିବେ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ସୁନିଶ୍ଚିତ କରନ୍ତୁ ଯେ, ବ୍ୟକ୍ତି ଜଣକ ଡିଭାଇସ ଓ ନିଜର ସ୍ଥାନ ସେଟଅପ କରିବା ପାଇଁ ଉପଲବ୍ଧ ଅଛନ୍ତି।"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ପ୍ରୋଫାଇଲ୍କୁ ଏବେ ସେଟ୍ କରିବେ?"</string>
- <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ଏବେ ସେଟଅପ୍ କରନ୍ତୁ"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ଏବେ ସେଟଅପ କରନ୍ତୁ"</string>
<string name="user_setup_button_setup_later" msgid="8712980133555493516">"ଏବେ ନୁହେଁଁ"</string>
<string name="user_add_user_type_title" msgid="551279664052914497">"ଯୋଡନ୍ତୁ"</string>
<string name="user_new_user_name" msgid="60979820612818840">"ନୂଆ ୟୁଜର"</string>
@@ -677,7 +677,7 @@
<string name="keyboard_layout_default_label" msgid="1997292217218546957">"ଡିଫଲ୍ଟ"</string>
<string name="turn_screen_on_title" msgid="3266937298097573424">"ସ୍କ୍ରିନକୁ ଚାଲୁ କରନ୍ତୁ"</string>
<string name="allow_turn_screen_on" msgid="6194845766392742639">"ସ୍କ୍ରିନକୁ ଚାଲୁ କରିବା ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
- <string name="allow_turn_screen_on_description" msgid="43834403291575164">"ସ୍କ୍ରିନକୁ ଚାଲୁ କରିବା ପାଇଁ ଏକ ଆପକୁ ଅନୁମତି ଦିଅନ୍ତୁ। ଯଦି ଅନୁମତି ଦିଆଯାଏ, ତେବେ ଆପଟି ଆପଣଙ୍କ ସ୍ପଷ୍ଟ ଇଣ୍ଟେଣ୍ଟ ବିନା ଯେ କୌଣସି ସମୟରେ ସ୍କ୍ରିନକୁ ଚାଲୁ କରିପାରେ।"</string>
+ <string name="allow_turn_screen_on_description" msgid="43834403291575164">"ସ୍କ୍ରିନକୁ ଚାଲୁ କରିବା ପାଇଁ ଏକ ଆପକୁ ଅନୁମତି ଦିଅନ୍ତୁ। ଯଦି ଅନୁମତି ଦିଆଯାଏ, ତେବେ ଆପଟି ଆପଣଙ୍କ ଏକ୍ସପ୍ଲିସିଟ ଇଣ୍ଟେଣ୍ଟ ବିନା ଯେ କୌଣସି ସମୟରେ ସ୍କ୍ରିନକୁ ଚାଲୁ କରିପାରେ।"</string>
<string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରିବା ବନ୍ଦ କରିବେ?"</string>
<string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ଯଦି ଆପଣ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରନ୍ତି କିମ୍ବା ଆଉଟପୁଟ ବଦଳାନ୍ତି, ତେବେ ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ବ୍ରଡକାଷ୍ଟ ବନ୍ଦ ହୋଇଯିବ"</string>
<string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 62f7e81..d485ccd 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -356,7 +356,7 @@
<string name="show_touches" msgid="8437666942161289025">"Pokazuj dotknięcia"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"Pokazuj potwierdzenie wizualne po dotknięciu"</string>
<string name="show_key_presses" msgid="6360141722735900214">"Wyświetl naciśnięcia klawiszy"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"Wyświetl opinie wizualne dla naciśnięć fizycznego klucza"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"Pokaż wizualną informację zwrotną po naciśnięciu fizycznego klawisza"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"Pokazuj zmiany powierzchni"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"Podświetlaj całe aktualizowane powierzchnie okien"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"Pokazuj aktualizacje widoku"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 48aa735..2ad1f48 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -382,7 +382,7 @@
<string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operações de clipe não retangulares"</string>
<string name="track_frame_time" msgid="522674651937771106">"Renderização HWUI do perfil"</string>
<string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Ativar cam. depuração GPU"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permitir carregamento de camadas de depuração de GPU p/ apps de depuração"</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite carregamento de camadas de depuração de GPU para apps de depuração"</string>
<string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Ativ. registo do fornecedor"</string>
<string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Inclua registos adicionais de fornecedores específicos de dispositivos em relatórios de erros, que podem conter informações privadas, utilizar mais bateria e/ou utilizar mais armazenamento."</string>
<string name="window_animation_scale_title" msgid="5236381298376812508">"Escala de animação de transição"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 2fdac37..79e0e087 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -268,7 +268,7 @@
<string name="mock_location_app_not_set" msgid="6972032787262831155">"Nuk është vendosur asnjë aplikacion që simulon vendndodhjen"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"Aplikacioni për simulimin e vendndodhjes: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Rrjetet"</string>
- <string name="wifi_display_certification" msgid="1805579519992520381">"Certifikimi i ekranit pa tel"</string>
+ <string name="wifi_display_certification" msgid="1805579519992520381">"Certifikimi i ekranit wireless"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Aktivizo regjistrimin Wi-Fi Verbose"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"Përshpejtimi i skanimit të Wi‑Fi"</string>
<string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Renditje e rastësishme jo e përhershme e MAC për Wi‑Fi"</string>
@@ -300,7 +300,7 @@
<string name="private_dns_mode_provider" msgid="3619040641762557028">"Emri i pritësit të ofruesit të DNS-së private"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"Fut emrin e pritësit të ofruesit të DNS-së"</string>
<string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"Nuk mund të lidhej"</string>
- <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Shfaq opsionet për certifikimin e ekranit pa tel"</string>
+ <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Shfaq opsionet për certifikimin e ekranit wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Zvogëlon shkarkimin e baterisë dhe përmirëson cilësinë e funksionimit të rrjetit"</string>
<string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Kur ky modalitet është i aktivizuar, adresa MAC e kësaj pajisjeje mund të ndryshojë çdo herë që lidhet me një rrjet që ka të aktivizuar renditjen e rastësishme të adresave MAC."</string>
@@ -356,7 +356,7 @@
<string name="show_touches" msgid="8437666942161289025">"Shfaq trokitjet"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"Shfaq reagimet vizuale për trokitjet"</string>
<string name="show_key_presses" msgid="6360141722735900214">"Shfaq shtypjet e tasteve"</string>
- <string name="show_key_presses_summary" msgid="725387457373015024">"Shfaq reagime vizuale për shtypjen e tasteve fizike"</string>
+ <string name="show_key_presses_summary" msgid="725387457373015024">"Shfaq reagim vizual për shtypjet fizike të tasteve"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"Shfaq përditësimet e sipërfaqes"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"Ndriço të gjitha sipërfaqet e dritares kur ato të përditësohen"</string>
<string name="show_hw_screen_updates" msgid="2021286231267747506">"Shfaq përditësimet e pamjes"</string>
@@ -478,7 +478,7 @@
<string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Karikim i shpejtë"</string>
<string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Po karikohet ngadalë"</string>
- <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Po karikohet pa tel"</string>
+ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Po karikohet wireless"</string>
<string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Po karikohet"</string>
<string name="battery_info_status_discharging" msgid="6962689305413556485">"Nuk po karikohet"</string>
<string name="battery_info_status_not_charging" msgid="3371084153747234837">"Lidhur, jo në karikim"</string>
@@ -585,7 +585,7 @@
<string name="user_grant_admin_title" msgid="5157031020083343984">"Të bëhet administrator ky përdorues?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"Administratorët kanë privilegje të veçanta që nuk i kanë përdoruesit e tjerë. Një administrator mund të menaxhojë të gjithë përdoruesit, të përditësojë ose të rivendosë këtë pajisje, të modifikojë cilësimet, të shikojë të gjitha aplikacionet e instaluara dhe të japë ose të revokojë privilegjet e administratorit për të tjerët."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"Bëje administrator"</string>
- <string name="user_setup_dialog_title" msgid="8037342066381939995">"Të konfig. përdoruesi tani?"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Të konfigurohet përdoruesi?"</string>
<string name="user_setup_dialog_message" msgid="269931619868102841">"Sigurohu që personi të jetë i gatshëm të marrë pajisjen dhe të caktojë hapësirën e vet"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Të konfigurohet tani profili?"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"Konfiguro tani"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index dc698ce..ae466ce 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -141,7 +141,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Откажи"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Упаривање омогућава приступ контактима и историји позива након повезивања."</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Упаривање са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g> није могуће."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Упаривање са <xliff:g id="DEVICE_NAME">%1$s</xliff:g> није могуће због нетачног PIN-а или приступног кода."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Упаривање са <xliff:g id="DEVICE_NAME">%1$s</xliff:g> није могуће због нетачног PIN-а или приступног кључа."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Није могуће комуницирати са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> је одбио/ла упаривање"</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Рачунар"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index b72c533..aa86df9 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -355,7 +355,7 @@
<string name="pointer_location_summary" msgid="957120116989798464">"திரையின் மேல் அடுக்கானது தற்போது தொடப்பட்டிருக்கும் தரவைக் காண்பிக்கிறது"</string>
<string name="show_touches" msgid="8437666942161289025">"தட்டல்களைக் காட்டு"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"தட்டல்களின் போது காட்சி அறிகுறிகளைக் காட்டும்"</string>
- <string name="show_key_presses" msgid="6360141722735900214">"பட்டன் அழுத்தத்தை காட்டவா"</string>
+ <string name="show_key_presses" msgid="6360141722735900214">"பட்டன் அழுத்தத்தை காட்டு"</string>
<string name="show_key_presses_summary" msgid="725387457373015024">"பட்டன் அழுத்தங்களைக் காட்சி மூலம் உறுதிப்படுத்தும்"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"மேலோட்ட புதுப்பிப்புகளைக் காட்டு"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"சாளரத்தின் பரப்புநிலைகள் புதுப்பிக்கப்படும்போது, அவற்றை முழுவதுமாகக் காட்டும்"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index bf297e6..b0489ab 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -355,7 +355,7 @@
<string name="pointer_location_summary" msgid="957120116989798464">"Показувати на екрані жести й натискання"</string>
<string name="show_touches" msgid="8437666942161289025">"Показувати дотики"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"Показувати візуальну реакцію на торкання"</string>
- <string name="show_key_presses" msgid="6360141722735900214">"Показувати натиск. клавіш"</string>
+ <string name="show_key_presses" msgid="6360141722735900214">"Показувати натискання клавіш"</string>
<string name="show_key_presses_summary" msgid="725387457373015024">"Показувати візуальний відгук на натискання клавіш"</string>
<string name="show_screen_updates" msgid="2078782895825535494">"Показ. оновлення поверхні"</string>
<string name="show_screen_updates_summary" msgid="2126932969682087406">"Підсвічувати вікна повністю під час оновлення"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 96e5d6a..24f838e 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -603,7 +603,7 @@
<string name="add_user_failed" msgid="4809887794313944872">"Yangi foydalanuvchi yaratilmadi"</string>
<string name="add_guest_failed" msgid="8074548434469843443">"Yangi mehmon yaratilmadi"</string>
<string name="user_nickname" msgid="262624187455825083">"Nik"</string>
- <string name="user_add_user" msgid="7876449291500212468">"Foydalanuvchi"</string>
+ <string name="user_add_user" msgid="7876449291500212468">"Foydalanuvchi kiritish"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Mehmon kiritish"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Mehmonni olib tashlash"</string>
<string name="guest_reset_guest" msgid="6110013010356013758">"Mehmon seansini tiklash"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 7035077..c63b838 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -581,7 +581,7 @@
<string name="user_add_profile_item_title" msgid="3111051717414643029">"Tiểu sử bị hạn chế"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"Thêm người dùng mới?"</string>
<string name="user_add_user_message_long" msgid="1527434966294733380">"Bạn có thể chia sẻ thiết bị này với người khác bằng cách tạo thêm người dùng. Mỗi người dùng sẽ có không gian riêng của mình. Họ có thể tùy chỉnh không gian riêng đó bằng các ứng dụng, hình nền, v.v. Người dùng cũng có thể điều chỉnh các tùy chọn cài đặt thiết bị có ảnh hưởng đến tất cả mọi người, chẳng hạn như Wi‑Fi.\n\nKhi bạn thêm người dùng mới, họ cần thiết lập không gian của mình.\n\nMọi người dùng đều có thể cập nhật ứng dụng cho tất cả người dùng khác. Các dịch vụ và các tùy chọn cài đặt hỗ trợ tiếp cận có thể không chuyển sang người dùng mới."</string>
- <string name="user_add_user_message_short" msgid="3295959985795716166">"Khi bạn thêm người dùng mới, họ cần thiết lập không gian của mình.\n\nMọi người dùng đều có thể cập nhật ứng dụng cho tất cả người dùng khác."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Khi bạn thêm người dùng mới, người đó cần thiết lập không gian của mình.\n\nMọi người dùng đều có thể cập nhật ứng dụng cho tất cả người dùng khác."</string>
<string name="user_grant_admin_title" msgid="5157031020083343984">"Đặt người dùng này làm quản trị viên?"</string>
<string name="user_grant_admin_message" msgid="1673791931033486709">"Quản trị viên có các đặc quyền mà những người dùng khác không có. Một quản trị viên có thể quản lý toàn bộ người dùng, cập nhật hoặc đặt lại thiết bị này, sửa đổi chế độ cài đặt, xem tất cả các ứng dụng đã cài đặt và cấp hoặc thu hồi đặc quyền của quản trị viên đối với những người khác."</string>
<string name="user_grant_admin_button" msgid="5441486731331725756">"Đặt làm quản trị viên"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index ab16a73..a3e2838 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -561,7 +561,7 @@
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"连接时遇到问题。请关闭并重新开启设备"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有线音频设备"</string>
<string name="help_label" msgid="3528360748637781274">"帮助和反馈"</string>
- <string name="storage_category" msgid="2287342585424631813">"存储"</string>
+ <string name="storage_category" msgid="2287342585424631813">"存储空间"</string>
<string name="shared_data_title" msgid="1017034836800864953">"共享数据"</string>
<string name="shared_data_summary" msgid="5516326713822885652">"查看和修改共享数据"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"此用户没有共享数据。"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index ceda902..898fee2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -54,6 +54,7 @@
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.stream.Stream;
/**
* CachedBluetoothDevice represents a remote Bluetooth device. It contains
@@ -652,6 +653,20 @@
return mDevice.getBatteryLevel();
}
+ /**
+ * Get the lowest battery level from remote device and its member devices
+ * @return battery level in percentage [0-100] or
+ * {@link BluetoothDevice#BATTERY_LEVEL_UNKNOWN}
+ */
+ public int getMinBatteryLevelWithMemberDevices() {
+ return Stream.concat(Stream.of(this), mMemberDevices.stream())
+ .mapToInt(cachedDevice -> cachedDevice.getBatteryLevel())
+ .filter(batteryLevel -> batteryLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN)
+ .min()
+ .orElse(BluetoothDevice.BATTERY_LEVEL_UNKNOWN);
+ }
+
+
void refresh() {
ThreadUtils.postOnBackgroundThread(() -> {
if (BluetoothUtils.isAdvancedDetailsHeader(mDevice)) {
@@ -1147,7 +1162,7 @@
// BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF, or BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
// any other value should be a framework bug. Thus assume here that if value is greater
// than BluetoothDevice.BATTERY_LEVEL_UNKNOWN, it must be valid
- final int batteryLevel = getBatteryLevel();
+ final int batteryLevel = getMinBatteryLevelWithMemberDevices();
if (batteryLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
// TODO: name com.android.settingslib.bluetooth.Utils something different
batteryLevelPercentageString =
@@ -1322,7 +1337,7 @@
// BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF, or BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
// any other value should be a framework bug. Thus assume here that if value is greater
// than BluetoothDevice.BATTERY_LEVEL_UNKNOWN, it must be valid
- final int batteryLevel = getBatteryLevel();
+ final int batteryLevel = getMinBatteryLevelWithMemberDevices();
if (batteryLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
// TODO: name com.android.settingslib.bluetooth.Utils something different
batteryLevelPercentageString =
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 4b61ff1..85efe69 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -529,6 +529,51 @@
}
@Test
+ public void getConnectionSummary_testMemberDevicesExist_returnMinBattery() {
+ // One device is active with battery level 70.
+ mBatteryLevel = 70;
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+
+
+ // Add a member device with battery level 30.
+ int lowerBatteryLevel = 30;
+ mCachedDevice.addMemberDevice(mSubCachedDevice);
+ doAnswer((invocation) -> lowerBatteryLevel).when(mSubCachedDevice).getBatteryLevel();
+
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, 30% battery");
+ }
+
+ @Test
+ public void getConnectionSummary_testMemberDevicesBatteryUnknown_returnMinBattery() {
+ // One device is active with battery level 70.
+ mBatteryLevel = 70;
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+
+ // Add a member device with battery level unknown.
+ mCachedDevice.addMemberDevice(mSubCachedDevice);
+ doAnswer((invocation) -> BluetoothDevice.BATTERY_LEVEL_UNKNOWN).when(
+ mSubCachedDevice).getBatteryLevel();
+
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, 70% battery");
+ }
+
+ @Test
+ public void getConnectionSummary_testAllDevicesBatteryUnknown_returnNoBattery() {
+ // One device is active with battery level unknown.
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+
+ // Add a member device with battery level unknown.
+ mCachedDevice.addMemberDevice(mSubCachedDevice);
+ doAnswer((invocation) -> BluetoothDevice.BATTERY_LEVEL_UNKNOWN).when(
+ mSubCachedDevice).getBatteryLevel();
+
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
+ }
+
+ @Test
public void getConnectionSummary_testMultipleProfilesActiveDevice() {
// Test without battery level
// Set A2DP and HFP profiles to be connected and test connection state summary
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 2086466..a8063e8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -35,6 +35,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -52,6 +53,7 @@
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
+import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -69,6 +71,8 @@
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.Arrays;
@@ -88,6 +92,10 @@
private UserManager mUserManager;
@Mock
private ContentResolver mContentResolver;
+ @Mock
+ private Context mUserContext;
+ @Mock
+ private ContentResolver mUserContentResolver;
private static final String URI_GET_SUMMARY = "content://authority/text/summary";
private static final String URI_GET_ICON = "content://authority/icon/my_icon";
@@ -104,6 +112,8 @@
mContentResolver = spy(application.getContentResolver());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getPackageName()).thenReturn("com.android.settings");
+ when(mUserContext.getContentResolver()).thenReturn(mUserContentResolver);
+ ShadowTileUtils.sCallRealEntryDataFromProvider = false;
}
@Test
@@ -375,6 +385,30 @@
}
@Test
+ public void loadTilesForAction_forUserProvider_getEntryDataFromProvider_inContextOfGivenUser() {
+ ShadowTileUtils.sCallRealEntryDataFromProvider = true;
+ UserHandle userHandle = new UserHandle(10);
+
+ doReturn(mUserContext).when(mContext).createContextAsUser(eq(userHandle), anyInt());
+
+ Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+ List<Tile> outTiles = new ArrayList<>();
+ List<ResolveInfo> info = new ArrayList<>();
+ ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+ URI_GET_SUMMARY, null, 123, PROFILE_ALL);
+ info.add(resolveInfo);
+
+ when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
+ anyInt())).thenReturn(info);
+
+ TileUtils.loadTilesForAction(mContext, userHandle, IA_SETTINGS_ACTION,
+ addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
+
+ verify(mUserContentResolver, atLeastOnce())
+ .acquireUnstableProvider(any(Uri.class));
+ }
+
+ @Test
public void loadTilesForAction_withPendingIntent_updatesPendingIntentMap() {
Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
List<Tile> outTiles = new ArrayList<>();
@@ -472,8 +506,17 @@
private static Bundle sMetaData;
+ private static boolean sCallRealEntryDataFromProvider;
+
@Implementation
protected static List<Bundle> getEntryDataFromProvider(Context context, String authority) {
+ if (sCallRealEntryDataFromProvider) {
+ return Shadow.directlyOn(
+ TileUtils.class,
+ "getEntryDataFromProvider",
+ ReflectionHelpers.ClassParameter.from(Context.class, context),
+ ReflectionHelpers.ClassParameter.from(String.class, authority));
+ }
return Arrays.asList(sMetaData);
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index c2dbf98..be63021 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -241,6 +241,7 @@
Settings.Secure.HEARING_AID_MEDIA_ROUTING,
Settings.Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED,
- Settings.Secure.SEARCH_PRESS_HOLD_NAV_HANDLE_ENABLED
+ Settings.Secure.SEARCH_PRESS_HOLD_NAV_HANDLE_ENABLED,
+ Settings.Secure.SEARCH_LONG_PRESS_HOME_ENABLED
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 6b0a906..248c60c 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -61,7 +61,7 @@
Settings.System.TTY_MODE,
Settings.System.MASTER_MONO,
Settings.System.MASTER_BALANCE,
- Settings.System.STAY_AWAKE_ON_FOLD,
+ Settings.System.FOLD_LOCK_BEHAVIOR,
Settings.System.SOUND_EFFECTS_ENABLED,
Settings.System.HAPTIC_FEEDBACK_ENABLED,
Settings.System.POWER_SOUNDS_ENABLED, // moved to global
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index a49461e..ff32bad 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -199,6 +199,7 @@
VALIDATORS.put(Secure.ASSIST_TOUCH_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ASSIST_LONG_PRESS_HOME_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.SEARCH_PRESS_HOLD_NAV_HANDLE_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.SEARCH_LONG_PRESS_HOME_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.VR_DISPLAY_MODE, new DiscreteValueValidator(new String[] {"0", "1"}));
VALIDATORS.put(Secure.NOTIFICATION_BADGING, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.NOTIFICATION_DISMISS_RTL, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index a08d07e..3688d04 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -134,6 +134,7 @@
VALIDATORS.put(System.HAPTIC_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.RINGTONE, URI_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_SOUND, URI_VALIDATOR);
+ VALIDATORS.put(System.FOLD_LOCK_BEHAVIOR, ANY_STRING_VALIDATOR);
VALIDATORS.put(System.ALARM_ALERT, URI_VALIDATOR);
VALIDATORS.put(System.TEXT_AUTO_REPLACE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.TEXT_AUTO_CAPS, BOOLEAN_VALIDATOR);
@@ -218,7 +219,6 @@
VALIDATORS.put(System.WIFI_STATIC_DNS1, LENIENT_IP_ADDRESS_VALIDATOR);
VALIDATORS.put(System.WIFI_STATIC_DNS2, LENIENT_IP_ADDRESS_VALIDATOR);
VALIDATORS.put(System.SHOW_BATTERY_PERCENT, BOOLEAN_VALIDATOR);
- VALIDATORS.put(System.STAY_AWAKE_ON_FOLD, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.CLOCKWORK_BLUETOOTH_SETTINGS_PREF, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index ef4e84f..5c67295 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1929,6 +1929,9 @@
dumpSetting(s, p,
Settings.Secure.SEARCH_PRESS_HOLD_NAV_HANDLE_ENABLED,
SecureSettingsProto.Assist.SEARCH_PRESS_HOLD_NAV_HANDLE_ENABLED);
+ dumpSetting(s, p,
+ Settings.Secure.SEARCH_LONG_PRESS_HOME_ENABLED,
+ SecureSettingsProto.Assist.SEARCH_LONG_PRESS_HOME_ENABLED);
p.end(assistToken);
final long assistHandlesToken = p.start(SecureSettingsProto.ASSIST_HANDLES);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index e3153e0..0a98032 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -94,6 +94,7 @@
static final int SETTINGS_VERSION_NEW_ENCODING = 121;
+ public static final int MAX_LENGTH_PER_STRING = 32768;
private static final long WRITE_SETTINGS_DELAY_MILLIS = 200;
private static final long MAX_WRITE_SETTINGS_DELAY_MILLIS = 2000;
@@ -430,6 +431,19 @@
return false;
}
+ final boolean isNameTooLong = name.length() > SettingsState.MAX_LENGTH_PER_STRING;
+ final boolean isValueTooLong =
+ value != null && value.length() > SettingsState.MAX_LENGTH_PER_STRING;
+ if (isNameTooLong || isValueTooLong) {
+ // only print the first few bytes of the name in case it is long
+ final String errorMessage = "The " + (isNameTooLong ? "name" : "value")
+ + " of your setting ["
+ + (name.length() > 20 ? (name.substring(0, 20) + "...") : name)
+ + "] is too long. The max length allowed for the string is "
+ + MAX_LENGTH_PER_STRING + ".";
+ throw new IllegalArgumentException(errorMessage);
+ }
+
Setting oldState = mSettings.get(name);
String oldValue = (oldState != null) ? oldState.value : null;
String oldDefaultValue = (oldState != null) ? oldState.defaultValue : null;
@@ -831,6 +845,7 @@
private void doWriteState() {
boolean wroteState = false;
+ String settingFailedToBePersisted = null;
final int version;
final ArrayMap<String, Setting> settings;
final ArrayMap<String, String> namespaceBannedHashes;
@@ -860,7 +875,6 @@
final int settingCount = settings.size();
for (int i = 0; i < settingCount; i++) {
-
Setting setting = settings.valueAt(i);
if (setting.isTransient()) {
if (DEBUG_PERSISTENCE) {
@@ -869,14 +883,27 @@
continue;
}
- if (writeSingleSetting(mVersion, serializer, setting.getId(), setting.getName(),
- setting.getValue(), setting.getDefaultValue(), setting.getPackageName(),
- setting.getTag(), setting.isDefaultFromSystem(),
- setting.isValuePreservedInRestore())) {
- if (DEBUG_PERSISTENCE) {
- Slog.i(LOG_TAG, "[PERSISTED]" + setting.getName() + "="
- + setting.getValue());
+ try {
+ if (writeSingleSetting(mVersion, serializer, setting.getId(),
+ setting.getName(),
+ setting.getValue(), setting.getDefaultValue(),
+ setting.getPackageName(),
+ setting.getTag(), setting.isDefaultFromSystem(),
+ setting.isValuePreservedInRestore())) {
+ if (DEBUG_PERSISTENCE) {
+ Slog.i(LOG_TAG, "[PERSISTED]" + setting.getName() + "="
+ + setting.getValue());
+ }
}
+ } catch (IOException ex) {
+ Slog.e(LOG_TAG, "[ABORT PERSISTING]" + setting.getName()
+ + " due to error writing to disk", ex);
+ // A setting failed to be written. Abort the serialization to avoid leaving
+ // a partially serialized setting on disk, which can cause parsing errors.
+ // Note down the problematic setting, so that we can delete it before trying
+ // again to persist the rest of the settings.
+ settingFailedToBePersisted = setting.getName();
+ throw ex;
}
}
serializer.endTag(null, TAG_SETTINGS);
@@ -902,14 +929,14 @@
Slog.i(LOG_TAG, "[PERSIST END]");
}
} catch (Throwable t) {
- Slog.wtf(LOG_TAG, "Failed to write settings, restoring backup", t);
+ Slog.wtf(LOG_TAG, "Failed to write settings, restoring old file", t);
if (t instanceof IOException) {
- if (DEBUG) {
- // we failed to create a directory, so log the permissions and existence
- // state for the settings file and directory
- logSettingsDirectoryInformation(destination.getBaseFile());
- }
if (t.getMessage().contains("Couldn't create directory")) {
+ if (DEBUG) {
+ // we failed to create a directory, so log the permissions and existence
+ // state for the settings file and directory
+ logSettingsDirectoryInformation(destination.getBaseFile());
+ }
// attempt to create the directory with Files.createDirectories, which
// throws more informative errors than File.mkdirs.
Path parentPath = destination.getBaseFile().getParentFile().toPath();
@@ -930,7 +957,15 @@
}
}
- if (wroteState) {
+ if (!wroteState) {
+ if (settingFailedToBePersisted != null) {
+ synchronized (mLock) {
+ // Delete the problematic setting. This will schedule a write as well.
+ deleteSettingLocked(settingFailedToBePersisted);
+ }
+ }
+ } else {
+ // success
synchronized (mLock) {
addHistoricalOperationLocked(HISTORICAL_OPERATION_PERSIST, null);
}
@@ -1090,7 +1125,10 @@
} catch (FileNotFoundException fnfe) {
final String message = "No fallback file found for: " + mStatePersistFile;
Slog.wtf(LOG_TAG, message);
- throw new IllegalStateException(message);
+ if (!isConfigSettingsKey(mKey)) {
+ // Allow partially deserialized config settings because they can be updated later
+ throw new IllegalStateException(message);
+ }
}
if (parseStateFromXmlStreamLocked(in)) {
// Parsed state from fallback file. Restore original file with fallback file
@@ -1102,7 +1140,10 @@
} else {
final String message = "Failed parsing settings file: " + mStatePersistFile;
Slog.wtf(LOG_TAG, message);
- throw new IllegalStateException(message);
+ if (!isConfigSettingsKey(mKey)) {
+ // Allow partially deserialized config settings because they can be updated later
+ throw new IllegalStateException(message);
+ }
}
}
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
index 55160fb..26cac37 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
@@ -31,21 +31,21 @@
public class SettingsStateTest extends AndroidTestCase {
public static final String CRAZY_STRING =
"\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\n\u000b\u000c\r" +
- "\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a" +
- "\u001b\u001c\u001d\u001e\u001f\u0020" +
- "fake_setting_value_1" +
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
- "\u1000 \u2000 \u5000 \u8000 \uc000 \ue000" +
- "\ud800\udc00\udbff\udfff" + // surrogate pairs
- "\uD800ab\uDC00 " + // broken surrogate pairs
- "日本語";
+ "\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a" +
+ "\u001b\u001c\u001d\u001e\u001f\u0020" +
+ "fake_setting_value_1" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "\u1000 \u2000 \u5000 \u8000 \uc000 \ue000" +
+ "\ud800\udc00\udbff\udfff" + // surrogate pairs
+ "\uD800ab\uDC00 " + // broken surrogate pairs
+ "日本語";
private static final String TEST_PACKAGE = "package";
private static final String SYSTEM_PACKAGE = "android";
@@ -170,11 +170,11 @@
final PrintStream os = new PrintStream(new FileOutputStream(file));
os.print(
"<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>" +
- "<settings version=\"120\">" +
- " <setting id=\"0\" name=\"k0\" value=\"null\" package=\"null\" />" +
- " <setting id=\"1\" name=\"k1\" value=\"\" package=\"\" />" +
- " <setting id=\"2\" name=\"k2\" value=\"v2\" package=\"p2\" />" +
- "</settings>");
+ "<settings version=\"120\">" +
+ " <setting id=\"0\" name=\"k0\" value=\"null\" package=\"null\" />" +
+ " <setting id=\"1\" name=\"k1\" value=\"\" package=\"\" />" +
+ " <setting id=\"2\" name=\"k2\" value=\"v2\" package=\"p2\" />" +
+ "</settings>");
os.close();
final SettingsState ss = new SettingsState(getContext(), lock, file, 1,
@@ -408,4 +408,50 @@
}
assertEquals(expectedMemUsage, settingsState.getMemoryUsage(TEST_PACKAGE));
}
+
+ public void testLargeSettingKey() {
+ SettingsState settingsState = new SettingsState(getContext(), mLock, mSettingsFile, 1,
+ SettingsState.MAX_BYTES_PER_APP_PACKAGE_LIMITED, Looper.getMainLooper());
+ final String largeKey = Strings.repeat("A", SettingsState.MAX_LENGTH_PER_STRING + 1);
+ final String testValue = "testValue";
+ synchronized (mLock) {
+ // Test system package
+ try {
+ settingsState.insertSettingLocked(largeKey, testValue, null, true, SYSTEM_PACKAGE);
+ fail("Should throw because it exceeded max string length");
+ } catch (IllegalArgumentException ex) {
+ assertTrue(ex.getMessage().contains("The max length allowed for the string is "));
+ }
+ // Test non system package
+ try {
+ settingsState.insertSettingLocked(largeKey, testValue, null, true, TEST_PACKAGE);
+ fail("Should throw because it exceeded max string length");
+ } catch (IllegalArgumentException ex) {
+ assertTrue(ex.getMessage().contains("The max length allowed for the string is "));
+ }
+ }
+ }
+
+ public void testLargeSettingValue() {
+ SettingsState settingsState = new SettingsState(getContext(), mLock, mSettingsFile, 1,
+ SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper());
+ final String testKey = "testKey";
+ final String largeValue = Strings.repeat("A", SettingsState.MAX_LENGTH_PER_STRING + 1);
+ synchronized (mLock) {
+ // Test system package
+ try {
+ settingsState.insertSettingLocked(testKey, largeValue, null, true, SYSTEM_PACKAGE);
+ fail("Should throw because it exceeded max string length");
+ } catch (IllegalArgumentException ex) {
+ assertTrue(ex.getMessage().contains("The max length allowed for the string is "));
+ }
+ // Test non system package
+ try {
+ settingsState.insertSettingLocked(testKey, largeValue, null, true, TEST_PACKAGE);
+ fail("Should throw because it exceeded max string length");
+ } catch (IllegalArgumentException ex) {
+ assertTrue(ex.getMessage().contains("The max length allowed for the string is "));
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index b708fc2..285fc5f1 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -6,6 +6,7 @@
aaliomer@google.com
aaronjli@google.com
+achalke@google.com
acul@google.com
adamcohen@google.com
aioana@google.com
@@ -70,6 +71,7 @@
patmanning@google.com
peanutbutter@google.com
peskal@google.com
+petrcermak@google.com
pinyaoting@google.com
pixel@google.com
pomini@google.com
@@ -81,13 +83,17 @@
shanh@google.com
snoeberger@google.com
steell@google.com
+stevenckng@google.com
stwu@google.com
syeonlee@google.com
sunnygoyal@google.com
thiruram@google.com
+tkachenkoi@google.com
tracyzhou@google.com
tsuji@google.com
twickham@google.com
+vadimt@google.com
+vanjan@google.com
victortulias@google.com
winsonc@google.com
wleshner@google.com
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-kn/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-kn/strings.xml
index 5d1f722..0480a2e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-kn/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-kn/strings.xml
@@ -11,7 +11,7 @@
<string name="recent_apps_label" msgid="6583276995616385847">"ಇತ್ತೀಚಿನ ಅಪ್ಲಿಕೇಶನ್ಗಳು"</string>
<string name="lockscreen_label" msgid="648347953557887087">"ಲಾಕ್ ಸ್ಕ್ರೀನ್"</string>
<string name="quick_settings_label" msgid="2999117381487601865">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
- <string name="notifications_label" msgid="6829741046963013567">"ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="notifications_label" msgid="6829741046963013567">"ನೋಟಿಫಿಕೇಶನ್ಗಳು"</string>
<string name="screenshot_label" msgid="863978141223970162">"ಸ್ಕ್ರೀನ್ಶಾಟ್"</string>
<string name="screenshot_utterance" msgid="1430760563401895074">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
<string name="volume_up_label" msgid="8592766918780362870">"ವಾಲ್ಯೂಮ್ ಜಾಸ್ತಿ"</string>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 764a855..a95ab55 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -24,6 +24,7 @@
import android.graphics.Path
import android.graphics.Rect
import android.graphics.RectF
+import android.os.Build
import android.os.Looper
import android.os.RemoteException
import android.util.Log
@@ -88,6 +89,9 @@
contentAfterFadeInInterpolator = PathInterpolator(0f, 0f, 0.6f, 1f)
)
+ // TODO(b/288507023): Remove this flag.
+ @JvmField val DEBUG_LAUNCH_ANIMATION = Build.IS_DEBUGGABLE
+
private val DEFAULT_LAUNCH_ANIMATOR = LaunchAnimator(TIMINGS, INTERPOLATORS)
private val DEFAULT_DIALOG_TO_APP_ANIMATOR = LaunchAnimator(DIALOG_TIMINGS, INTERPOLATORS)
@@ -240,8 +244,17 @@
private fun Controller.callOnIntentStartedOnMainThread(willAnimate: Boolean) {
if (Looper.myLooper() != Looper.getMainLooper()) {
- this.launchContainer.context.mainExecutor.execute { this.onIntentStarted(willAnimate) }
+ this.launchContainer.context.mainExecutor.execute {
+ callOnIntentStartedOnMainThread(willAnimate)
+ }
} else {
+ if (DEBUG_LAUNCH_ANIMATION) {
+ Log.d(
+ TAG,
+ "Calling controller.onIntentStarted(willAnimate=$willAnimate) " +
+ "[controller=$this]"
+ )
+ }
this.onIntentStarted(willAnimate)
}
}
@@ -542,6 +555,13 @@
Log.i(TAG, "Aborting the animation as no window is opening")
removeTimeout()
iCallback?.invoke()
+
+ if (DEBUG_LAUNCH_ANIMATION) {
+ Log.d(
+ TAG,
+ "Calling controller.onLaunchAnimationCancelled() [no window opening]"
+ )
+ }
controller.onLaunchAnimationCancelled()
return
}
@@ -759,6 +779,10 @@
Log.i(TAG, "Remote animation timed out")
timedOut = true
+
+ if (DEBUG_LAUNCH_ANIMATION) {
+ Log.d(TAG, "Calling controller.onLaunchAnimationCancelled() [animation timed out]")
+ }
controller.onLaunchAnimationCancelled()
}
@@ -773,6 +797,13 @@
removeTimeout()
animation?.cancel()
+
+ if (DEBUG_LAUNCH_ANIMATION) {
+ Log.d(
+ TAG,
+ "Calling controller.onLaunchAnimationCancelled() [remote animation cancelled]",
+ )
+ }
controller.onLaunchAnimationCancelled()
}
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index 31df2ba..2d5796e 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -303,7 +303,6 @@
-packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index 84f7bb5..ce53b7e 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -28,7 +28,7 @@
<string name="keyguard_enter_password" msgid="6483623792371009758">"Fut fjalëkalimin"</string>
<string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Karta e pavlefshme."</string>
<string name="keyguard_charged" msgid="5478247181205188995">"I karikuar"</string>
- <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me valë"</string>
+ <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet në mënyrë wireless"</string>
<string name="keyguard_plugged_in_dock" msgid="2122073051904360987">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string>
<string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
@@ -41,7 +41,7 @@
<string name="keyguard_missing_sim_instructions" msgid="7735360104844653246">"Shto një kartë SIM."</string>
<string name="keyguard_missing_sim_instructions_long" msgid="3451467338947610268">"Karta SIM mungon ose është e palexueshme. Shto një kartë SIM."</string>
<string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Kartë SIM e papërdorshme."</string>
- <string name="keyguard_permanent_disabled_sim_instructions" msgid="5034635040020685428">"Karta jote SIM është çaktivizuar përgjithmonë.\n Kontakto me ofruesin e shërbimit me valë për një kartë tjetër SIM."</string>
+ <string name="keyguard_permanent_disabled_sim_instructions" msgid="5034635040020685428">"Karta jote SIM është çaktivizuar përgjithmonë.\n Kontakto me ofruesin e shërbimit wireless për një tjetër kartë SIM."</string>
<string name="keyguard_sim_locked_message" msgid="7095293254587575270">"Karta SIM është e kyçur."</string>
<string name="keyguard_sim_puk_locked_message" msgid="2503428315518592542">"Karta SIM është e kyçur me PUK."</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="8489092646014631659">"Karta SIM po shkyçet…"</string>
diff --git a/packages/SystemUI/res-product/values-sq/strings.xml b/packages/SystemUI/res-product/values-sq/strings.xml
index 619f22f..f7421c1 100644
--- a/packages/SystemUI/res-product/values-sq/strings.xml
+++ b/packages/SystemUI/res-product/values-sq/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="dock_alignment_slow_charging" product="default" msgid="6997633396534416792">"Drejtvendose përsëri telefonin për karikim më të shpejtë"</string>
- <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Drejtvendose përsëri telefonin për ta karikuar me valë"</string>
+ <string name="dock_alignment_not_charging" product="default" msgid="3980752926226749808">"Drejtvendose përsëri telefonin për karikim wireless"</string>
<string name="inattentive_sleep_warning_message" product="tv" msgid="6844464574089665063">"Pajisja Android TV së shpejti do të fiket. Shtyp një buton për ta mbajtur të ndezur."</string>
<string name="inattentive_sleep_warning_message" product="default" msgid="5693904520452332224">"Pajisja së shpejti do të fiket. Shtype për ta mbajtur të ndezur."</string>
<string name="keyguard_missing_sim_message" product="tablet" msgid="408124574073032188">"Nuk ka kartë SIM në tablet."</string>
diff --git a/packages/SystemUI/res/layout/battery_percentage_view.xml b/packages/SystemUI/res/layout/battery_percentage_view.xml
index 82facd0..8b5aeaa 100644
--- a/packages/SystemUI/res/layout/battery_percentage_view.xml
+++ b/packages/SystemUI/res/layout/battery_percentage_view.xml
@@ -27,4 +27,5 @@
android:gravity="center_vertical|start"
android:paddingStart="@dimen/battery_level_padding_start"
android:importantForAccessibility="no"
+ android:includeFontPadding="false"
/>
diff --git a/packages/SystemUI/res/layout/battery_status_chip.xml b/packages/SystemUI/res/layout/battery_status_chip.xml
index ff68ac0..7437183 100644
--- a/packages/SystemUI/res/layout/battery_status_chip.xml
+++ b/packages/SystemUI/res/layout/battery_status_chip.xml
@@ -25,7 +25,8 @@
<LinearLayout
android:id="@+id/rounded_container"
android:layout_width="wrap_content"
- android:layout_height="@dimen/ongoing_appops_chip_height"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/ongoing_appops_chip_height"
android:layout_gravity="center"
android:background="@drawable/statusbar_chip_bg"
android:clipToOutline="true"
@@ -36,7 +37,7 @@
<com.android.systemui.battery.BatteryMeterView
android:id="@+id/battery_meter_view"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/media_projection_app_selector.xml b/packages/SystemUI/res/layout/media_projection_app_selector.xml
index e474938..b77f78d 100644
--- a/packages/SystemUI/res/layout/media_projection_app_selector.xml
+++ b/packages/SystemUI/res/layout/media_projection_app_selector.xml
@@ -20,10 +20,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
- androidprv:maxCollapsedHeight="0dp"
+ androidprv:maxCollapsedHeight="10000dp"
androidprv:maxCollapsedHeightSmall="56dp"
androidprv:maxWidth="@*android:dimen/chooser_width"
android:id="@*android:id/contentPanel">
+ <!-- maxCollapsedHeight above is huge, to make sure the layout is always expanded. -->
<LinearLayout
android:id="@*android:id/chooser_header"
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 5132e57..c5351b1 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -79,6 +79,7 @@
android:id="@+id/status_bar_start_side_except_heads_up"
android:layout_height="wrap_content"
android:layout_width="match_parent"
+ android:layout_gravity="center_vertical|start"
android:clipChildren="false">
<ViewStub
android:id="@+id/operator_name"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 6f68580..25aaead 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Skuif af"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Beweeg links"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Beweeg regs"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Vergrotingwisselaar"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Vergroot die hele skerm"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Vergroot \'n deel van die skerm"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index ebc9dd5..c7a8c09 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"ወደ ታች ውሰድ"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ወደ ግራ ውሰድ"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"ወደ ቀኝ ውሰድ"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"የማጉላት ማብሪያ/ማጥፊያ"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ሙሉ ገፅ እይታን ያጉሉ"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"የማያ ገጹን ክፍል አጉላ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 5412e53..1a7c195 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"نقل للأسفل"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"نقل لليسار"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"نقل لليمين"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"مفتاح تبديل وضع التكبير"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"تكبير الشاشة كلها"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"تكبير جزء من الشاشة"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index ccfdf87..c7d06dd 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"তললৈ নিয়ক"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"বাওঁফাললৈ নিয়ক"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"সোঁফাললৈ নিয়ক"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"বিবৰ্ধনৰ ছুইচ"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"পূৰ্ণ স্ক্ৰীন বিবৰ্ধন কৰক"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"স্ক্ৰীনৰ কিছু অংশ বিবৰ্ধন কৰক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 8d3e215..321a588 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Aşağı köçürün"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Sola köçürün"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Sağa köçürün"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Böyütmə dəyişdiricisi"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Tam ekranı böyüdün"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekran hissəsinin böyüdülməsi"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index a115d7d..c41cad5 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Pomerite nadole"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Pomerite nalevo"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Pomerite nadesno"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Prelazak na drugi režim uvećanja"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Uvećajte ceo ekran"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Uvećajte deo ekrana"</string>
@@ -1180,10 +1188,10 @@
<string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Upravljaj pristupom"</string>
<string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Koristi telefonski poziv"</string>
<string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Nedavno korišćeno u telefonskom pozivu"</string>
- <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Koristi <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Koriste <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Koristi <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
+ <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Koriste <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
- <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Koristi <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
+ <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Koriste <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
<string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index a8dd1a5..b1ae529 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Перамясціць ніжэй"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Перамясціць улева"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Перамясціць управа"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Пераключальнік павелічэння"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Павялічыць увесь экран"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Павялічыць частку экрана"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 5b567dd..ccf9f07 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Преместване надолу"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Преместване наляво"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Преместване надясно"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Превключване на увеличението"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Увеличаване на целия екран"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увеличаване на част от екрана"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 9d2d9e8..6d13274 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"নিচে নামান"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"বাঁদিকে সরান"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"ডানদিকে সরান"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"বড় করে দেখার সুইচ"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"সম্পূর্ণ স্ক্রিন বড় করে দেখা"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"স্ক্রিনের কিছুটা অংশ বড় করুন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index fa17ef9..8f0a0c2 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Pomjeranje prema dolje"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Pomjeranje lijevo"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Pomjeranje desno"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Prekidač za uvećavanje"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Uvećavanje prikaza preko cijelog ekrana"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Uvećavanje dijela ekrana"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 65a3709..c53bb89 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mou cap avall"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mou cap a l\'esquerra"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mou cap a la dreta"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Canvia al mode d\'ampliació"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Amplia la pantalla completa"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Amplia una part de la pantalla"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 39e7296..1c5eac1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -111,7 +111,7 @@
<string name="screenrecord_continue" msgid="4055347133700593164">"Začít"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Nahrávání obrazovky"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Nahrávání obrazovky a zvuku"</string>
- <string name="screenrecord_taps_label" msgid="1595690528298857649">"Zobrazovat klepnutí na obrazovku"</string>
+ <string name="screenrecord_taps_label" msgid="1595690528298857649">"Zobrazovat klepnutí na displej"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Zastavit"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Sdílet"</string>
<string name="screenrecord_save_title" msgid="1886652605520893850">"Nahrávka obrazovky se uložila"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Přesunout dolů"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Přesunout doleva"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Přesunout doprava"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Přepínač zvětšení"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Zvětšit celou obrazovku"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zvětšit část obrazovky"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 957e7855..fc7b654 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -172,12 +172,12 @@
<string name="biometric_re_enroll_dialog_confirm" msgid="3049858021857801836">"Konfigurer"</string>
<string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"Ikke nu"</string>
<string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"Dette er påkrævet for at forbedre sikkerheden og ydeevnen"</string>
- <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Konfigurer oplåsning med fingeraftryk igen"</string>
- <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Oplåsning med fingeraftryk"</string>
- <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Konfigurer oplåsning med fingeraftryk"</string>
- <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Hvis du vil konfigurere oplåsning med fingeraftryk igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere oplåsning med fingeraftryk igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string>
- <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Hvis du vil konfigurere oplåsning med fingeraftryk igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere oplåsning med fingeraftryk igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string>
- <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Oplåsning med fingeraftryk kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string>
+ <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Konfigurer fingeroplåsning igen"</string>
+ <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Fingeroplåsning"</string>
+ <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Konfigurer fingeroplåsning"</string>
+ <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Hvis du vil konfigurere fingeroplåsning igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere fingeroplåsning igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string>
+ <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Hvis du vil konfigurere fingeroplåsning igen, bliver dine nuværende fingeraftryksbilleder og -modeller slettet.\n\nNår de er slettet, skal du konfigurere fingeroplåsning igen for at bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet."</string>
+ <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Fingeroplåsning kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string>
<string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Konfigurer ansigtsoplåsning igen"</string>
<string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Ansigtsoplåsning"</string>
<string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Konfigurer ansigtsoplåsning"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Flyt ned"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Flyt til venstre"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Flyt til højre"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Skift forstørrelsestilstand"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Forstør hele skærmen"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Forstør en del af skærmen"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 56177ba..70b1ef5 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Nach unten bewegen"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Nach links bewegen"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Nach rechts bewegen"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Vergrößerungsschalter"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ganzen Bildschirm vergrößern"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Teil des Bildschirms vergrößern"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 7b85ac8..a029d0c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Μετακίνηση κάτω"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Μετακίνηση αριστερά"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Μετακίνηση δεξιά"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Εναλλαγή μεγιστοποίησης"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Μεγέθυνση πλήρους οθόνης"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Μεγέθυνση μέρους της οθόνης"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 83f76c6..61f7b50 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index f434bd3..ad17b3d 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -861,6 +861,10 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <string name="accessibility_control_increase_window_width" msgid="6992249470832493283">"Increase width of magnifier"</string>
+ <string name="accessibility_control_decrease_window_width" msgid="5740401560105929681">"Decrease width of magnifier"</string>
+ <string name="accessibility_control_increase_window_height" msgid="2200966116612324260">"Increase height of magnifier"</string>
+ <string name="accessibility_control_decrease_window_height" msgid="2054479949445332761">"Decrease height of magnifier"</string>
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 83f76c6..61f7b50 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 83f76c6..61f7b50 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 7851dad..e17acfd 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -861,6 +861,10 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
+ <string name="accessibility_control_increase_window_width" msgid="6992249470832493283">"Increase width of magnifier"</string>
+ <string name="accessibility_control_decrease_window_width" msgid="5740401560105929681">"Decrease width of magnifier"</string>
+ <string name="accessibility_control_increase_window_height" msgid="2200966116612324260">"Increase height of magnifier"</string>
+ <string name="accessibility_control_decrease_window_height" msgid="2054479949445332761">"Decrease height of magnifier"</string>
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Magnification switch"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index bdc406a..f6a45bf 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover hacia abajo"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover hacia la izquierda"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover hacia la derecha"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Interruptor de ampliación"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 93093a9..d61f09d 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover hacia abajo"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover hacia la izquierda"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover hacia la derecha"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Botón para cambiar el modo de ampliación"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 9bb3c03..e9b1769 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Teisalda alla"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Teisalda vasakule"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Teisalda paremale"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Suurenduse lüliti"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Täisekraani suurendamine"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekraanikuva osa suurendamine"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 5d32c00..c524d1c 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Eraman behera"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Eraman ezkerrera"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Eraman eskuinera"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Lupa aplikatzeko botoia"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Handitu pantaila osoa"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Handitu pantailaren zati bat"</string>
@@ -1078,7 +1086,7 @@
<string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Oraingoz ez da automatikoki konektatuko wifira"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Ikusi guztiak"</string>
<string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Sarea aldatzeko, deskonektatu Etherneta"</string>
- <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Gailuaren funtzionamendua hobetzeko, aplikazioek eta zerbitzuek wifi-sareak bilatzen jarraituko dute, baita wifi-konexioa desaktibatuta dagoenean ere. Aukera hori aldatzeko, joan wifi-sareen bilaketaren ezarpenetara. "<annotation id="link">"Aldatu"</annotation></string>
+ <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Gailuaren funtzionamendua hobetzeko, aplikazioek eta zerbitzuek wifi-sareak bilatzen jarraituko dute, baita wifi-konexioa desaktibatuta dagoenean ere. Aukera hori aldatzeko, joan wifi-sareak bilatzeko eginbidearen ezarpenetara. "<annotation id="link">"Aldatu"</annotation></string>
<string name="turn_off_airplane_mode" msgid="8425587763226548579">"Desaktibatu hegaldi modua"</string>
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioak lauza hau gehitu nahi du Ezarpen bizkorrak menuan:"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Gehitu lauza"</string>
@@ -1130,7 +1138,7 @@
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Gailuko erregistro guztiak erabiltzeko baimena eman nahi diozu <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> aplikazioari?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"Eman behin erabiltzeko baimena"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ez eman baimenik"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"Gailuko erregistroetan gailuan gertatzen den guztia gordetzen da. Arazoak bilatu eta konpontzeko erabil ditzakete aplikazioek erregistro horiek.\n\nBaliteke erregistro batzuek kontuzko informazioa edukitzea. Beraz, eman gailuko erregistro guztiak erabiltzeko baimena fidagarritzat jotzen dituzun aplikazioei bakarrik. \n\nNahiz eta gailuko erregistro guztiak erabiltzeko baimena ez eman aplikazio honi, aplikazioak hari dagozkion erregistroak atzitu ahalko ditu. Gainera, baliteke gailuaren fabrikatzaileak gailuko erregistro edo datu batzuk atzitu ahal izatea."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"Gailuko erregistroetan gailuan gertatzen den guztia gordetzen da. Arazoak bilatu eta konpontzeko erabil ditzakete aplikazioek erregistro horiek.\n\nBaliteke erregistro batzuek kontuzko informazioa edukitzea. Beraz, eman gailuko erregistro guztiak erabiltzeko baimena fidagarritzat jotzen dituzun aplikazioei bakarrik. \n\nNahiz eta gailuko erregistro guztiak erabiltzeko baimena ez eman aplikazio honi, aplikazioak hari dagozkion erregistroak erabili ahalko ditu. Gainera, baliteke gailuaren fabrikatzaileak gailuko erregistro edo datu batzuk erabili ahal izatea."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Lortu informazio gehiago"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Lortu informazio gehiago <xliff:g id="URL">%s</xliff:g> helbidean"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ireki <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index bb948f4..ca65df2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"انتقال به پایین"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"انتقال به راست"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"انتقال به چپ"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"کلید درشتنمایی"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"درشتنمایی تمامصفحه"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"درشتنمایی بخشی از صفحه"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c8349c5..4371f00 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Siirrä alas"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Siirrä vasemmalle"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Siirrä oikealle"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Suurennusvalinta"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Koko näytön suurennus"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Suurenna osa näytöstä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 36bcfc4..96c9404 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Déplacer vers le bas"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Déplacer vers la gauche"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Déplacer vers la droite"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Commutateur d\'agrandissement"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Agrandir la totalité de l\'écran"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Agrandir une partie de l\'écran"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a274d0f..5c9efe4 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Déplacer vers le bas"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Déplacer vers la gauche"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Déplacer vers la droite"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Changer de mode d\'agrandissement"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Agrandir tout l\'écran"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Agrandir une partie de l\'écran"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 7105a3c..f7fc9b9 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover cara abaixo"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover cara á esquerda"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover cara á dereita"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Interruptor do modo de ampliación"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Amplía parte da pantalla"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index fdc6a8b..7fba445 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"નીચે ખસેડો"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ડાબી બાજુ ખસેડો"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"જમણી બાજુ ખસેડો"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"મોટું કરવાની સુવિધાવાળી સ્વિચ"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"પૂર્ણ સ્ક્રીનને મોટી કરો"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"સ્ક્રીનનો કોઈ ભાગ મોટો કરો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 7a94870..e043ac3 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -297,7 +297,7 @@
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"वर्क ऐप्लिकेशन"</string>
<string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"रोकी गई"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"नाइट लाइट"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"शाम को चालू की जाएगी"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"शाम को चालू होगी"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"सुबह तक चालू रहेगी"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> पर चालू की जाएगी"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> तक"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"नीचे ले जाएं"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"बाईं ओर ले जाएं"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"दाईं ओर ले जाएं"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"ज़ूम करने की सुविधा वाला स्विच"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"फ़ुल स्क्रीन को ज़ूम करें"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीन के किसी हिस्से को ज़ूम करें"</string>
@@ -903,8 +911,8 @@
<string name="controls_providers_title" msgid="6879775889857085056">"कंट्रोल जोड़ने के लिए ऐप्लिकेशन चुनें"</string>
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# कंट्रोल जोड़ा गया.}one{# कंट्रोल जोड़ा गया.}other{# कंट्रोल जोड़े गए.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"हटाया गया"</string>
- <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> को जोड़ना है?"</string>
- <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> यह चुन सकता है कि इस पैनल पर कौनसे कंट्रोल और कॉन्टेंट दिखे."</string>
+ <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ऐप्लिकेशन को जोड़ना है?"</string>
+ <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> ऐप्लिकेशन यह चुन सकता है कि इस पैनल पर कौनसे कंट्रोल और कॉन्टेंट दिखे."</string>
<string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> के लिए कंट्रोल हटाने हैं?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"पसंदीदा बनाया गया"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"पसंदीदा बनाया गया, क्रम संख्या <xliff:g id="NUMBER">%d</xliff:g>"</string>
@@ -1127,7 +1135,7 @@
<string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"कोई जानकारी नहीं"</string>
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string>
<string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
- <string name="log_access_confirmation_title" msgid="4843557604739943395">"क्या <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> को डिवाइस लॉग का ऐक्सेस देना है?"</string>
+ <string name="log_access_confirmation_title" msgid="4843557604739943395">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> को डिवाइस लॉग ऐक्सेस करने की अनुमति देनी है?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"एक बार ऐक्सेस करने की अनुमति दें"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"अनुमति न दें"</string>
<string name="log_access_confirmation_body" msgid="6883031912003112634">"डिवाइस लॉग में आपके डिवाइस पर की गई कार्रवाइयां रिकॉर्ड होती हैं. ऐप्लिकेशन, इन लॉग का इस्तेमाल गड़बड़ियां ढूंढने और उन्हें ठीक करने के लिए कर सकते हैं.\n\nकुछ लॉग में संवेदनशील जानकारी हो सकती है. इसलिए, सिर्फ़ भरोसेमंद ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस दें. \n\nअगर इस ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस नहीं दिया जाता है, तब भी यह डिवाइस पर मौजूद अपने लॉग ऐक्सेस कर सकता है. डिवाइस को बनाने वाली कंपनी फिर भी डिवाइस के कुछ लॉग या जानकारी ऐक्सेस कर सकती है."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index cd0f67c..8b19817 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Premjesti dolje"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Premjesti ulijevo"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Premjesti udesno"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Prebacivanje povećavanja"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Povećajte cijeli zaslon"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Povećaj dio zaslona"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 240b082..9accf6e 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mozgatás lefelé"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mozgatás balra"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mozgatás jobbra"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Nagyításváltó"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"A teljes képernyő felnagyítása"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Képernyő bizonyos részének nagyítása"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index cc826bd..235d040 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -397,7 +397,7 @@
<string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ավելացնելով նոր օգտատեր՝ դուք դուրս կգաք հյուրի ռեժիմից։ Հյուրի ընթացիկ աշխատաշրջանի բոլոր հավելվածներն ու տվյալները կջնջվեն։"</string>
<string name="user_limit_reached_title" msgid="2429229448830346057">"Սահմանաչափը սպառված է"</string>
<string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Հնարավոր է ստեղծել միայն մեկ օգտատեր։}one{Կարող եք առավելագույնը # օգտատեր ավելացնել։}other{Կարող եք առավելագույնը # օգտատեր ավելացնել։}}"</string>
- <string name="user_remove_user_title" msgid="9124124694835811874">"Հեռացնե՞լ օգտատիրոջը:"</string>
+ <string name="user_remove_user_title" msgid="9124124694835811874">"Հեռացնե՞լ օգտատիրոջը"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"Այս օգտատիրոջ բոլոր հավելվածներն ու տվյալները կջնջվեն:"</string>
<string name="user_remove_user_remove" msgid="8387386066949061256">"Հեռացնել"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Սկսե՞լ տեսագրումը կամ հեռարձակումը <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածով"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Տեղափոխել ներքև"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Տեղափոխել ձախ"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Տեղափոխել աջ"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Խոշորացման փոփոխություն"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Խոշորացնել ամբողջ էկրանը"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Խոշորացնել էկրանի որոշակի հատվածը"</string>
@@ -1128,7 +1136,7 @@
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string>
<string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Հասանելի դարձնե՞լ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> հավելվածին սարքի բոլոր մատյանները"</string>
- <string name="log_access_confirmation_allow" msgid="752147861593202968">"Թույլատրել մեկանգամյա մուտքը"</string>
+ <string name="log_access_confirmation_allow" msgid="752147861593202968">"Թույլատրել մեկանգամյա մուտք"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Չթույլատրել"</string>
<string name="log_access_confirmation_body" msgid="6883031912003112634">"Այն, ինչ տեղի է ունենում ձեր սարքում, գրանցվում է սարքի մատյաններում։ Հավելվածները կարող են դրանք օգտագործել անսարքությունները հայտնաբերելու և վերացնելու նպատակով։\n\nՔանի որ որոշ մատյաններ անձնական տեղեկություններ են պարունակում, խորհուրդ ենք տալիս հասանելի դարձնել ձեր սարքի բոլոր մատյանները միայն այն հավելվածներին, որոնց վստահում եք։ \n\nԵթե այս հավելվածին նման թույլտվություն չեք տվել, դրան նախկինի պես հասանելի կլինեն իր մատյանները։ Հնարավոր է՝ ձեր սարքի արտադրողին ևս հասանելի լինեն սարքի որոշ մատյաններ և տեղեկություններ։"</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Իմանալ ավելին"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 6e4ba4b..c9b6530 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Pindahkan ke bawah"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Pindahkan ke kiri"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Pindahkan ke kanan"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Tombol pembesaran"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Memperbesar tampilan layar penuh"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Perbesar sebagian layar"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 78fd712..7083940 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Færa niður"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Færa til vinstri"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Færa til hægri"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Stækkunarrofi"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Stækka allan skjáinn"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Stækka hluta skjásins"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 409eac1..568bac5 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -172,17 +172,17 @@
<string name="biometric_re_enroll_dialog_confirm" msgid="3049858021857801836">"Configura"</string>
<string name="biometric_re_enroll_dialog_cancel" msgid="93760939407091417">"Non ora"</string>
<string name="biometric_re_enroll_notification_content" msgid="8685925877186288180">"L\'operazione è necessaria per migliorare la sicurezza e le prestazioni"</string>
- <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Riconfigura lo sblocco con l\'impronta"</string>
- <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Sblocco con l\'impronta"</string>
- <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configura lo sblocco con l\'impronta"</string>
- <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Per riconfigurare lo sblocco con l\'impronta, i modelli e le immagini dell\'impronta correnti verranno eliminati.\n\nDopo la cancellazione, dovrai riconfigurare la funzionalità per usare l\'impronta per sbloccare il telefono o verificare la tua identità."</string>
- <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Per riconfigurare lo sblocco con l\'impronta, il modello e le immagini dell\'impronta correnti verranno eliminati.\n\nDopo la cancellazione, dovrai riconfigurare la funzionalità per usare l\'impronta per sbloccare il telefono o verificare la tua identità."</string>
- <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Impossibile configurare lo sblocco con l\'impronta. Vai alle Impostazioni e riprova."</string>
- <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Riconfigura lo sblocco con il volto"</string>
- <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Sblocco con il volto"</string>
- <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Configura lo sblocco con il volto"</string>
- <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Per riconfigurare lo sblocco con il volto, l\'attuale modello del volto verrà eliminato.\n\nDovrai riconfigurare questa funzionalità per usare il volto per sbloccare il telefono."</string>
- <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Impossibile configurare lo sblocco con il volto. Vai alle Impostazioni e riprova."</string>
+ <string name="fingerprint_re_enroll_notification_title" msgid="4539432429683916604">"Riconfigura lo Sblocco con l\'Impronta"</string>
+ <string name="fingerprint_re_enroll_notification_name" msgid="630798657797645704">"Sblocco con l\'Impronta"</string>
+ <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Configura lo Sblocco con l\'Impronta"</string>
+ <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"Per riconfigurare lo Sblocco con l\'Impronta, i modelli e le immagini dell\'impronta correnti verranno eliminati.\n\nDopo la cancellazione, dovrai riconfigurare la funzionalità per usare l\'impronta per sbloccare il telefono o verificare la tua identità."</string>
+ <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"Per riconfigurare lo Sblocco con l\'Impronta, il modello e le immagini dell\'impronta correnti verranno eliminati.\n\nDopo la cancellazione, dovrai riconfigurare la funzionalità per usare l\'impronta per sbloccare il telefono o verificare la tua identità."</string>
+ <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Impossibile configurare lo Sblocco con l\'Impronta. Vai alle Impostazioni e riprova."</string>
+ <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Riconfigura lo Sblocco con il Volto"</string>
+ <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Sblocco con il Volto"</string>
+ <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Configura lo Sblocco con il Volto"</string>
+ <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"Per riconfigurare lo Sblocco con il Volto, l\'attuale modello del volto verrà eliminato.\n\nDovrai riconfigurare questa funzionalità per usare il volto per sbloccare il telefono."</string>
+ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Impossibile configurare lo Sblocco con il Volto. Vai alle Impostazioni e riprova."</string>
<string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Tocca il sensore di impronte"</string>
<string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Premi l\'icona Sblocca per continuare"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impossibile riconoscere il volto. Usa l\'impronta."</string>
@@ -190,7 +190,7 @@
<skip />
<string name="keyguard_face_failed" msgid="9044619102286917151">"Volto non riconosciuto"</string>
<string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa l\'impronta"</string>
- <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Sblocco con il volto non disponibile"</string>
+ <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Sblocco con il Volto non disponibile"</string>
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth collegato."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentuale della batteria sconosciuta."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connesso a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
@@ -254,7 +254,7 @@
<string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Rotazione automatica dello schermo"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Geolocalizzazione"</string>
<string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Salvaschermo"</string>
- <string name="quick_settings_camera_label" msgid="5612076679385269339">"Accesso alla fotocamera"</string>
+ <string name="quick_settings_camera_label" msgid="5612076679385269339">"Accesso alla videocamera"</string>
<string name="quick_settings_mic_label" msgid="8392773746295266375">"Accesso al microfono"</string>
<string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Disponibile"</string>
<string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Bloccato"</string>
@@ -365,7 +365,7 @@
<string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Sbloccato con il volto"</string>
<string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Volto riconosciuto"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Scorri verso l\'alto per riprovare"</string>
- <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"Scorri verso l\'alto per riprovare lo sblocco con il volto"</string>
+ <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"Scorri verso l\'alto per riprovare lo Sblocco con il Volto"</string>
<string name="require_unlock_for_nfc" msgid="1305686454823018831">"Sblocca per usare NFC"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"Questo dispositivo appartiene alla tua organizzazione"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"Questo dispositivo appartiene a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Sposta giù"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Sposta a sinistra"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Sposta a destra"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Opzione Ingrandimento"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ingrandisci l\'intero schermo"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ingrandisci parte dello schermo"</string>
@@ -1084,7 +1092,7 @@
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Aggiungi riquadro"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Non aggiungerlo"</string>
<string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleziona utente"</string>
- <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{C\'è # app attiva}many{Ci sono # app attive}other{Ci sono # app attive}}"</string>
+ <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app è attiva}many{# di app sono attive}other{# app sono attive}}"</string>
<string name="fgs_dot_content_description" msgid="2865071539464777240">"Nuove informazioni"</string>
<string name="fgs_manager_dialog_title" msgid="5879184257257718677">"App attive"</string>
<string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Queste app sono attive e in esecuzione, anche quando non le utilizzi. Questo migliora la loro funzionalità, ma influisce sulla durata della batteria."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index fc15eab..d42451a 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"הזזה למטה"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"הזזה שמאלה"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"הזזה ימינה"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"מעבר למצב הגדלה"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"הגדלה של המסך המלא"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"הגדלת חלק מהמסך"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 1883bf3..21a402c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"下に移動"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"左に移動"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"右に移動"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"拡大スイッチ"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"画面全体を拡大します"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"画面の一部を拡大します"</string>
@@ -904,7 +912,7 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# 件のコントロールを追加しました。}other{# 件のコントロールを追加しました。}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"削除済み"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> を追加しますか?"</string>
- <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> はここに表示されるコントロールとコンテンツを選択できます。"</string>
+ <string name="controls_panel_authorization" msgid="7045551688535104194">"ここに表示されるコントロールとコンテンツを <xliff:g id="APPNAME">%s</xliff:g> が選択できるようになります。"</string>
<string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> のコントロールを削除しますか?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"お気に入りに追加済み"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"お気に入りに追加済み、位置: <xliff:g id="NUMBER">%d</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index c1e687e..722f66d 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"ქვემოთ გადატანა"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"მარცხნივ გადატანა"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"მარჯვნივ გადატანა"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"გადიდების გადართვა"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"გაადიდეთ სრულ ეკრანზე"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ეკრანის ნაწილის გადიდება"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 0067de0..f8919f2 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Төмен қарай жылжыту"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Солға жылжыту"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Оңға жылжыту"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Ұлғайту режиміне ауыстырғыш"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Толық экранды ұлғайту"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Экранның бөлігін ұлғайту"</string>
@@ -925,7 +933,7 @@
<string name="controls_favorite_load_none" msgid="7687593026725357775">"Үйлесімді басқару элементтері қолжетімді емес."</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Басқа"</string>
<string name="controls_dialog_title" msgid="2343565267424406202">"Құрылғы басқару элементтеріне қосу"</string>
- <string name="controls_dialog_ok" msgid="2770230012857881822">"Енгізу"</string>
+ <string name="controls_dialog_ok" msgid="2770230012857881822">"Қосу"</string>
<string name="controls_dialog_remove" msgid="3775288002711561936">"Жою"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ұсынған"</string>
<string name="controls_tile_locked" msgid="731547768182831938">"Құрылғы құлыпталды."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 11eb614..4206a10 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"ផ្លាស់ទីចុះក្រោម"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ផ្លាស់ទីទៅឆ្វេង"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"ផ្លាស់ទីទៅស្តាំ"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"ប៊ូតុងបិទបើកការពង្រីក"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ពង្រីកពេញអេក្រង់"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ពង្រីកផ្នែកនៃអេក្រង់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 9549132..5bb81f7 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -230,7 +230,7 @@
<string name="data_usage_disabled_dialog_mobile_title" msgid="2286843518689837719">"ಮೊಬೈಲ್ ಡೇಟಾವನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="data_usage_disabled_dialog_title" msgid="9131615296036724838">"ಡೇಟಾ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="data_usage_disabled_dialog" msgid="7933201635215099780">"ಡೇಟಾ ಬಳಕೆಯು ನೀವು ಹೊಂದಿಸಿರುವ ಮಿತಿಯನ್ನು ತಲುಪಿದೆ. ಹೀಗಾಗಿ ನೀವು ಈಗ ಮೊಬೈಲ್ ಡೇಟಾ ಬಳಸುತ್ತಿಲ್ಲ.\n\nನೀವು ಮುಂದುವರಿದರೆ, ಡೇಟಾ ಬಳಕೆಗೆ ಶುಲ್ಕ ತೆರಬೇಕಾಗಬಹುದು."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"ಮುಂದುವರಿಸು"</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"ಮುಂದುವರಿಸಿ"</string>
<string name="accessibility_location_active" msgid="2845747916764660369">"ಸ್ಥಳ ವಿನಂತಿಗಳು ಸಕ್ರಿಯವಾಗಿವೆ"</string>
<string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ಸೆನ್ಸರ್ಗಳು ಆಫ್ ಆಗಿವೆ"</string>
<string name="accessibility_clear_all" msgid="970525598287244592">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೆರವುಗೊಳಿಸು."</string>
@@ -502,7 +502,7 @@
<string name="screen_pinning_description_gestural" msgid="7246323931831232068">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಮೇಲೆ ಸ್ವೈಪ್ ಮಾಡಿ ಮತ್ತು ಅನ್ಪಿನ್ ಮಾಡಲು ಹೋಲ್ಡ್ ಮಾಡಿ."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಅನ್ಪಿನ್ ಮಾಡಲು ಅವಲೋಕನವನ್ನು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹೋಲ್ಡ್ ಮಾಡಿ."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಅನ್ಪಿನ್ ಮಾಡಲು ಮುಖಪುಟವನ್ನು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಒತ್ತಿಹಿಡಿಯಿರಿ."</string>
- <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು (ಉದಾ, ಸಂಪರ್ಕಗಳು ಮತ್ತು ಇಮೇಲ್ ವಿಷಯ)."</string>
+ <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಬಹುದು(ಉದಾ, ಸಂಪರ್ಕಗಳು ಮತ್ತು ಇಮೇಲ್ ಕಂಟೆಂಟ್)."</string>
<string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"ಪಿನ್ ಮಾಡಲಾದ ಆ್ಯಪ್ ಇತರ ಆ್ಯಪ್ಗಳನ್ನು ತೆರೆಯಬಹುದು."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನ್ಪಿನ್ ಮಾಡಲು, ಹಿಂದಕ್ಕೆ ಮತ್ತು ಸಮಗ್ರ ನೋಟ ಬಟನ್ಗಳನ್ನು ಸ್ಪರ್ಶಿಸಿ & ಒತ್ತಿಹಿಡಿಯಿರಿ"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನ್ಪಿನ್ ಮಾಡಲು, ಹಿಂದಕ್ಕೆ ಮತ್ತು ಮುಖಪುಟ ಬಟನ್ಗಳನ್ನು ಸ್ಪರ್ಶಿಸಿ & ಒತ್ತಿಹಿಡಿಯಿರಿ"</string>
@@ -649,7 +649,7 @@
<string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"ಮುಖಪುಟ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"ಇತ್ತೀಚಿನವುಗಳು"</string>
<string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"ಹಿಂದೆ"</string>
- <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ನೋಟಿಫಿಕೇಶನ್ಗಳು"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್ಕಟ್ಗಳು"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ಕೀಬೋರ್ಡ್ ಲೇಔಟ್ ಬದಲಾಯಿಸಿ"</string>
<string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ಪಠ್ಯ ತೆರವುಗೊಳಿಸಿ"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"ಕೆಳಗೆ ಸರಿಸಿ"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ಎಡಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"ಬಲಕ್ಕೆ ಸರಿಸಿ"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"ಝೂಮ್ ಮಾಡುವ ಸ್ವಿಚ್"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಹಿಗ್ಗಿಸಿ"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ಸ್ಕ್ರೀನ್ನ ಅರ್ಧಭಾಗವನ್ನು ಝೂಮ್ ಮಾಡಿ"</string>
@@ -1127,7 +1135,7 @@
<string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"ಅಪರಿಚಿತ"</string>
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string>
<string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
- <string name="log_access_confirmation_title" msgid="4843557604739943395">"ಎಲ್ಲಾ ಸಾಧನದ ಲಾಗ್ಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ಗೆ ಅನುಮತಿಸುವುದೇ?"</string>
+ <string name="log_access_confirmation_title" msgid="4843557604739943395">"ಎಲ್ಲಾ ಸಾಧನದ ಲಾಗ್ಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"ಒಂದು ಬಾರಿಯ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"ಅನುಮತಿಸಬೇಡಿ"</string>
<string name="log_access_confirmation_body" msgid="6883031912003112634">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಸಾಧನದ ಲಾಗ್ಗಳು ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತವೆ. ಸಮಸ್ಯೆಗಳನ್ನು ಪತ್ತೆಹಚ್ಚಲು ಮತ್ತು ಪರಿಹರಿಸಲು ಆ್ಯಪ್ಗಳು ಈ ಲಾಗ್ ಅನ್ನು ಬಳಸಬಹುದು.\n\nಕೆಲವು ಲಾಗ್ಗಳು ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಿರಬಹುದು, ಆದ್ದರಿಂದ ನಿಮ್ಮ ವಿಶ್ವಾಸಾರ್ಹ ಆ್ಯಪ್ಗಳಿಗೆ ಮಾತ್ರ ಸಾಧನದ ಎಲ್ಲಾ ಲಾಗ್ಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ. \n\nಎಲ್ಲಾ ಸಾಧನ ಲಾಗ್ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ನೀವು ಈ ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸದಿದ್ದರೆ, ಅದು ಆಗಲೂ ತನ್ನದೇ ಆದ ಲಾಗ್ಗಳನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ನಿಮ್ಮ ಸಾಧನ ತಯಾರಕರಿಗೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಕೆಲವು ಲಾಗ್ಗಳು ಅಥವಾ ಮಾಹಿತಿಯನ್ನು ಪ್ರವೇಶಿಸಲು ಈಗಲೂ ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
diff --git a/packages/SystemUI/res/values-kn/strings_tv.xml b/packages/SystemUI/res/values-kn/strings_tv.xml
index cfcc896..f1087aa 100644
--- a/packages/SystemUI/res/values-kn/strings_tv.xml
+++ b/packages/SystemUI/res/values-kn/strings_tv.xml
@@ -22,7 +22,7 @@
<string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ಕನೆಕ್ಷನ್ ಕಡಿತಗೊಂಡಿದೆ"</string>
<string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ಮೂಲಕ"</string>
- <string name="tv_notification_panel_title" msgid="5311050946506276154">"ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="tv_notification_panel_title" msgid="5311050946506276154">"ನೋಟಿಫಿಕೇಶನ್ಗಳು"</string>
<string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string>
<string name="mic_recording_announcement" msgid="7587123608060316575">"ಮೈಕ್ರೊಫೋನ್ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
<string name="camera_recording_announcement" msgid="7240177719403759112">"ಕ್ಯಾಮರಾ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ea62509..235b396 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"아래로 이동"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"왼쪽으로 이동"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"오른쪽으로 이동"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"확대 전환"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"전체 화면 확대"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"화면 일부 확대"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index e59c8f5..570c320 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Төмөн жылдыруу"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Солго жылдыруу"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Оңго жылдыруу"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Чоңойтуу режимине которулуу"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Толук экранда ачуу"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Экрандын бир бөлүгүн чоңойтуу"</string>
@@ -904,7 +912,7 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# көзөмөл кошулду.}other{# көзөмөл кошулду.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Өчүрүлдү"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> кошулсунбу?"</string>
- <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> бул жерде көрсөтүлө турган башкаруу элементтерин жана контентти тандай алат."</string>
+ <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> бул жерде көрүнө турган нерселерди тандайт."</string>
<string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> башкаруу элементтери өчүрүлсүнбү?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Сүйүктүүлөргө кошулду"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Сүйүктүүлөргө <xliff:g id="NUMBER">%d</xliff:g>-позицияга кошулду"</string>
@@ -1130,7 +1138,7 @@
<string name="log_access_confirmation_title" msgid="4843557604739943395">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> колдонмосуна түзмөктөгү бардык таржымалдарды жеткиликтүү кыласызбы?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"Бир жолу жеткиликтүү кылуу"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Тыюу салуу"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"Түзмөктө аткарылган бардык аракеттер түзмөктүн таржымалдарында сакталып калат. Колдонмолор бул таржымалдарды колдонуп, маселелерди оңдошот.\n\nАйрым таржымалдарда купуя маалымат болушу мүмкүн, андыктан ишенимдүү колдонмолорго гана түзмөктөгү бардык таржымалдарды пайдаланууга уруксат бериңиз. \n\nЭгер бул колдонмого түзмөктөгү бардык таржымалдарга кирүүгө тыюу салсаңыз, ал өзүнүн таржымалдарын пайдалана берет. Түзмөктү өндүрүүчү түзмөгүңүздөгү айрым таржымалдарды же маалыматты көрө берет."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"Түзмөктө жасалган аракеттердин баары таржымалдарда сакталат. Колдонмолор алардын жардамы менен мүмкүн болгон мүчүлүштүктөрдү таап, оңдоп турат.\n\nАйрым таржымалдарда купуя маалымат камтылышы мүмкүн болгондуктан, түзмөктөгү бардык таржымалдарды ишенимдүү колдонмолорго гана жеткиликтүү кылыңыз. \n\nЭгер бул колдонмого түзмөктөгү айрым таржымалдарды гана жеткиликтүү кылсаңыз, ал мурункудай эле өзүнүн таржымалдарын көрө берет. Түзмөгүңүздөгү айрым таржымалдар же нерселер анын өндүрүүчүсүнө көрүнүшү мүмкүн."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Кеңири маалымат"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Кеңири маалымат: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ачуу"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index efbac48..9d6a3a1 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"ຍ້າຍລົງ"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ຍ້າຍໄປຊ້າຍ"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"ຍ້າຍໄປຂວາ"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"ສະຫຼັບການຂະຫຍາຍ"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ຂະຫຍາຍເຕັມຈໍ"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ຂະຫຍາຍບາງສ່ວນຂອງໜ້າຈໍ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 810c3c1..7f849a1 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Perkelti žemyn"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Perkelti kairėn"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Perkelti dešinėn"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Didinimo jungiklis"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Viso ekrano didinimas"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Didinti ekrano dalį"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index b86188d..e37163c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Pārvietot uz leju"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Pārvietot pa kreisi"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Pārvietot pa labi"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Palielinājuma slēdzis"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Palielināt visu ekrānu"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Palielināt ekrāna daļu"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 9b28a0e..3bef569 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -297,13 +297,13 @@
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Работни апликации"</string>
<string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"Паузирано"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Ноќно светло"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Вклуч. на зајдисонце"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"На зајдисонце"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"До изгрејсонце"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Вклучување: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Темна тема"</string>
<string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Штедач на батерија"</string>
- <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Вклуч. на зајдисонце"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"На зајдисонце"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрејсонце"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Се вклучува во <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Премести надолу"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Премести налево"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Премести надесно"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Прекинувач за зголемување"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Зголемете го целиот екран"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Зголемувајте дел од екранот"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 8b58add..32d6c03 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -297,7 +297,7 @@
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"ഔദ്യോഗിക ആപ്പുകൾ"</string>
<string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"തൽക്കാലം നിർത്തി"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"നൈറ്റ് ലൈറ്റ്"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"സൂര്യാസ്തമയത്തിന്"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"അസ്തമയത്തിന്"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"സൂര്യോദയം വരെ"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> വരെ"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"താഴേക്ക് നീക്കുക"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ഇടത്തേക്ക് നീക്കുക"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"വലത്തേക്ക് നീക്കുക"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"മാഗ്നിഫിക്കേഷൻ മോഡ് മാറുക"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"സ്ക്രീൻ പൂർണ്ണമായും മാഗ്നിഫൈ ചെയ്യുക"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"സ്ക്രീനിന്റെ ഭാഗം മാഗ്നിഫൈ ചെയ്യുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 23f4f8d..78eba99 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Доош зөөх"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Зүүн тийш зөөх"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Баруун тийш зөөх"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Томруулах сэлгэлт"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Бүтэн дэлгэцийг томруулах"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Дэлгэцийн нэг хэсгийг томруулах"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 25332db..08eaf70 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"खाली हलवा"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"डावीकडे हलवा"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"उजवीकडे हलवा"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"मॅग्निफिकेशन स्विच"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"फुल स्क्रीन मॅग्निफाय करा"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीनचा काही भाग मॅग्निफाय करा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 20d5afc..16b4332 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Alih ke bawah"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Alih ke kiri"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Alih ke kanan"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Suis pembesaran"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Besarkan skrin penuh"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Besarkan sebahagian skrin"</string>
@@ -904,7 +912,7 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kawalan ditambah.}other{# kawalan ditambah.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Dialih keluar"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Tambahkan <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g>boleh memilih kawalan dan kandungan yang dipaparkan di sini."</string>
+ <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> boleh memilih kawalan dan kandungan yang dipaparkan di sini."</string>
<string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Alih keluar kawalan untuk <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Digemari"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Digemari, kedudukan <xliff:g id="NUMBER">%d</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 1e4fbf5..ba2488f 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -99,7 +99,7 @@
<string name="screenrecord_title" msgid="4257171601439507792">"ဖန်သားပြင်ရိုက်ကူးစက်"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"စကရင်ရိုက်ကူးမှု အပြီးသတ်နေသည်"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
- <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"စတင် ရိုက်သံဖမ်းမလား။"</string>
+ <string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"ရိုက်သံဖမ်းခြင်း စတင်မလား။"</string>
<string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"ရုပ်သံဖမ်းနေစဉ် Android သည် သင့်ဖန်သားပြင်တွင် မြင်နိုင်သည့် (သို့) သင့်စက်တွင် ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"အက်ပ်တစ်ခုကို ရုပ်သံဖမ်းနေစဉ် Android သည် ယင်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string>
<string name="screenrecord_permission_dialog_continue" msgid="5811122652514424967">"ရုပ်သံ စဖမ်းရန်"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"အောက်သို့ရွှေ့ရန်"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ဘယ်ဘက်သို့ရွှေ့ရန်"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"ညာဘက်သို့ရွှေ့ရန်"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"ချဲ့ရန် ခလုတ်"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ဖန်သားပြင်အပြည့် ချဲ့သည်"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ဖန်သားပြင် တစ်စိတ်တစ်ပိုင်းကို ချဲ့ပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index e8b495d..d77fb44 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Flytt ned"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Flytt til venstre"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Flytt til høyre"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Forstørringsbryter"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Forstørr hele skjermen"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Forstørr en del av skjermen"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 30f6efa..cdcadd6 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -297,13 +297,13 @@
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"कामसम्बन्धी एपहरू"</string>
<string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"पज गरिएको छ"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Night Light"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"सूर्यास्तमा सक्रिय"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"सर्यास्त हुँदा अन हुन्छ"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"सूर्योदयसम्म"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> मा सक्रिय"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> सम्म"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"अँध्यारो थिम"</string>
<string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ब्याट्री सेभर"</string>
- <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"सूर्यास्तमा सक्रिय"</string>
+ <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"सर्यास्त हुँदा अन हुन्छ"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयसम्म"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> मा सक्रिय"</string>
<string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> सम्म"</string>
@@ -394,7 +394,7 @@
<string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"हो, जारी राख्नुहोस्"</string>
<string name="guest_notification_app_name" msgid="2110425506754205509">"अतिथि मोड"</string>
<string name="guest_notification_session_active" msgid="5567273684713471450">"तपाईं अतिथि मोड चलाउँदै हुनुहुन्छ"</string>
- <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"तपाईंले नयाँ प्रयोगकर्ता थप्नुभयो भने तपाईं अतिथि मोडबाट बाहिरिनु हुने छ र हालको अतिथि सत्रका सबै एप तथा डेटा मेटिने छ।"</string>
+ <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"तपाईंले नयाँ प्रयोगकर्ता हाल्नुभयो भने तपाईं अतिथि मोडबाट बाहिरिनु हुने छ र हालको अतिथि सत्रका सबै एप तथा डेटा मेटिने छ।"</string>
<string name="user_limit_reached_title" msgid="2429229448830346057">"प्रयोगकर्ताको सीमा पुग्यो"</string>
<string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{एउटा प्रोफाइल मात्र बनाउन सकिन्छ।}other{तपाईं बढीमा # जना प्रयोगकर्ता सामेल गराउन सक्नुहुन्छ।}}"</string>
<string name="user_remove_user_title" msgid="9124124694835811874">"प्रयोगकर्ता हटाउन चाहनुहुन्छ?"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"तल सार्नुहोस्"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"बायाँ सार्नुहोस्"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"दायाँ सार्नुहोस्"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"म्याग्निफिकेसन स्विच"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"पूरै स्क्रिन जुम इन गर्नुहोस्"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रिनको केही भाग म्याग्निफाइ गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e547c67..8fb4f35 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Omlaag verplaatsen"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Naar links verplaatsen"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Naar rechts verplaatsen"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Vergrotingsschakelaar"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Volledig scherm vergroten"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Deel van het scherm vergroten"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index d34b848..af7e090 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"ତଳକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ବାମକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"ଡାହାଣକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ସ୍ୱିଚ୍"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ମ୍ୟାଗ୍ନିଫାଏ କରନ୍ତୁ"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ସ୍କ୍ରିନର ଅଂଶ ମାଗ୍ନିଫାଏ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 867fd17..8025ad1 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"ਹੇਠਾਂ ਲਿਜਾਓ"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ਖੱਬੇ ਲਿਜਾਓ"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"ਸੱਜੇ ਲਿਜਾਓ"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"ਵੱਡਦਰਸ਼ੀਕਰਨ ਸਵਿੱਚ"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਵੱਡਦਰਸ਼ੀ ਕਰੋ"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ਸਕ੍ਰੀਨ ਦੇ ਹਿੱਸੇ ਨੂੰ ਵੱਡਾ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3750c0e..59b7072 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Przesuń w dół"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Przesuń w lewo"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Przesuń w prawo"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Przełączanie powiększenia"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Powiększanie pełnego ekranu"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Powiększ część ekranu"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 53c3418..20819b7 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -108,7 +108,7 @@
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sons do dispositivo, como música, chamadas e toques"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Microfone"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Áudio e microfone do dispositivo"</string>
- <string name="screenrecord_continue" msgid="4055347133700593164">"Início"</string>
+ <string name="screenrecord_continue" msgid="4055347133700593164">"Iniciar"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Gravando tela"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Gravando tela e áudio"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Mostrar toques na tela"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover para baixo"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover para a esquerda"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover para a direita"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Chave de ampliação"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar toda a tela"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
@@ -904,7 +912,7 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar o app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> pode escolher quais controles e conteúdos aparecem aqui."</string>
+ <string name="controls_panel_authorization" msgid="7045551688535104194">"O app <xliff:g id="APPNAME">%s</xliff:g> pode escolher quais controles e conteúdos aparecem aqui."</string>
<string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remover controles do app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -1128,7 +1136,7 @@
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string>
<string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Permitir que o app <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> acesse todos os registros do dispositivo?"</string>
- <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir o acesso único"</string>
+ <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir acesso único"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Não permitir"</string>
<string name="log_access_confirmation_body" msgid="6883031912003112634">"Os registros do dispositivo gravam o que acontece nele. Os apps podem usar esses registros para encontrar e corrigir problemas.\n\nAlguns registros podem conter informações sensíveis, então autorize o acesso a eles apenas para os apps em que você confia. \n\nSe você não permitir que esse app acesse todos os registros do dispositivo, ele ainda vai poder acessar os dele. O fabricante do dispositivo também pode ter acesso a alguns registros ou informações."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saiba mais"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 9516f6c..ae6c944 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover para baixo"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover para a esquerda"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover para a direita"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Interruptor de ampliação"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar o ecrã inteiro"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte do ecrã"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 53c3418..20819b7 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -108,7 +108,7 @@
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sons do dispositivo, como música, chamadas e toques"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Microfone"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Áudio e microfone do dispositivo"</string>
- <string name="screenrecord_continue" msgid="4055347133700593164">"Início"</string>
+ <string name="screenrecord_continue" msgid="4055347133700593164">"Iniciar"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Gravando tela"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Gravando tela e áudio"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Mostrar toques na tela"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover para baixo"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover para a esquerda"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover para a direita"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Chave de ampliação"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar toda a tela"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
@@ -904,7 +912,7 @@
<string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string>
<string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
<string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar o app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
- <string name="controls_panel_authorization" msgid="7045551688535104194">"<xliff:g id="APPNAME">%s</xliff:g> pode escolher quais controles e conteúdos aparecem aqui."</string>
+ <string name="controls_panel_authorization" msgid="7045551688535104194">"O app <xliff:g id="APPNAME">%s</xliff:g> pode escolher quais controles e conteúdos aparecem aqui."</string>
<string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remover controles do app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
<string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -1128,7 +1136,7 @@
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string>
<string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Permitir que o app <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> acesse todos os registros do dispositivo?"</string>
- <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir o acesso único"</string>
+ <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir acesso único"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Não permitir"</string>
<string name="log_access_confirmation_body" msgid="6883031912003112634">"Os registros do dispositivo gravam o que acontece nele. Os apps podem usar esses registros para encontrar e corrigir problemas.\n\nAlguns registros podem conter informações sensíveis, então autorize o acesso a eles apenas para os apps em que você confia. \n\nSe você não permitir que esse app acesse todos os registros do dispositivo, ele ainda vai poder acessar os dele. O fabricante do dispositivo também pode ter acesso a alguns registros ou informações."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saiba mais"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index c96a9d25..d87415f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Mută în jos"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Mută la stânga"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Mută spre dreapta"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Comutator de mărire"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Mărește tot ecranul"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Mărește o parte a ecranului"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d1f137f..b271b16 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Переместить вниз"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Переместить влево"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Переместить вправо"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Переключатель режима увеличения"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Увеличение всего экрана"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увеличить часть экрана"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 6e3d064..65511283 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"පහළට ගෙන යන්න"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"වමට ගෙන යන්න"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"දකුණට ගෙන යන්න"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"විශාලන ස්විචය"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"පූර්ණ තිරය විශාලනය කරන්න"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"තිරයේ කොටසක් විශාලනය කරන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index c95eda8..0dd0477 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -297,7 +297,7 @@
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Pracovné aplikácie"</string>
<string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"Pozastavené"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Nočný režim"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Zapne sa pri západe slnka"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Zap. pri záp. slnka"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do východu slnka"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Od <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Posunúť nadol"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Posunúť doľava"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Posunúť doprava"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Prepínač zväčenia"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Zväčšenie celej obrazovky"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zväčšiť časť obrazovky"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 176e3fe..1608d59 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Premakni navzdol"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Premakni levo"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Premakni desno"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Stikalo za povečavo"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Povečanje celotnega zaslona"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Povečava dela zaslona"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 1d9b5fe..5acec41 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -297,7 +297,7 @@
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Aplikacionet e punës"</string>
<string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"Vendosur në pauzë"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Drita e natës"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Në perëndim të diellit"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Aktiv në perëndim"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Deri në lindje të diellit"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Aktive në <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Deri në <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -380,7 +380,7 @@
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Heshtje\ne plotë"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Vetëm\nme prioritet"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Vetëm\nalarmet"</string>
- <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet me valë • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
+ <string name="keyguard_indication_charging_time_wireless" msgid="577856646141738675">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet në mënyrë wireless • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time" msgid="6492711711891071502">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_fast" msgid="8390311020603859480">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet shpejt • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet ngadalë • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Lëvize poshtë"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Lëvize majtas"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Lëvize djathtas"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Ndërrimi i zmadhimit"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Zmadho ekranin e plotë"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zmadho një pjesë të ekranit"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 84c2905..5bd0121 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Померите надоле"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Померите налево"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Померите надесно"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Прелазак на други режим увећања"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Увећајте цео екран"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увећајте део екрана"</string>
@@ -1180,10 +1188,10 @@
<string name="privacy_dialog_manage_permissions" msgid="2543451567190470413">"Управљај приступом"</string>
<string name="privacy_dialog_active_call_usage" msgid="7858746847946397562">"Користи телефонски позив"</string>
<string name="privacy_dialog_recent_call_usage" msgid="1214810644978167344">"Недавно коришћено у телефонском позиву"</string>
- <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Користи <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="privacy_dialog_active_app_usage" msgid="631997836335929880">"Користе <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="privacy_dialog_recent_app_usage" msgid="4883417856848222450">"Недавно користила апликација <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Користи <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
+ <string name="privacy_dialog_active_app_usage_1" msgid="9047570143069220911">"Користе <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="privacy_dialog_recent_app_usage_1" msgid="2551340497722370109">"Недавно користила апликација <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
- <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Користи <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
+ <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"Користе <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
<string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"Недавно користила апликација <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 69329c7..fa9b8c5 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Flytta nedåt"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Flytta åt vänster"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Flytta åt höger"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Förstoringsreglage"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Förstora hela skärmen"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Förstora en del av skärmen"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 7f15007..aa72d98 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Sogeza chini"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Sogeza kushoto"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Sogeza kulia"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Swichi ya ukuzaji"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Kuza skrini nzima"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Kuza sehemu ya skrini"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 09a4cea..102b7c5 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"கீழே நகர்த்து"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"இடப்புறம் நகர்த்து"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"வலப்புறம் நகர்த்து"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"பெரிதாக்கல் ஸ்விட்ச்"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"முழுத்திரையைப் பெரிதாக்கும்"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"திரையின் ஒரு பகுதியைப் பெரிதாக்கும்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 1d6ce58..1c24995 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"కిందకి పంపండి"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ఎడమవైపుగా జరపండి"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"కుడివైపుగా జరపండి"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"మ్యాగ్నిఫికేషన్ స్విచ్"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ఫుల్ స్క్రీన్ను మ్యాగ్నిఫై చేయండి"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"స్క్రీన్లో భాగాన్ని మ్యాగ్నిఫై చేయండి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 6c6eaa7..97c6597 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"ย้ายลง"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"ย้ายไปทางซ้าย"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"ย้ายไปทางขวา"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"เปลี่ยนโหมดการขยาย"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ขยายเป็นเต็มหน้าจอ"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ขยายบางส่วนของหน้าจอ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index b5af2d2..423f7fb 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Ibaba"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Ilipat pakaliwa"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Ilipat pakanan"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Switch ng pag-magnify"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"I-magnify ang buong screen"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"I-magnify ang isang bahagi ng screen"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index b4114b2..69574d7 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Aşağı taşı"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Sola taşı"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Sağa taşı"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Büyütme moduna geçin"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Tam ekran büyütme"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekranın bir parçasını büyütün"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 168ebf8..cbf7391 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -297,7 +297,7 @@
<string name="quick_settings_work_mode_label" msgid="6440531507319809121">"Робочі додатки"</string>
<string name="quick_settings_work_mode_paused_state" msgid="6681788236383735976">"Призупинено"</string>
<string name="quick_settings_night_display_label" msgid="8180030659141778180">"Нічний екран"</string>
- <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Вмикається ввечері"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Запуск увечері"</string>
<string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"До сходу сонця"</string>
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Вмикається о <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"До <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -752,7 +752,7 @@
<string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"вилучити опцію"</string>
<string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"додати опцію в кінець"</string>
<string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Перемістити опцію"</string>
- <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Додати опцію"</string>
+ <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Додати панель"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Перемістити на позицію <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додати на позицію <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Позиція <xliff:g id="POSITION">%1$d</xliff:g>"</string>
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Перемістити вниз"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Перемістити ліворуч"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Перемістити праворуч"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Перемикач режиму збільшення"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Збільшення всього екрана"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Збільшити частину екрана"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 8f86121..315f5ec 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"نیچے منتقل کریں"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"بائیں منتقل کریں"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"دائیں منتقل کریں"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"میگنیفکیشن پر سوئچ کریں"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"فُل اسکرین کو بڑا کریں"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"اسکرین کا حصہ بڑا کریں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index cd719a6..4b62416 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Pastga siljitish"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Chapga siljitish"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Oʻngga siljitish"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Kattalashtirish rejimini almashtirish"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ekranni toʻliq kattalashtirish"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekran qismini kattalashtirish"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 1a7a38f..331a64b 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Di chuyển xuống"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Di chuyển sang trái"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Di chuyển sang phải"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Nút chuyển phóng to"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Phóng to toàn màn hình"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Phóng to một phần màn hình"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index d54c035..89857b5 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"下移"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"左移"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"右移"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"切换放大模式"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"放大整个屏幕"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大部分屏幕"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 431ef9e..db3aac5 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"向下移"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"向左移"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"向右移"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"放大開關"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"放大成個畫面"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大部分螢幕畫面"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 3e43d72..2d88b3f 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"向下移"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"向左移"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"向右移"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"切換放大模式"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"放大整個螢幕畫面"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大局部螢幕畫面"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 5b2b43e..caeabdc 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -861,6 +861,14 @@
<string name="accessibility_control_move_down" msgid="5390922476900974512">"Yehlisa"</string>
<string name="accessibility_control_move_left" msgid="8156206978511401995">"Yisa kwesokunxele"</string>
<string name="accessibility_control_move_right" msgid="8926821093629582888">"Yisa kwesokudla"</string>
+ <!-- no translation found for accessibility_control_increase_window_width (6992249470832493283) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_width (5740401560105929681) -->
+ <skip />
+ <!-- no translation found for accessibility_control_increase_window_height (2200966116612324260) -->
+ <skip />
+ <!-- no translation found for accessibility_control_decrease_window_height (2054479949445332761) -->
+ <skip />
<string name="magnification_mode_switch_description" msgid="2698364322069934733">"Iswishi yokukhulisa"</string>
<string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Khulisa isikrini esigcwele"</string>
<string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Khulisa ingxenye eyesikrini"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 3ada7c2..34b08b4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1231,6 +1231,7 @@
<dimen name="magnification_setting_image_button_open_in_full_padding_horizontal">28dp</dimen>
<dimen name="magnification_setting_drag_corner_radius">28dp</dimen>
<dimen name="magnification_setting_drag_size">56dp</dimen>
+ <fraction name="magnification_resize_window_size_amount">10%</fraction>
<!-- Seekbar with icon buttons -->
<dimen name="seekbar_icon_size">24dp</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 9957429..2fa895b 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -172,6 +172,10 @@
<item type="id" name="accessibility_action_move_right"/>
<item type="id" name="accessibility_action_move_up"/>
<item type="id" name="accessibility_action_move_down"/>
+ <item type="id" name="accessibility_action_increase_window_width"/>
+ <item type="id" name="accessibility_action_decrease_window_width"/>
+ <item type="id" name="accessibility_action_increase_window_height"/>
+ <item type="id" name="accessibility_action_decrease_window_height"/>
<!-- Accessibility actions for Accessibility floating menu. -->
<item type="id" name="action_move_top_left"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 275e5d8..3ca24af 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2398,6 +2398,16 @@
<string name="accessibility_control_move_left">Move left</string>
<!-- Action in accessibility menu to move the magnification window right. [CHAR LIMIT=30] -->
<string name="accessibility_control_move_right">Move right</string>
+
+ <!-- Action in accessibility menu to increase the magnification window width. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_control_increase_window_width">Increase width of magnifier</string>
+ <!-- Action in accessibility menu to decrease the magnification window width. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_control_decrease_window_width">Decrease width of magnifier</string>
+ <!-- Action in accessibility menu to increase the magnification window height. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_control_increase_window_height">Increase height of magnifier</string>
+ <!-- Action in accessibility menu to decrease the magnification window height. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_control_decrease_window_height">Decrease height of magnifier</string>
+
<!-- Content description for magnification mode switch. [CHAR LIMIT=NONE] -->
<string name="magnification_mode_switch_description">Magnification switch</string>
<!-- A11y state description for magnification mode switch that device is in full-screen mode. [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 8200e5c..9059230 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -17,6 +17,7 @@
package com.android.systemui.shared.rotation;
import static android.content.pm.PackageManager.FEATURE_PC;
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.internal.view.RotationPolicy.NATURAL_ROTATION;
@@ -37,6 +38,8 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -67,6 +70,7 @@
import java.io.PrintWriter;
import java.util.Optional;
+import java.util.concurrent.Executor;
import java.util.function.Supplier;
/**
@@ -119,6 +123,8 @@
private final int mIconCwStart0ResId;
@DrawableRes
private final int mIconCwStart90ResId;
+ /** Defaults to mainExecutor if not set via {@link #setBgExecutor(Executor)}. */
+ private Executor mBgExecutor;
@DrawableRes
private int mIconResId;
@@ -178,6 +184,8 @@
mAccessibilityManager = AccessibilityManager.getInstance(context);
mTaskStackListener = new TaskStackListenerImpl();
mWindowRotationProvider = windowRotationProvider;
+
+ mBgExecutor = context.getMainExecutor();
}
public void setRotationButton(RotationButton rotationButton,
@@ -193,6 +201,10 @@
return mContext;
}
+ public void setBgExecutor(Executor bgExecutor) {
+ mBgExecutor = bgExecutor;
+ }
+
/**
* Called during Taskbar initialization.
*/
@@ -219,8 +231,11 @@
mListenersRegistered = true;
- updateDockedState(mContext.registerReceiver(mDockedReceiver,
- new IntentFilter(Intent.ACTION_DOCK_EVENT)));
+ mBgExecutor.execute(() -> {
+ final Intent intent = mContext.registerReceiver(mDockedReceiver,
+ new IntentFilter(Intent.ACTION_DOCK_EVENT));
+ mContext.getMainExecutor().execute(() -> updateDockedState(intent));
+ });
if (registerRotationWatcher) {
try {
@@ -246,11 +261,13 @@
mListenersRegistered = false;
- try {
- mContext.unregisterReceiver(mDockedReceiver);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Docked receiver already unregistered", e);
- }
+ mBgExecutor.execute(() -> {
+ try {
+ mContext.unregisterReceiver(mDockedReceiver);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Docked receiver already unregistered", e);
+ }
+ });
if (mRotationWatcherRegistered) {
try {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 3990b10..c64ae01 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -17,6 +17,7 @@
package com.android.keyguard;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.StatusBarState.SHADE;
import android.util.Property;
import android.view.View;
@@ -124,7 +125,16 @@
true /* animate */);
log("keyguardFadingAway transition w/ Y Aniamtion");
} else if (statusBarState == KEYGUARD) {
- if (keyguardFadingAway) {
+ // Sometimes, device will be unlocked and then locked very quickly.
+ // keyguardFadingAway hasn't been set to false cause unlock animation hasn't finished
+ // So we should not animate keyguard fading away in this case (when oldState is SHADE)
+ if (oldStatusBarState != SHADE) {
+ log("statusBarState == KEYGUARD && oldStatusBarState != SHADE");
+ } else {
+ log("statusBarState == KEYGUARD && oldStatusBarState == SHADE");
+ }
+
+ if (keyguardFadingAway && oldStatusBarState != SHADE) {
mKeyguardViewVisibilityAnimating = true;
AnimationProperties animProps = new AnimationProperties()
.setDelay(0)
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 28d59c2..c5887d3 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -26,6 +26,7 @@
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UiContext;
@@ -703,6 +704,18 @@
}
/**
+ * Sets the window frame size with given width and height in pixels without changing the
+ * window center.
+ *
+ * @param width the window frame width in pixels
+ * @param height the window frame height in pixels.
+ */
+ @MainThread
+ private void setMagnificationFrameSize(int width, int height) {
+ setWindowSize(width + 2 * mMirrorSurfaceMargin, height + 2 * mMirrorSurfaceMargin);
+ }
+
+ /**
* Sets the window size with given width and height in pixels without changing the
* window center. The width or the height will be clamped in the range
* [{@link #mMinWindowSize}, screen width or height].
@@ -1466,19 +1479,50 @@
AccessibilityAction.ACTION_CLICK.getId(), getClickAccessibilityActionLabel());
info.addAction(clickAction);
info.setClickable(true);
+
info.addAction(
new AccessibilityAction(R.id.accessibility_action_zoom_in,
mContext.getString(R.string.accessibility_control_zoom_in)));
info.addAction(new AccessibilityAction(R.id.accessibility_action_zoom_out,
mContext.getString(R.string.accessibility_control_zoom_out)));
- info.addAction(new AccessibilityAction(R.id.accessibility_action_move_up,
- mContext.getString(R.string.accessibility_control_move_up)));
- info.addAction(new AccessibilityAction(R.id.accessibility_action_move_down,
- mContext.getString(R.string.accessibility_control_move_down)));
- info.addAction(new AccessibilityAction(R.id.accessibility_action_move_left,
- mContext.getString(R.string.accessibility_control_move_left)));
- info.addAction(new AccessibilityAction(R.id.accessibility_action_move_right,
- mContext.getString(R.string.accessibility_control_move_right)));
+
+ if (!mEditSizeEnable) {
+ info.addAction(new AccessibilityAction(R.id.accessibility_action_move_up,
+ mContext.getString(R.string.accessibility_control_move_up)));
+ info.addAction(new AccessibilityAction(R.id.accessibility_action_move_down,
+ mContext.getString(R.string.accessibility_control_move_down)));
+ info.addAction(new AccessibilityAction(R.id.accessibility_action_move_left,
+ mContext.getString(R.string.accessibility_control_move_left)));
+ info.addAction(new AccessibilityAction(R.id.accessibility_action_move_right,
+ mContext.getString(R.string.accessibility_control_move_right)));
+ } else {
+ if ((mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin)
+ < mWindowBounds.width()) {
+ info.addAction(new AccessibilityAction(
+ R.id.accessibility_action_increase_window_width,
+ mContext.getString(
+ R.string.accessibility_control_increase_window_width)));
+ }
+ if ((mMagnificationFrame.height() + 2 * mMirrorSurfaceMargin)
+ < mWindowBounds.height()) {
+ info.addAction(new AccessibilityAction(
+ R.id.accessibility_action_increase_window_height,
+ mContext.getString(
+ R.string.accessibility_control_increase_window_height)));
+ }
+ if ((mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin) > mMinWindowSize) {
+ info.addAction(new AccessibilityAction(
+ R.id.accessibility_action_decrease_window_width,
+ mContext.getString(
+ R.string.accessibility_control_decrease_window_width)));
+ }
+ if ((mMagnificationFrame.height() + 2 * mMirrorSurfaceMargin) > mMinWindowSize) {
+ info.addAction(new AccessibilityAction(
+ R.id.accessibility_action_decrease_window_height,
+ mContext.getString(
+ R.string.accessibility_control_decrease_window_height)));
+ }
+ }
info.setContentDescription(mContext.getString(R.string.magnification_window_title));
info.setStateDescription(formatStateDescription(getScale()));
@@ -1493,6 +1537,11 @@
}
private boolean performA11yAction(int action) {
+ final float changeWindowSizeAmount = mContext.getResources().getFraction(
+ R.fraction.magnification_resize_window_size_amount,
+ /* base= */ 1,
+ /* pbase= */ 1);
+
if (action == AccessibilityAction.ACTION_CLICK.getId()) {
if (mEditSizeEnable) {
// When edit mode is enabled, click the magnifier to exit edit mode.
@@ -1514,9 +1563,26 @@
move(-mSourceBounds.width(), 0);
} else if (action == R.id.accessibility_action_move_right) {
move(mSourceBounds.width(), 0);
+ } else if (action == R.id.accessibility_action_increase_window_width) {
+ int newFrameWidth =
+ (int) (mMagnificationFrame.width() * (1 + changeWindowSizeAmount));
+ setMagnificationFrameSize(newFrameWidth, mMagnificationFrame.height());
+ } else if (action == R.id.accessibility_action_increase_window_height) {
+ int newFrameHeight =
+ (int) (mMagnificationFrame.height() * (1 + changeWindowSizeAmount));
+ setMagnificationFrameSize(mMagnificationFrame.width(), newFrameHeight);
+ } else if (action == R.id.accessibility_action_decrease_window_width) {
+ int newFrameWidth =
+ (int) (mMagnificationFrame.width() * (1 - changeWindowSizeAmount));
+ setMagnificationFrameSize(newFrameWidth, mMagnificationFrame.height());
+ } else if (action == R.id.accessibility_action_decrease_window_height) {
+ int newFrameHeight =
+ (int) (mMagnificationFrame.height() * (1 - changeWindowSizeAmount));
+ setMagnificationFrameSize(mMagnificationFrame.width(), newFrameHeight);
} else {
return false;
}
+
mWindowMagnifierCallback.onAccessibilityActionPerformed(mDisplayId);
return true;
}
@@ -1527,4 +1593,5 @@
mDisplayId, scale, /* updatePersistence= */ true);
}
}
+
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index ca43705..a79be6e 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -354,11 +354,13 @@
if (mPercentageStyleId != 0) { // Only set if specified as attribute
mBatteryPercentView.setTextAppearance(mPercentageStyleId);
}
+ float fontHeight = mBatteryPercentView.getPaint().getFontMetricsInt(null);
+ mBatteryPercentView.setLineHeight(TypedValue.COMPLEX_UNIT_PX, fontHeight);
if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
updatePercentText();
addView(mBatteryPercentView, new LayoutParams(
LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT));
+ (int) Math.ceil(fontHeight)));
}
} else {
if (showing) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
index 53dc0e3..62e2369 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
@@ -25,8 +25,8 @@
import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepositoryImpl
import com.android.systemui.biometrics.data.repository.PromptRepository
import com.android.systemui.biometrics.data.repository.PromptRepositoryImpl
-import com.android.systemui.biometrics.data.repository.RearDisplayStateRepository
-import com.android.systemui.biometrics.data.repository.RearDisplayStateRepositoryImpl
+import com.android.systemui.biometrics.data.repository.DisplayStateRepository
+import com.android.systemui.biometrics.data.repository.DisplayStateRepositoryImpl
import com.android.systemui.biometrics.domain.interactor.CredentialInteractor
import com.android.systemui.biometrics.domain.interactor.CredentialInteractorImpl
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
@@ -65,9 +65,10 @@
@SysUISingleton
fun fingerprintRepository(impl: FingerprintPropertyRepositoryImpl):
FingerprintPropertyRepository
+
@Binds
@SysUISingleton
- fun rearDisplayStateRepository(impl: RearDisplayStateRepositoryImpl): RearDisplayStateRepository
+ fun displayStateRepository(impl: DisplayStateRepositoryImpl): DisplayStateRepository
@Binds
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt
new file mode 100644
index 0000000..7a9efcf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.data.repository
+
+import android.content.Context
+import android.hardware.devicestate.DeviceStateManager
+import android.hardware.display.DisplayManager
+import android.hardware.display.DisplayManager.DisplayListener
+import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+import android.os.Handler
+import android.view.DisplayInfo
+import com.android.internal.util.ArrayUtils
+import com.android.systemui.biometrics.shared.model.DisplayRotation
+import com.android.systemui.biometrics.shared.model.toDisplayRotation
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.stateIn
+
+/** Repository for the current state of the display */
+interface DisplayStateRepository {
+ /** Provides the current rear display state. */
+ val isInRearDisplayMode: StateFlow<Boolean>
+
+ /** Provides the current display rotation */
+ val currentRotation: StateFlow<DisplayRotation>
+}
+
+@SysUISingleton
+class DisplayStateRepositoryImpl
+@Inject
+constructor(
+ @Application applicationScope: CoroutineScope,
+ @Application val context: Context,
+ deviceStateManager: DeviceStateManager,
+ displayManager: DisplayManager,
+ @Main handler: Handler,
+ @Main mainExecutor: Executor
+) : DisplayStateRepository {
+ override val isInRearDisplayMode: StateFlow<Boolean> =
+ conflatedCallbackFlow {
+ val sendRearDisplayStateUpdate = { state: Boolean ->
+ trySendWithFailureLogging(
+ state,
+ TAG,
+ "Error sending rear display state update to $state"
+ )
+ }
+
+ val callback =
+ DeviceStateManager.DeviceStateCallback { state ->
+ val isInRearDisplayMode =
+ ArrayUtils.contains(
+ context.resources.getIntArray(
+ com.android.internal.R.array.config_rearDisplayDeviceStates
+ ),
+ state
+ )
+ sendRearDisplayStateUpdate(isInRearDisplayMode)
+ }
+
+ sendRearDisplayStateUpdate(false)
+ deviceStateManager.registerCallback(mainExecutor, callback)
+ awaitClose { deviceStateManager.unregisterCallback(callback) }
+ }
+ .stateIn(
+ applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = false,
+ )
+
+ private fun getDisplayRotation(): DisplayRotation {
+ val cachedDisplayInfo = DisplayInfo()
+ context.display?.getDisplayInfo(cachedDisplayInfo)
+ return cachedDisplayInfo.rotation.toDisplayRotation()
+ }
+
+ override val currentRotation: StateFlow<DisplayRotation> =
+ conflatedCallbackFlow {
+ val callback =
+ object : DisplayListener {
+ override fun onDisplayRemoved(displayId: Int) {}
+
+ override fun onDisplayAdded(displayId: Int) {}
+
+ override fun onDisplayChanged(displayId: Int) {
+ val rotation = getDisplayRotation()
+ trySendWithFailureLogging(
+ rotation,
+ TAG,
+ "Error sending display rotation to $rotation"
+ )
+ }
+ }
+ displayManager.registerDisplayListener(
+ callback,
+ handler,
+ EVENT_FLAG_DISPLAY_CHANGED
+ )
+ awaitClose { displayManager.unregisterDisplayListener(callback) }
+ }
+ .stateIn(
+ applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = getDisplayRotation(),
+ )
+
+ companion object {
+ const val TAG = "DisplayStateRepositoryImpl"
+ }
+}
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 daff5fe..aa33100 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
@@ -16,13 +16,19 @@
package com.android.systemui.biometrics.data.repository
+import android.Manifest.permission.USE_BIOMETRIC_INTERNAL
+import android.annotation.RequiresPermission
+import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
+import android.hardware.biometrics.SensorProperties
import android.hardware.fingerprint.FingerprintManager
+import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toSensorStrength
+import com.android.systemui.biometrics.shared.model.toSensorType
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
@@ -31,11 +37,10 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
/**
* A repository for the global state of FingerprintProperty.
@@ -44,22 +49,17 @@
*/
interface FingerprintPropertyRepository {
- /**
- * If the repository is initialized or not. Other properties are defaults until this is true.
- */
- val isInitialized: Flow<Boolean>
-
/** The id of fingerprint sensor. */
- val sensorId: StateFlow<Int>
+ val sensorId: Flow<Int>
/** The security strength of sensor (convenience, weak, strong). */
- val strength: StateFlow<SensorStrength>
+ val strength: Flow<SensorStrength>
/** The types of fingerprint sensor (rear, ultrasonic, optical, etc.). */
- val sensorType: StateFlow<FingerprintSensorType>
+ val sensorType: Flow<FingerprintSensorType>
/** The sensor location relative to each physical display. */
- val sensorLocations: StateFlow<Map<String, SensorLocationInternal>>
+ val sensorLocations: Flow<Map<String, SensorLocationInternal>>
}
@SysUISingleton
@@ -70,64 +70,64 @@
private val fingerprintManager: FingerprintManager?,
) : FingerprintPropertyRepository {
- override val isInitialized: Flow<Boolean> =
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ private val props: StateFlow<FingerprintSensorPropertiesInternal> =
conflatedCallbackFlow {
val callback =
object : IFingerprintAuthenticatorsRegisteredCallback.Stub() {
override fun onAllAuthenticatorsRegistered(
sensors: List<FingerprintSensorPropertiesInternal>
) {
- if (sensors.isNotEmpty()) {
- setProperties(sensors[0])
- trySendWithFailureLogging(true, TAG, "initialize properties")
+ if (sensors.isEmpty()) {
+ trySendWithFailureLogging(
+ DEFAULT_PROPS,
+ TAG,
+ "no registered sensors, use default props"
+ )
+ } else {
+ trySendWithFailureLogging(
+ sensors[0],
+ TAG,
+ "update properties on authenticators registered"
+ )
}
}
}
fingerprintManager?.addAuthenticatorsRegisteredCallback(callback)
- trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
awaitClose {}
}
- .shareIn(scope = applicationScope, started = SharingStarted.Eagerly, replay = 1)
+ .stateIn(
+ applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = DEFAULT_PROPS,
+ )
- private val _sensorId: MutableStateFlow<Int> = MutableStateFlow(-1)
- override val sensorId: StateFlow<Int> = _sensorId.asStateFlow()
+ override val sensorId: Flow<Int> = props.map { it.sensorId }
- private val _strength: MutableStateFlow<SensorStrength> =
- MutableStateFlow(SensorStrength.CONVENIENCE)
- override val strength = _strength.asStateFlow()
+ override val strength: Flow<SensorStrength> = props.map { it.sensorStrength.toSensorStrength() }
- private val _sensorType: MutableStateFlow<FingerprintSensorType> =
- MutableStateFlow(FingerprintSensorType.UNKNOWN)
- override val sensorType = _sensorType.asStateFlow()
+ override val sensorType: Flow<FingerprintSensorType> =
+ props.map { it.sensorType.toSensorType() }
- private val _sensorLocations: MutableStateFlow<Map<String, SensorLocationInternal>> =
- MutableStateFlow(mapOf("" to SensorLocationInternal.DEFAULT))
- override val sensorLocations: StateFlow<Map<String, SensorLocationInternal>> =
- _sensorLocations.asStateFlow()
-
- private fun setProperties(prop: FingerprintSensorPropertiesInternal) {
- _sensorId.value = prop.sensorId
- _strength.value = prop.sensorStrength.toSensorStrength()
- _sensorType.value = sensorTypeIntToObject(prop.sensorType)
- _sensorLocations.value =
- prop.allLocations.associateBy { sensorLocationInternal ->
+ override val sensorLocations: Flow<Map<String, SensorLocationInternal>> =
+ props.map {
+ it.allLocations.associateBy { sensorLocationInternal ->
sensorLocationInternal.displayId
}
- }
+ }
companion object {
private const val TAG = "FingerprintPropertyRepositoryImpl"
- }
-}
-
-private fun sensorTypeIntToObject(value: Int): FingerprintSensorType {
- return when (value) {
- 0 -> FingerprintSensorType.UNKNOWN
- 1 -> FingerprintSensorType.REAR
- 2 -> FingerprintSensorType.UDFPS_ULTRASONIC
- 3 -> FingerprintSensorType.UDFPS_OPTICAL
- 4 -> FingerprintSensorType.POWER_BUTTON
- 5 -> FingerprintSensorType.HOME_BUTTON
- else -> throw IllegalArgumentException("Invalid SensorType value: $value")
+ private val DEFAULT_PROPS =
+ FingerprintSensorPropertiesInternal(
+ -1 /* sensorId */,
+ SensorProperties.STRENGTH_CONVENIENCE,
+ 0 /* maxEnrollmentsPerUser */,
+ listOf<ComponentInfoInternal>(),
+ FingerprintSensorProperties.TYPE_UNKNOWN,
+ false /* halControlsIllumination */,
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT)
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/RearDisplayStateRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/RearDisplayStateRepository.kt
deleted file mode 100644
index d17d961..0000000
--- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/RearDisplayStateRepository.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.biometrics.data.repository
-
-import android.content.Context
-import android.hardware.devicestate.DeviceStateManager
-import com.android.internal.util.ArrayUtils
-import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.stateIn
-
-/** Provide current rear display state. */
-interface RearDisplayStateRepository {
- /** Provides the current rear display state. */
- val isInRearDisplayMode: StateFlow<Boolean>
-}
-
-@SysUISingleton
-class RearDisplayStateRepositoryImpl
-@Inject
-constructor(
- @Application applicationScope: CoroutineScope,
- @Application context: Context,
- deviceStateManager: DeviceStateManager,
- @Main mainExecutor: Executor
-) : RearDisplayStateRepository {
- override val isInRearDisplayMode: StateFlow<Boolean> =
- conflatedCallbackFlow {
- val sendRearDisplayStateUpdate = { state: Boolean ->
- trySendWithFailureLogging(
- state,
- TAG,
- "Error sending rear display state update to $state"
- )
- }
-
- val callback =
- DeviceStateManager.DeviceStateCallback { state ->
- val isInRearDisplayMode =
- ArrayUtils.contains(
- context.resources.getIntArray(
- com.android.internal.R.array.config_rearDisplayDeviceStates
- ),
- state
- )
- sendRearDisplayStateUpdate(isInRearDisplayMode)
- }
-
- sendRearDisplayStateUpdate(false)
- deviceStateManager.registerCallback(mainExecutor, callback)
- awaitClose { deviceStateManager.unregisterCallback(callback) }
- }
- .stateIn(
- applicationScope,
- started = SharingStarted.Eagerly,
- initialValue = false,
- )
-
- companion object {
- const val TAG = "RearDisplayStateRepositoryImpl"
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt
index 26b6f2a..6fe79c6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt
@@ -18,7 +18,8 @@
import android.content.Context
import android.content.res.Configuration
-import com.android.systemui.biometrics.data.repository.RearDisplayStateRepository
+import com.android.systemui.biometrics.data.repository.DisplayStateRepository
+import com.android.systemui.biometrics.shared.model.DisplayRotation
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.qualifiers.Application
@@ -43,6 +44,9 @@
/** Whether the device is currently folded. */
val isFolded: Flow<Boolean>
+ /** Current rotation of the display */
+ val currentRotation: StateFlow<DisplayRotation>
+
/** Called on configuration changes, used to keep the display state in sync */
fun onConfigurationChanged(newConfig: Configuration)
}
@@ -54,7 +58,7 @@
@Application applicationScope: CoroutineScope,
@Application context: Context,
@Main mainExecutor: Executor,
- rearDisplayStateRepository: RearDisplayStateRepository,
+ displayStateRepository: DisplayStateRepository,
) : DisplayStateInteractor {
private var screenSizeFoldProvider: ScreenSizeFoldProvider = ScreenSizeFoldProvider(context)
@@ -90,7 +94,10 @@
)
override val isInRearDisplayMode: StateFlow<Boolean> =
- rearDisplayStateRepository.isInRearDisplayMode
+ displayStateRepository.isInRearDisplayMode
+
+ override val currentRotation: StateFlow<DisplayRotation> =
+ displayStateRepository.currentRotation
override fun onConfigurationChanged(newConfig: Configuration) {
screenSizeFoldProvider.onConfigurationChange(newConfig)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt
index 5badcaf..a6ad24e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt
@@ -32,7 +32,6 @@
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
@@ -69,7 +68,7 @@
val isConfirmationRequired: Flow<Boolean>
/** Fingerprint sensor type */
- val sensorType: StateFlow<FingerprintSensorType>
+ val sensorType: Flow<FingerprintSensorType>
/** Use biometrics for authentication. */
fun useBiometricsForAuthentication(
@@ -95,7 +94,7 @@
class PromptSelectorInteractorImpl
@Inject
constructor(
- private val fingerprintPropertyRepository: FingerprintPropertyRepository,
+ fingerprintPropertyRepository: FingerprintPropertyRepository,
private val promptRepository: PromptRepository,
lockPatternUtils: LockPatternUtils,
) : PromptSelectorInteractor {
@@ -147,8 +146,7 @@
}
}
- override val sensorType: StateFlow<FingerprintSensorType> =
- fingerprintPropertyRepository.sensorType
+ override val sensorType: Flow<FingerprintSensorType> = fingerprintPropertyRepository.sensorType
override fun useBiometricsForAuthentication(
promptInfo: PromptInfo,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractor.kt
index aa85e5f3..75ae061 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractor.kt
@@ -17,32 +17,43 @@
package com.android.systemui.biometrics.domain.interactor
import android.hardware.biometrics.SensorLocationInternal
-import android.util.Log
import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
/** Business logic for SideFps overlay offsets. */
interface SideFpsOverlayInteractor {
- /** Get the corresponding offsets based on different displayId. */
- fun getOverlayOffsets(displayId: String): SensorLocationInternal
+ /** The displayId of the current display. */
+ val displayId: Flow<String>
+
+ /** Overlay offsets corresponding to given displayId. */
+ val overlayOffsets: Flow<SensorLocationInternal>
+
+ /** Called on display changes, used to keep the display state in sync */
+ fun onDisplayChanged(displayId: String)
}
@SysUISingleton
class SideFpsOverlayInteractorImpl
@Inject
-constructor(private val fingerprintPropertyRepository: FingerprintPropertyRepository) :
+constructor(fingerprintPropertyRepository: FingerprintPropertyRepository) :
SideFpsOverlayInteractor {
- override fun getOverlayOffsets(displayId: String): SensorLocationInternal {
- val offsets = fingerprintPropertyRepository.sensorLocations.value
- return if (offsets.containsKey(displayId)) {
- offsets[displayId]!!
- } else {
- Log.w(TAG, "No location specified for display: $displayId")
- offsets[""]!!
+ private val _displayId: MutableStateFlow<String> = MutableStateFlow("")
+ override val displayId: Flow<String> = _displayId.asStateFlow()
+
+ override val overlayOffsets: Flow<SensorLocationInternal> =
+ combine(displayId, fingerprintPropertyRepository.sensorLocations) { displayId, offsets ->
+ offsets[displayId] ?: SensorLocationInternal.DEFAULT
}
+
+ override fun onDisplayChanged(displayId: String) {
+ _displayId.value = displayId
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/DisplayRotation.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/DisplayRotation.kt
new file mode 100644
index 0000000..10a3e91
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/DisplayRotation.kt
@@ -0,0 +1,21 @@
+package com.android.systemui.biometrics.shared.model
+
+import android.view.Surface
+
+/** Shadows [Surface.Rotation] for kotlin use within SysUI. */
+enum class DisplayRotation {
+ ROTATION_0,
+ ROTATION_90,
+ ROTATION_180,
+ ROTATION_270,
+}
+
+/** Converts [Surface.Rotation] to corresponding [DisplayRotation] */
+fun Int.toDisplayRotation(): DisplayRotation =
+ when (this) {
+ Surface.ROTATION_0 -> DisplayRotation.ROTATION_0
+ Surface.ROTATION_90 -> DisplayRotation.ROTATION_90
+ Surface.ROTATION_180 -> DisplayRotation.ROTATION_180
+ Surface.ROTATION_270 -> DisplayRotation.ROTATION_270
+ else -> throw IllegalArgumentException("Invalid DisplayRotation value: $this")
+ }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/FingerprintSensorType.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/FingerprintSensorType.kt
index df5cefd..c6fdcb3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/FingerprintSensorType.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/FingerprintSensorType.kt
@@ -27,3 +27,15 @@
POWER_BUTTON,
HOME_BUTTON,
}
+
+/** Convert [this] to corresponding [FingerprintSensorType] */
+fun Int.toSensorType(): FingerprintSensorType =
+ when (this) {
+ FingerprintSensorProperties.TYPE_UNKNOWN -> FingerprintSensorType.UNKNOWN
+ FingerprintSensorProperties.TYPE_REAR -> FingerprintSensorType.REAR
+ FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC -> FingerprintSensorType.UDFPS_ULTRASONIC
+ FingerprintSensorProperties.TYPE_UDFPS_OPTICAL -> FingerprintSensorType.UDFPS_OPTICAL
+ FingerprintSensorProperties.TYPE_POWER_BUTTON -> FingerprintSensorType.POWER_BUTTON
+ FingerprintSensorProperties.TYPE_HOME_BUTTON -> FingerprintSensorType.HOME_BUTTON
+ else -> throw IllegalArgumentException("Invalid SensorType value: $this")
+ }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt
index 30e865e..476daac 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt
@@ -28,8 +28,8 @@
/** Convert [this] to corresponding [SensorStrength] */
fun Int.toSensorStrength(): SensorStrength =
when (this) {
- 0 -> SensorStrength.CONVENIENCE
- 1 -> SensorStrength.WEAK
- 2 -> SensorStrength.STRONG
+ SensorProperties.STRENGTH_CONVENIENCE -> SensorStrength.CONVENIENCE
+ SensorProperties.STRENGTH_WEAK -> SensorStrength.WEAK
+ SensorProperties.STRENGTH_STRONG -> SensorStrength.STRONG
else -> throw IllegalArgumentException("Invalid SensorStrength value: $this")
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index b1439fd..ce31b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -261,6 +261,18 @@
}
}
+ // set padding
+ launch {
+ viewModel.promptPadding.collect { promptPadding ->
+ view.setPadding(
+ promptPadding.left,
+ promptPadding.top,
+ promptPadding.right,
+ promptPadding.bottom
+ )
+ }
+ }
+
// configure & hide/disable buttons
launch {
viewModel.credentialKind
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModel.kt
index 9b30acb..b406ea4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModel.kt
@@ -33,7 +33,7 @@
@Inject
constructor(
private val displayStateInteractor: DisplayStateInteractor,
- private val promptSelectorInteractor: PromptSelectorInteractor,
+ promptSelectorInteractor: PromptSelectorInteractor,
) {
/** Current device rotation. */
private var rotation: Int = Surface.ROTATION_0
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index be08932..25634aa 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -15,16 +15,21 @@
*/
package com.android.systemui.biometrics.ui.viewmodel
+import android.content.Context
+import android.graphics.Rect
import android.hardware.biometrics.BiometricPrompt
import android.util.Log
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import com.android.systemui.biometrics.AuthBiometricView
+import com.android.systemui.biometrics.Utils
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
import com.android.systemui.biometrics.domain.model.BiometricModalities
import com.android.systemui.biometrics.shared.model.BiometricModality
+import com.android.systemui.biometrics.shared.model.DisplayRotation
import com.android.systemui.biometrics.shared.model.PromptKind
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION
import com.android.systemui.statusbar.VibratorHelper
@@ -49,6 +54,7 @@
private val displayStateInteractor: DisplayStateInteractor,
private val promptSelectorInteractor: PromptSelectorInteractor,
private val vibrator: VibratorHelper,
+ @Application context: Context,
private val featureFlags: FeatureFlags,
) {
/** Models UI of [BiometricPromptLayout.iconView] */
@@ -135,6 +141,23 @@
!isOverlayTouched && size.isNotSmall
}
+ /** Padding for prompt UI elements */
+ val promptPadding: Flow<Rect> =
+ combine(size, displayStateInteractor.currentRotation) { size, rotation ->
+ if (size != PromptSize.LARGE) {
+ val navBarInsets = Utils.getNavbarInsets(context)
+ if (rotation == DisplayRotation.ROTATION_90) {
+ Rect(0, 0, navBarInsets.right, 0)
+ } else if (rotation == DisplayRotation.ROTATION_270) {
+ Rect(navBarInsets.left, 0, 0, 0)
+ } else {
+ Rect(0, 0, 0, navBarInsets.bottom)
+ }
+ } else {
+ Rect(0, 0, 0, 0)
+ }
+ }
+
/** Title for the prompt. */
val title: Flow<String> =
promptSelectorInteractor.prompt.map { it?.title ?: "" }.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 0dcba50..ef0f494 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -29,6 +29,7 @@
import android.app.KeyguardManager;
import android.app.NotificationManager;
import android.app.StatsManager;
+import android.app.StatusBarManager;
import android.app.UiModeManager;
import android.app.WallpaperManager;
import android.app.admin.DevicePolicyManager;
@@ -680,4 +681,10 @@
static TextClassificationManager provideTextClassificationManager(Context context) {
return context.getSystemService(TextClassificationManager.class);
}
+
+ @Provides
+ @Singleton
+ static StatusBarManager provideStatusBarManager(Context context) {
+ return context.getSystemService(StatusBarManager.class);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 5a2c5d0..b6c50f7 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -112,14 +112,14 @@
val BUILDER_EXTRAS_OVERRIDE =
sysPropBooleanFlag(
"persist.sysui.notification.builder_extras_override",
- default = true
+ default = false
)
/** Only notify group expansion listeners when a change happens. */
// TODO(b/292213543): Tracking Bug
@JvmField
val NOTIFICATION_GROUP_EXPANSION_CHANGE =
- unreleasedFlag("notification_group_expansion_change", teamfood = true)
+ unreleasedFlag("notification_group_expansion_change")
// 200 - keyguard/lockscreen
// ** Flag retired **
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index ab294a6..2414ef98 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -763,13 +763,6 @@
}
}
}
-
- @Override
- public void onStrongAuthStateChanged(int userId) {
- if (mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
- doKeyguardLocked(null);
- }
- }
};
ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
@@ -2184,9 +2177,8 @@
* Enable the keyguard if the settings are appropriate.
*/
private void doKeyguardLocked(Bundle options) {
- // if another app is disabling us, don't show unless we're in lockdown mode
- if (!mExternallyEnabled
- && !mLockPatternUtils.isUserInLockdown(KeyguardUpdateMonitor.getCurrentUser())) {
+ // if another app is disabling us, don't show
+ if (!mExternallyEnabled) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
mNeedToReshowWhenReenabled = true;
@@ -2199,14 +2191,21 @@
// we explicitly re-set state.
if (mShowing && mKeyguardStateController.isShowing()) {
if (mPM.isInteractive() && !mHiding) {
- // It's already showing, and we're not trying to show it while the screen is off.
- // We can simply reset all of the views, but don't hide the bouncer in case the user
- // is currently interacting with it.
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing (instead, resetting) because it is "
- + "already showing, we're interactive, and we were not previously hiding. "
- + "It should be safe to short-circuit here.");
- resetStateLocked(/* hideBouncer= */ false);
- return;
+ if (mKeyguardStateController.isKeyguardGoingAway()) {
+ Log.e(TAG, "doKeyguard: we're still showing, but going away. Re-show the "
+ + "keyguard rather than short-circuiting and resetting.");
+ } else {
+ // It's already showing, and we're not trying to show it while the screen is
+ // off. We can simply reset all of the views, but don't hide the bouncer in case
+ // the user is currently interacting with it.
+ if (DEBUG) Log.d(TAG,
+ "doKeyguard: not showing (instead, resetting) because it is "
+ + "already showing, we're interactive, we were not "
+ + "previously hiding. It should be safe to short-circuit "
+ + "here.");
+ resetStateLocked(/* hideBouncer= */ false);
+ return;
+ }
} else {
// We are trying to show the keyguard while the screen is off or while we were in
// the middle of hiding - this results from race conditions involving locking while
@@ -2731,13 +2730,18 @@
setUnlockAndWakeFromDream(false, WakeAndUnlockUpdateReason.SHOW);
setPendingLock(false);
- // Force if we we're showing in the middle of hiding, to ensure we end up in the correct
- // state.
- setShowingLocked(true, mHiding /* force */);
- if (mHiding) {
- Log.d(TAG, "Forcing setShowingLocked because mHiding=true, which means we're "
- + "showing in the middle of hiding.");
+ final boolean hidingOrGoingAway =
+ mHiding || mKeyguardStateController.isKeyguardGoingAway();
+ if (hidingOrGoingAway) {
+ Log.d(TAG, "Forcing setShowingLocked because one of these is true:"
+ + "mHiding=" + mHiding
+ + ", keyguardGoingAway=" + mKeyguardStateController.isKeyguardGoingAway()
+ + ", which means we're showing in the middle of hiding.");
}
+
+ // Force if we we're showing in the middle of unlocking, to ensure we end up in the
+ // correct state.
+ setShowingLocked(true, hidingOrGoingAway /* force */);
mHiding = false;
if (!mFeatureFlags.isEnabled(Flags.KEYGUARD_WM_STATE_REFACTOR)) {
@@ -2947,7 +2951,6 @@
Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime
+ " fadeoutDuration=" + fadeoutDuration);
synchronized (KeyguardViewMediator.this) {
-
// Tell ActivityManager that we canceled the keyguard animation if
// handleStartKeyguardExitAnimation was called, but we're not hiding the keyguard,
// unless we're animating the surface behind the keyguard and will be hiding the
@@ -3215,10 +3218,13 @@
// Post layout changes to the next frame, so we don't hang at the end of the animation.
DejankUtils.postAfterTraversal(() -> {
- if (!mPM.isInteractive()) {
- Log.e(TAG, "exitKeyguardAndFinishSurfaceBehindRemoteAnimation#postAfterTraversal" +
- "Not interactive after traversal. Don't hide the keyguard. This means we " +
- "re-locked the device during unlock.");
+ if (!mPM.isInteractive() && !mPendingLock) {
+ Log.e(TAG, "exitKeyguardAndFinishSurfaceBehindRemoteAnimation#postAfterTraversal:"
+ + "mPM.isInteractive()=" + mPM.isInteractive()
+ + "mPendingLock=" + mPendingLock + "."
+ + "One of these being false means we re-locked the device during unlock. "
+ + "Do not proceed to finish keyguard exit and unlock.");
+ finishSurfaceBehindRemoteAnimation(true /* showKeyguard */);
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
index 5d7a3d4..23f50ea 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
@@ -34,6 +34,7 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.wallet.controller.QuickAccessWalletController
+import com.android.systemui.wallet.util.getPaymentCards
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -60,7 +61,7 @@
val callback =
object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) {
- val hasCards = response?.walletCards?.isNotEmpty() == true
+ val hasCards = getPaymentCards(response.walletCards)?.isNotEmpty() == true
trySendWithFailureLogging(
state(
isFeatureEnabled = isWalletAvailable(),
@@ -135,7 +136,7 @@
object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) {
continuation.resumeWith(
- Result.success(response?.walletCards ?: emptyList())
+ Result.success(getPaymentCards(response.walletCards) ?: emptyList())
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
index 053c9b5..cf64a83 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
@@ -29,7 +29,10 @@
import android.os.IBinder
import android.os.ResultReceiver
import android.os.UserHandle
+import android.util.Log
+import android.view.View
import android.view.ViewGroup
+import android.view.accessibility.AccessibilityEvent
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
@@ -40,6 +43,9 @@
import com.android.internal.app.ResolverListController
import com.android.internal.app.chooser.NotSelectableTargetInfo
import com.android.internal.app.chooser.TargetInfo
+import com.android.internal.widget.RecyclerView
+import com.android.internal.widget.RecyclerViewAccessibilityDelegate
+import com.android.internal.widget.ResolverDrawerLayout
import com.android.systemui.R
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorComponent
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorController
@@ -105,6 +111,10 @@
super.onCreate(bundle)
controller.init()
+ // we override AppList's AccessibilityDelegate set in ResolverActivity.onCreate because in
+ // our case this delegate must extend RecyclerViewAccessibilityDelegate, otherwise
+ // RecyclerView scrolling is broken
+ setAppListAccessibilityDelegate()
}
override fun onStart() {
@@ -264,7 +274,9 @@
recentsViewController.hasRecentTasks
}
- override fun shouldShowContentPreviewWhenEmpty() = shouldShowContentPreview()
+ override fun shouldShowStickyContentPreviewWhenEmpty() = shouldShowContentPreview()
+
+ override fun shouldShowServiceTargets() = false
private fun hasWorkProfile() = mMultiProfilePagerAdapter.count > 1
@@ -277,6 +289,8 @@
recentsViewController.createView(parent)
companion object {
+ const val TAG = "MediaProjectionAppSelectorActivity"
+
/**
* When EXTRA_CAPTURE_REGION_RESULT_RECEIVER is passed as intent extra the activity will
* send the [CaptureRegion] to the result receiver instead of returning media projection
@@ -313,4 +327,42 @@
putExtra(EXTRA_SELECTED_PROFILE, selectedProfile)
}
}
+
+ private fun setAppListAccessibilityDelegate() {
+ val rdl = requireViewById<ResolverDrawerLayout>(com.android.internal.R.id.contentPanel)
+ for (i in 0 until mMultiProfilePagerAdapter.count) {
+ val list =
+ mMultiProfilePagerAdapter
+ .getItem(i)
+ .rootView
+ .findViewById<View>(com.android.internal.R.id.resolver_list)
+ if (list == null || list !is RecyclerView) {
+ Log.wtf(TAG, "MediaProjection only supports RecyclerView")
+ } else {
+ list.accessibilityDelegate = RecyclerViewExpandingAccessibilityDelegate(rdl, list)
+ }
+ }
+ }
+
+ /**
+ * An a11y delegate propagating all a11y events to [AppListAccessibilityDelegate] so that it can
+ * expand drawer when needed. It needs to extend [RecyclerViewAccessibilityDelegate] because
+ * that superclass handles RecyclerView scrolling while using a11y services.
+ */
+ private class RecyclerViewExpandingAccessibilityDelegate(
+ rdl: ResolverDrawerLayout,
+ view: RecyclerView
+ ) : RecyclerViewAccessibilityDelegate(view) {
+
+ private val delegate = AppListAccessibilityDelegate(rdl)
+
+ override fun onRequestSendAccessibilityEvent(
+ host: ViewGroup,
+ child: View,
+ event: AccessibilityEvent
+ ): Boolean {
+ super.onRequestSendAccessibilityEvent(host, child, event)
+ return delegate.onRequestSendAccessibilityEvent(host, child, event)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 4be572f..d403788 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -29,6 +29,7 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
+import android.app.StatusBarManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -72,6 +73,7 @@
private final FeatureFlags mFeatureFlags;
private final Lazy<ScreenCaptureDevicePolicyResolver> mScreenCaptureDevicePolicyResolver;
+ private final StatusBarManager mStatusBarManager;
private String mPackageName;
private int mUid;
@@ -87,9 +89,11 @@
@Inject
public MediaProjectionPermissionActivity(FeatureFlags featureFlags,
- Lazy<ScreenCaptureDevicePolicyResolver> screenCaptureDevicePolicyResolver) {
+ Lazy<ScreenCaptureDevicePolicyResolver> screenCaptureDevicePolicyResolver,
+ StatusBarManager statusBarManager) {
mFeatureFlags = featureFlags;
mScreenCaptureDevicePolicyResolver = screenCaptureDevicePolicyResolver;
+ mStatusBarManager = statusBarManager;
}
@Override
@@ -311,6 +315,8 @@
// WM Shell running inside.
mUserSelectingTask = true;
startActivityAsUser(intent, UserHandle.of(ActivityManager.getCurrentUser()));
+ // close shade if it's open
+ mStatusBarManager.collapsePanels();
}
} catch (RemoteException e) {
Log.e(TAG, "Error granting projection permission", e);
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
index 282a65a..1b9784f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
@@ -22,12 +22,14 @@
import android.app.Notification.EXTRA_SUBSTITUTE_APP_NAME
import android.app.PendingIntent
import android.app.StatusBarManager
+import android.app.UriGrantsManager
import android.app.smartspace.SmartspaceAction
import android.app.smartspace.SmartspaceConfig
import android.app.smartspace.SmartspaceManager
import android.app.smartspace.SmartspaceSession
import android.app.smartspace.SmartspaceTarget
import android.content.BroadcastReceiver
+import android.content.ContentProvider
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
@@ -700,10 +702,13 @@
Log.d(TAG, "adding track for $userId from browser: $desc")
}
+ val currentEntry = mediaEntries.get(packageName)
+ val appUid = currentEntry?.appUid ?: Process.INVALID_UID
+
// Album art
var artworkBitmap = desc.iconBitmap
if (artworkBitmap == null && desc.iconUri != null) {
- artworkBitmap = loadBitmapFromUri(desc.iconUri!!)
+ artworkBitmap = loadBitmapFromUriForUser(desc.iconUri!!, userId, appUid, packageName)
}
val artworkIcon =
if (artworkBitmap != null) {
@@ -712,9 +717,7 @@
null
}
- val currentEntry = mediaEntries.get(packageName)
val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
- val appUid = currentEntry?.appUid ?: Process.INVALID_UID
val isExplicit =
desc.extras?.getLong(MediaConstants.METADATA_KEY_IS_EXPLICIT) ==
MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT
@@ -1261,6 +1264,30 @@
false
}
}
+
+ /** Returns a bitmap if the user can access the given URI, else null */
+ private fun loadBitmapFromUriForUser(
+ uri: Uri,
+ userId: Int,
+ appUid: Int,
+ packageName: String,
+ ): Bitmap? {
+ try {
+ val ugm = UriGrantsManager.getService()
+ ugm.checkGrantUriPermission_ignoreNonSystem(
+ appUid,
+ packageName,
+ ContentProvider.getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ ContentProvider.getUserIdFromUri(uri, userId)
+ )
+ return loadBitmapFromUri(uri)
+ } catch (e: SecurityException) {
+ Log.e(TAG, "Failed to get URI permission: $e")
+ }
+ return null
+ }
+
/**
* Load a bitmap from a URI
*
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
index 5d732fb..cbb7e1d 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
@@ -17,6 +17,7 @@
package com.android.systemui.mediaprojection.appselector.view
import android.app.ActivityOptions
+import android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
import android.app.IActivityTaskManager
import android.graphics.Rect
import android.os.Binder
@@ -129,6 +130,9 @@
view.width,
view.height
)
+ activityOptions.setPendingIntentBackgroundActivityStartMode(
+ MODE_BACKGROUND_ACTIVITY_START_ALLOWED
+ )
activityOptions.launchCookie = launchCookie
activityTaskManager.startActivityFromRecents(task.taskId, activityOptions.toBundle())
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 146b5f5..79e7b71 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -359,6 +359,7 @@
public void setBackgroundExecutor(Executor bgExecutor) {
mBgExecutor = bgExecutor;
+ mRotationButtonController.setBgExecutor(bgExecutor);
}
public void setDisplayTracker(DisplayTracker displayTracker) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 30218a6..26912f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -226,7 +226,7 @@
listenToMetadata(device);
} else {
stopListeningToStaleDeviceMetadata();
- batteryLevel = device.getBatteryLevel();
+ batteryLevel = device.getMinBatteryLevelWithMemberDevices();
}
if (batteryLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index 544e6ad..e382eca 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -20,6 +20,7 @@
import static android.provider.Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT;
import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE;
+import static com.android.systemui.wallet.util.WalletCardUtilsKt.getPaymentCards;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -210,7 +211,7 @@
public void onWalletCardsRetrieved(@NonNull GetWalletCardsResponse response) {
Log.i(TAG, "Successfully retrieved wallet cards.");
mIsWalletUpdating = false;
- List<WalletCard> cards = response.getWalletCards();
+ List<WalletCard> cards = getPaymentCards(response.getWalletCards());
if (cards.isEmpty()) {
Log.d(TAG, "No wallet cards exist.");
mCardViewDrawable = null;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index e41fb18..53c9a0e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -40,6 +40,7 @@
import android.view.IWindowSession;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
@@ -401,9 +402,9 @@
private void applyForceShowNavigationFlag(NotificationShadeWindowState state) {
if (state.panelExpanded || state.bouncerShowing
|| ENABLE_REMOTE_INPUT && state.remoteInputActive) {
- mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
+ mLpChanged.forciblyShownTypes |= WindowInsets.Type.navigationBars();
} else {
- mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
+ mLpChanged.forciblyShownTypes &= ~WindowInsets.Type.navigationBars();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 798f2d5..b4de914 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -36,6 +36,7 @@
import com.android.keyguard.LockIconViewController;
import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.back.domain.interactor.BackActionInteractor;
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
import com.android.systemui.bouncer.ui.binder.KeyguardBouncerViewBinder;
@@ -288,7 +289,7 @@
}
if (mExpandAnimationRunning) {
if (isDown && mClock.uptimeMillis() > mLaunchAnimationTimeout) {
- mShadeLogger.d("NSWVC: launch animation timed out");
+ Log.wtf(TAG, "NSWVC: launch animation timed out");
setExpandAnimationRunning(false);
} else {
return logDownDispatch(ev, "expand animation running", false);
@@ -545,6 +546,10 @@
@VisibleForTesting
void setExpandAnimationRunning(boolean running) {
if (mExpandAnimationRunning != running) {
+ // TODO(b/288507023): Remove this log.
+ if (ActivityLaunchAnimator.DEBUG_LAUNCH_ANIMATION) {
+ Log.d(TAG, "Setting mExpandAnimationRunning=" + running);
+ }
if (running) {
mLaunchAnimationTimeout = mClock.uptimeMillis() + 5000;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
index 91547a4..a08cd3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification
+import android.util.Log
import android.view.ViewGroup
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.animation.ActivityLaunchAnimator
@@ -30,6 +31,8 @@
import kotlin.math.ceil
import kotlin.math.max
+private const val TAG = "NotificationLaunchAnimatorController"
+
/** A provider of [NotificationLaunchAnimatorController]. */
@CentralSurfacesComponent.CentralSurfacesScope
class NotificationLaunchAnimatorControllerProvider @Inject constructor(
@@ -89,28 +92,33 @@
val clipStartLocation = notificationListContainer.topClippingStartLocation
val roundedTopClipping = (clipStartLocation - location[1]).coerceAtLeast(0)
val windowTop = location[1] + roundedTopClipping
- val topCornerRadius = if (roundedTopClipping > 0) {
- // Because the rounded Rect clipping is complex, we start the top rounding at
- // 0, which is pretty close to matching the real clipping.
- // We'd have to clipOut the overlaid drawable too with the outer rounded rect in case
- // if we'd like to have this perfect, but this is close enough.
- 0f
- } else {
- notification.topCornerRadius
- }
- val params = LaunchAnimationParameters(
- top = windowTop,
- bottom = location[1] + height,
- left = location[0],
- right = location[0] + notification.width,
- topCornerRadius = topCornerRadius,
- bottomCornerRadius = notification.bottomCornerRadius
- )
+ val topCornerRadius =
+ if (roundedTopClipping > 0) {
+ // Because the rounded Rect clipping is complex, we start the top rounding at
+ // 0, which is pretty close to matching the real clipping.
+ // We'd have to clipOut the overlaid drawable too with the outer rounded rect in
+ // case
+ // if we'd like to have this perfect, but this is close enough.
+ 0f
+ } else {
+ notification.topCornerRadius
+ }
+ val params =
+ LaunchAnimationParameters(
+ top = windowTop,
+ bottom = location[1] + height,
+ left = location[0],
+ right = location[0] + notification.width,
+ topCornerRadius = topCornerRadius,
+ bottomCornerRadius = notification.bottomCornerRadius
+ )
params.startTranslationZ = notification.translationZ
params.startNotificationTop = location[1]
- params.notificationParentTop = notificationListContainer
- .getViewParentForNotification(notificationEntry).locationOnScreen[1]
+ params.notificationParentTop =
+ notificationListContainer
+ .getViewParentForNotification(notificationEntry)
+ .locationOnScreen[1]
params.startRoundedTopClipping = roundedTopClipping
params.startClipTopAmount = notification.clipTopAmount
if (notification.isChildInGroup) {
@@ -135,6 +143,9 @@
}
override fun onIntentStarted(willAnimate: Boolean) {
+ if (ActivityLaunchAnimator.DEBUG_LAUNCH_ANIMATION) {
+ Log.d(TAG, "onIntentStarted(willAnimate=$willAnimate)")
+ }
notificationExpansionRepository.setIsExpandAnimationRunning(willAnimate)
notificationEntry.isExpandAnimationRunning = willAnimate
@@ -165,6 +176,10 @@
}
override fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean?) {
+ if (ActivityLaunchAnimator.DEBUG_LAUNCH_ANIMATION) {
+ Log.d(TAG, "onLaunchAnimationCancelled()")
+ }
+
// TODO(b/184121838): Should we call InteractionJankMonitor.cancel if the animation started
// here?
notificationExpansionRepository.setIsExpandAnimationRunning(false)
@@ -177,11 +192,13 @@
notification.isExpandAnimationRunning = true
notificationListContainer.setExpandingNotification(notification)
- jankMonitor.begin(notification,
- InteractionJankMonitor.CUJ_NOTIFICATION_APP_START)
+ jankMonitor.begin(notification, InteractionJankMonitor.CUJ_NOTIFICATION_APP_START)
}
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
+ if (ActivityLaunchAnimator.DEBUG_LAUNCH_ANIMATION) {
+ Log.d(TAG, "onLaunchAnimationEnd()")
+ }
jankMonitor.end(InteractionJankMonitor.CUJ_NOTIFICATION_APP_START)
notification.isExpandAnimationRunning = false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/NotificationExpansionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/NotificationExpansionRepository.kt
index f605bdf..6f0a97a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/NotificationExpansionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/NotificationExpansionRepository.kt
@@ -16,12 +16,16 @@
package com.android.systemui.statusbar.notification.data.repository
+import android.util.Log
+import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
+private const val TAG = "NotificationExpansionRepository"
+
/** A repository tracking the status of notification expansion animations. */
@SysUISingleton
class NotificationExpansionRepository @Inject constructor() {
@@ -37,6 +41,9 @@
/** Sets whether the notification expansion animation is currently running. */
fun setIsExpandAnimationRunning(running: Boolean) {
+ if (ActivityLaunchAnimator.DEBUG_LAUNCH_ANIMATION) {
+ Log.d(TAG, "setIsExpandAnimationRunning(running=$running)")
+ }
_isExpandAnimationRunning.value = running
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManager.java
index 51eb9f7..c24e9dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManager.java
@@ -36,7 +36,7 @@
@SysUISingleton
public class NotifInflationErrorManager {
- Set<NotificationEntry> mErroredNotifs = new ArraySet<>();
+ Set<String> mErroredNotifs = new ArraySet<>();
List<NotifInflationErrorListener> mListeners = new ArrayList<>();
@Inject
@@ -48,7 +48,7 @@
* @param e the exception encountered while inflating
*/
public void setInflationError(NotificationEntry entry, Exception e) {
- mErroredNotifs.add(entry);
+ mErroredNotifs.add(entry.getKey());
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).onNotifInflationError(entry, e);
}
@@ -58,8 +58,8 @@
* Notification inflated successfully and is no longer errored out.
*/
public void clearInflationError(NotificationEntry entry) {
- if (mErroredNotifs.contains(entry)) {
- mErroredNotifs.remove(entry);
+ if (mErroredNotifs.contains(entry.getKey())) {
+ mErroredNotifs.remove(entry.getKey());
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).onNotifInflationErrorCleared(entry);
}
@@ -70,7 +70,7 @@
* Whether or not the notification encountered an exception while inflating.
*/
public boolean hasInflationError(@NonNull NotificationEntry entry) {
- return mErroredNotifs.contains(entry);
+ return mErroredNotifs.contains(entry.getKey());
}
/**
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 6db8df9..05f837b 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
@@ -1662,8 +1662,9 @@
@VisibleForTesting
void onKeyguardTransitionChanged(TransitionStep transitionStep) {
- boolean isTransitionToAod = transitionStep.getFrom().equals(KeyguardState.GONE)
- && transitionStep.getTo().equals(KeyguardState.AOD);
+ boolean isTransitionToAod = transitionStep.getTo().equals(KeyguardState.AOD)
+ && (transitionStep.getFrom().equals(KeyguardState.GONE)
+ || transitionStep.getFrom().equals(KeyguardState.OCCLUDED));
if (mIsInTransitionToAod != isTransitionToAod) {
mIsInTransitionToAod = isTransitionToAod;
updateShowEmptyShadeView();
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 ccb87bf..a243356 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -624,7 +624,7 @@
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
- private final NotificationPresenter mPresenter;
+ private final Lazy<NotificationPresenter> mPresenterLazy;
private NotificationActivityStarter mNotificationActivityStarter;
private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
private final Optional<Bubbles> mBubblesOptional;
@@ -725,7 +725,8 @@
Lazy<NotificationShadeWindowViewController> notificationShadeWindowViewControllerLazy,
NotificationShelfController notificationShelfController,
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
- NotificationPresenter notificationPresenter,
+ // Lazy due to b/298099682.
+ Lazy<NotificationPresenter> notificationPresenterLazy,
NotificationExpansionRepository notificationExpansionRepository,
DozeParameters dozeParameters,
ScrimController scrimController,
@@ -833,7 +834,7 @@
mStackScrollerController = notificationStackScrollLayoutController;
mStackScroller = mStackScrollerController.getView();
mNotifListContainer = mStackScrollerController.getNotificationListContainer();
- mPresenter = notificationPresenter;
+ mPresenterLazy = notificationPresenterLazy;
mNotificationExpansionRepository = notificationExpansionRepository;
mDozeServiceHost = dozeServiceHost;
mPowerManager = powerManager;
@@ -1556,9 +1557,9 @@
mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController);
mStackScrollerController.setNotificationActivityStarter(mNotificationActivityStarter);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
- mShadeController.setNotificationPresenter(mPresenter);
+ mShadeController.setNotificationPresenter(mPresenterLazy.get());
mNotificationsController.initialize(
- mPresenter,
+ mPresenterLazy.get(),
mNotifListContainer,
mStackScrollerController.getNotifStackController(),
mNotificationActivityStarter);
@@ -1736,12 +1737,12 @@
@Override
public boolean isDeviceInVrMode() {
- return mPresenter.isDeviceInVrMode();
+ return mPresenterLazy.get().isDeviceInVrMode();
}
@Override
public NotificationPresenter getPresenter() {
- return mPresenter;
+ return mPresenterLazy.get();
}
@VisibleForTesting
@@ -2148,7 +2149,7 @@
String action = intent.getAction();
if (ACTION_FAKE_ARTWORK.equals(action)) {
if (DEBUG_MEDIA_FAKE_ARTWORK) {
- mPresenter.updateMediaMetaData(true, true);
+ mPresenterLazy.get().updateMediaMetaData(true, true);
}
}
}
@@ -2234,10 +2235,10 @@
*/
boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
boolean clearNotificationEffects =
- !mPresenter.isPresenterFullyCollapsed() && (mState == StatusBarState.SHADE
+ !mPresenterLazy.get().isPresenterFullyCollapsed() && (mState == StatusBarState.SHADE
|| mState == StatusBarState.SHADE_LOCKED);
int notificationLoad = mNotificationsController.getActiveNotificationsCount();
- if (pinnedHeadsUp && mPresenter.isPresenterFullyCollapsed()) {
+ if (pinnedHeadsUp && mPresenterLazy.get().isPresenterFullyCollapsed()) {
notificationLoad = 1;
}
final int finalNotificationLoad = notificationLoad;
@@ -2405,7 +2406,7 @@
releaseGestureWakeLock();
runLaunchTransitionEndRunnable();
mKeyguardStateController.setLaunchTransitionFadingAway(false);
- mPresenter.updateMediaMetaData(true /* metaDataChanged */, true);
+ mPresenterLazy.get().updateMediaMetaData(true /* metaDataChanged */, true);
}
/**
@@ -2429,7 +2430,7 @@
beforeFading.run();
}
updateScrimController();
- mPresenter.updateMediaMetaData(false, true);
+ mPresenterLazy.get().updateMediaMetaData(false, true);
mShadeSurface.resetAlpha();
mShadeSurface.fadeOut(
FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION,
@@ -3564,7 +3565,8 @@
updateDozingState();
checkBarModes();
updateScrimController();
- mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
+ mPresenterLazy.get()
+ .updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 83a040c..1966033 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -40,6 +40,7 @@
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
+import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.user.ui.binder.StatusBarUserChipViewBinder;
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
import com.android.systemui.util.leak.RotationUtils;
@@ -51,7 +52,7 @@
private final StatusBarContentInsetsProvider mContentInsetsProvider;
private DarkReceiver mBattery;
- private DarkReceiver mClock;
+ private Clock mClock;
private int mRotationOrientation = -1;
@Nullable
private View mCutoutSpace;
@@ -123,6 +124,10 @@
}
}
+ void onDensityOrFontScaleChanged() {
+ mClock.onDensityOrFontScaleChanged();
+ }
+
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (updateDisplayParameters()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index 4de669c..85a75ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -71,12 +71,20 @@
override fun onConfigChanged(newConfig: Configuration?) {
mView.updateResources()
}
+
+ override fun onDensityOrFontScaleChanged() {
+ mView.onDensityOrFontScaleChanged()
+ }
}
override fun onViewAttached() {
statusContainer = mView.requireViewById(R.id.system_icons)
statusContainer.setOnHoverListener(
statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer))
+
+ progressProvider?.setReadyToHandleTransition(true)
+ configurationController.addCallback(configurationListener)
+
if (moveFromCenterAnimationController == null) return
val statusBarLeftSide: View =
@@ -103,9 +111,6 @@
moveFromCenterAnimationController.onStatusBarWidthChanged()
}
}
-
- progressProvider?.setReadyToHandleTransition(true)
- configurationController.addCallback(configurationListener)
}
override fun onViewDetached() {
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 62a8cfd..b0f8276 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -763,7 +763,7 @@
* Sets the amount of vertical over scroll that should be performed on the notifications scrim.
*/
public void setNotificationsOverScrollAmount(int overScrollAmount) {
- mNotificationsScrim.setTranslationY(overScrollAmount);
+ if (mNotificationsScrim != null) mNotificationsScrim.setTranslationY(overScrollAmount);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
index 4b2fb43..6483b7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
@@ -19,7 +19,6 @@
import android.content.res.ColorStateList
import android.view.View
import android.view.View.GONE
-import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import android.view.ViewGroup
import android.widget.ImageView
@@ -33,12 +32,11 @@
import com.android.systemui.common.ui.binder.IconViewBinder
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.statusbar.StatusBarIconView
-import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
-import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewBinding
+import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewVisibilityHelper
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -83,20 +81,11 @@
launch {
visibilityState.collect { state ->
- when (state) {
- STATE_ICON -> {
- mobileGroupView.visibility = VISIBLE
- dotView.visibility = GONE
- }
- STATE_DOT -> {
- mobileGroupView.visibility = INVISIBLE
- dotView.visibility = VISIBLE
- }
- STATE_HIDDEN -> {
- mobileGroupView.visibility = INVISIBLE
- dotView.visibility = INVISIBLE
- }
- }
+ ModernStatusBarViewVisibilityHelper.setVisibilityState(
+ state,
+ mobileGroupView,
+ dotView,
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewVisibilityHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewVisibilityHelper.kt
new file mode 100644
index 0000000..6668cbc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewVisibilityHelper.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.ui.binder
+
+import android.view.View
+import com.android.systemui.statusbar.StatusBarIconView
+import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconBinder
+import com.android.systemui.statusbar.pipeline.wifi.ui.binder.WifiViewBinder
+
+/**
+ * The helper to update the groupView and dotView visibility based on given visibility state, only
+ * used for [MobileIconBinder] and [WifiViewBinder] now.
+ */
+class ModernStatusBarViewVisibilityHelper {
+ companion object {
+
+ fun setVisibilityState(
+ @StatusBarIconView.VisibleState state: Int,
+ groupView: View,
+ dotView: View,
+ ) {
+ when (state) {
+ StatusBarIconView.STATE_ICON -> {
+ groupView.visibility = View.VISIBLE
+ dotView.visibility = View.GONE
+ }
+ StatusBarIconView.STATE_DOT -> {
+ groupView.visibility = View.INVISIBLE
+ dotView.visibility = View.VISIBLE
+ }
+ StatusBarIconView.STATE_HIDDEN -> {
+ groupView.visibility = View.INVISIBLE
+ dotView.visibility = View.INVISIBLE
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
index 3082a66..e593575 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
@@ -27,10 +27,9 @@
import com.android.systemui.common.ui.binder.IconViewBinder
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.statusbar.StatusBarIconView
-import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
-import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewBinding
+import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewVisibilityHelper
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
import kotlinx.coroutines.InternalCoroutinesApi
@@ -83,8 +82,18 @@
launch {
visibilityState.collect { visibilityState ->
- groupView.isVisible = visibilityState == STATE_ICON
- dotView.isVisible = visibilityState == STATE_DOT
+ // for b/296864006, we can not hide all the child views if visibilityState
+ // is STATE_HIDDEN. Because hiding all child views would cause the
+ // getWidth() of this view return 0, and that would cause the translation
+ // calculation fails in StatusIconContainer. Therefore, like class
+ // MobileIconBinder, instead of set the child views visibility to View.GONE,
+ // we set their visibility to View.INVISIBLE to make them invisible but
+ // keep the width.
+ ModernStatusBarViewVisibilityHelper.setVisibilityState(
+ visibilityState,
+ groupView,
+ dotView,
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index f994372..b7ae233 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -37,9 +37,11 @@
import android.text.style.CharacterStyle;
import android.text.style.RelativeSizeSpan;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.TextView;
import com.android.settingslib.Utils;
@@ -143,6 +145,8 @@
}
mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
mUserTracker = Dependency.get(UserTracker.class);
+
+ setIncludeFontPadding(false);
}
@Override
@@ -389,6 +393,15 @@
mContext.getResources().getDimensionPixelSize(
R.dimen.status_bar_clock_end_padding),
0);
+
+ float fontHeight = getPaint().getFontMetricsInt(null);
+ setLineHeight(TypedValue.COMPLEX_UNIT_PX, fontHeight);
+
+ ViewGroup.LayoutParams lp = getLayoutParams();
+ if (lp != null) {
+ lp.height = (int) Math.ceil(fontHeight);
+ setLayoutParams(lp);
+ }
}
private void updateShowSeconds() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
index 24987ab..f4cc0ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
@@ -21,7 +21,6 @@
import static android.view.WindowInsets.Type.tappableElement;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
@@ -44,6 +43,7 @@
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.WindowManager;
import com.android.internal.policy.SystemBarUtils;
@@ -361,9 +361,9 @@
|| state.mIsLaunchAnimationRunning
// Don't force-show the status bar if the user has already dismissed it.
|| state.mOngoingProcessRequiresStatusBarVisible) {
- mLpChanged.privateFlags |= PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
+ mLpChanged.forciblyShownTypes |= WindowInsets.Type.statusBars();
} else {
- mLpChanged.privateFlags &= ~PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
+ mLpChanged.forciblyShownTypes &= ~WindowInsets.Type.statusBars();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
index 81d04d4..6fd0a4d 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
@@ -16,6 +16,8 @@
package com.android.systemui.wallet.ui;
+import static com.android.systemui.wallet.util.WalletCardUtilsKt.getPaymentCards;
+
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -47,10 +49,10 @@
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
/** Controller for the wallet card carousel screen. */
public class WalletScreenController implements
@@ -126,22 +128,11 @@
return;
}
Log.i(TAG, "Successfully retrieved wallet cards.");
- List<WalletCard> walletCards = response.getWalletCards();
+ List<WalletCard> walletCards = getPaymentCards(response.getWalletCards());
- boolean allUnknown = true;
- for (WalletCard card : walletCards) {
- if (card.getCardType() != WalletCard.CARD_TYPE_UNKNOWN) {
- allUnknown = false;
- break;
- }
- }
-
- List<WalletCardViewInfo> paymentCardData = new ArrayList<>();
- for (WalletCard card : walletCards) {
- if (allUnknown || card.getCardType() == WalletCard.CARD_TYPE_PAYMENT) {
- paymentCardData.add(new QAWalletCardViewInfo(mContext, card));
- }
- }
+ List<WalletCardViewInfo> paymentCardData = walletCards.stream().map(
+ card -> new QAWalletCardViewInfo(mContext, card)
+ ).collect(Collectors.toList());
// Get on main thread for UI updates.
mHandler.post(() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/util/WalletCardUtils.kt b/packages/SystemUI/src/com/android/systemui/wallet/util/WalletCardUtils.kt
new file mode 100644
index 0000000..077b80b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/wallet/util/WalletCardUtils.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.wallet.util
+
+import android.service.quickaccesswallet.WalletCard
+
+/**
+ * Filters wallet cards to only those of [WalletCard.CARD_TYPE_PAYMENT], or returns all cards if
+ * they are all of [WalletCard.CARD_TYPE_UNKNOWN] (maintaining pre-U behavior). Used by the wallet
+ * card carousel, quick settings tile, and lock screen.
+ */
+fun getPaymentCards(walletCards: List<WalletCard>): List<WalletCard> {
+ val atLeastOneKnownCardType = walletCards.any { it.cardType != WalletCard.CARD_TYPE_UNKNOWN }
+
+ return if (atLeastOneKnownCardType) {
+ walletCards.filter { it.cardType == WalletCard.CARD_TYPE_PAYMENT }
+ } else {
+ walletCards
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index e96ad87..7ac8092 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -712,6 +712,245 @@
}
@Test
+ public void windowWidthIsNotMax_performA11yActionIncreaseWidth_windowWidthIncreased() {
+ final Rect windowBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
+ final int startingWidth = (int) (windowBounds.width() * 0.8);
+ final int startingHeight = (int) (windowBounds.height() * 0.8);
+ final float changeWindowSizeAmount = mContext.getResources().getFraction(
+ R.fraction.magnification_resize_window_size_amount,
+ /* base= */ 1,
+ /* pbase= */ 1);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+ Float.NaN);
+ mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
+ mWindowMagnificationController.setEditMagnifierSizeMode(true);
+ });
+
+ final View mirrorView = mWindowManager.getAttachedView();
+ final AtomicInteger actualWindowHeight = new AtomicInteger();
+ final AtomicInteger actualWindowWidth = new AtomicInteger();
+
+ mInstrumentation.runOnMainSync(
+ () -> {
+ mirrorView.performAccessibilityAction(
+ R.id.accessibility_action_increase_window_width, null);
+ actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height);
+ actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width);
+ });
+
+ final int mirrorSurfaceMargin = mResources.getDimensionPixelSize(
+ R.dimen.magnification_mirror_surface_margin);
+ // Window width includes the magnifier frame and the margin. Increasing the window size
+ // will be increasing the amount of the frame size only.
+ int newWindowWidth =
+ (int) ((startingWidth - 2 * mirrorSurfaceMargin) * (1 + changeWindowSizeAmount))
+ + 2 * mirrorSurfaceMargin;
+ assertEquals(newWindowWidth, actualWindowWidth.get());
+ assertEquals(startingHeight, actualWindowHeight.get());
+ }
+
+ @Test
+ public void windowHeightIsNotMax_performA11yActionIncreaseHeight_windowHeightIncreased() {
+ final Rect windowBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
+ final int startingWidth = (int) (windowBounds.width() * 0.8);
+ final int startingHeight = (int) (windowBounds.height() * 0.8);
+ final float changeWindowSizeAmount = mContext.getResources().getFraction(
+ R.fraction.magnification_resize_window_size_amount,
+ /* base= */ 1,
+ /* pbase= */ 1);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+ Float.NaN);
+ mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
+ mWindowMagnificationController.setEditMagnifierSizeMode(true);
+ });
+
+ final View mirrorView = mWindowManager.getAttachedView();
+ final AtomicInteger actualWindowHeight = new AtomicInteger();
+ final AtomicInteger actualWindowWidth = new AtomicInteger();
+
+ mInstrumentation.runOnMainSync(
+ () -> {
+ mirrorView.performAccessibilityAction(
+ R.id.accessibility_action_increase_window_height, null);
+ actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height);
+ actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width);
+ });
+
+ final int mirrorSurfaceMargin = mResources.getDimensionPixelSize(
+ R.dimen.magnification_mirror_surface_margin);
+ // Window height includes the magnifier frame and the margin. Increasing the window size
+ // will be increasing the amount of the frame size only.
+ int newWindowHeight =
+ (int) ((startingHeight - 2 * mirrorSurfaceMargin) * (1 + changeWindowSizeAmount))
+ + 2 * mirrorSurfaceMargin;
+ assertEquals(startingWidth, actualWindowWidth.get());
+ assertEquals(newWindowHeight, actualWindowHeight.get());
+ }
+
+ @Test
+ public void windowWidthIsMax_noIncreaseWindowWidthA11yAction() {
+ final Rect windowBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
+ final int startingWidth = windowBounds.width();
+ final int startingHeight = windowBounds.height();
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+ Float.NaN);
+ mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
+ mWindowMagnificationController.setEditMagnifierSizeMode(true);
+ });
+
+ final View mirrorView = mWindowManager.getAttachedView();
+ final AccessibilityNodeInfo accessibilityNodeInfo =
+ mirrorView.createAccessibilityNodeInfo();
+ assertFalse(accessibilityNodeInfo.getActionList().contains(
+ new AccessibilityAction(R.id.accessibility_action_increase_window_width, null)));
+ }
+
+ @Test
+ public void windowHeightIsMax_noIncreaseWindowHeightA11yAction() {
+ final Rect windowBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
+ final int startingWidth = windowBounds.width();
+ final int startingHeight = windowBounds.height();
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+ Float.NaN);
+ mWindowMagnificationController.setWindowSize(startingWidth, startingHeight);
+ mWindowMagnificationController.setEditMagnifierSizeMode(true);
+ });
+
+ final View mirrorView = mWindowManager.getAttachedView();
+ final AccessibilityNodeInfo accessibilityNodeInfo =
+ mirrorView.createAccessibilityNodeInfo();
+ assertFalse(accessibilityNodeInfo.getActionList().contains(
+ new AccessibilityAction(R.id.accessibility_action_increase_window_height, null)));
+ }
+
+ @Test
+ public void windowWidthIsNotMin_performA11yActionDecreaseWidth_windowWidthDecreased() {
+ int mMinWindowSize = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
+ final int startingSize = (int) (mMinWindowSize * 1.1);
+ final float changeWindowSizeAmount = mContext.getResources().getFraction(
+ R.fraction.magnification_resize_window_size_amount,
+ /* base= */ 1,
+ /* pbase= */ 1);
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+ Float.NaN);
+ mWindowMagnificationController.setWindowSize(startingSize, startingSize);
+ mWindowMagnificationController.setEditMagnifierSizeMode(true);
+ });
+
+ final View mirrorView = mWindowManager.getAttachedView();
+ final AtomicInteger actualWindowHeight = new AtomicInteger();
+ final AtomicInteger actualWindowWidth = new AtomicInteger();
+
+ mInstrumentation.runOnMainSync(
+ () -> {
+ mirrorView.performAccessibilityAction(
+ R.id.accessibility_action_decrease_window_width, null);
+ actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height);
+ actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width);
+ });
+
+ final int mirrorSurfaceMargin = mResources.getDimensionPixelSize(
+ R.dimen.magnification_mirror_surface_margin);
+ // Window width includes the magnifier frame and the margin. Decreasing the window size
+ // will be decreasing the amount of the frame size only.
+ int newWindowWidth =
+ (int) ((startingSize - 2 * mirrorSurfaceMargin) * (1 - changeWindowSizeAmount))
+ + 2 * mirrorSurfaceMargin;
+ assertEquals(newWindowWidth, actualWindowWidth.get());
+ assertEquals(startingSize, actualWindowHeight.get());
+ }
+
+ @Test
+ public void windowHeightIsNotMin_performA11yActionDecreaseHeight_windowHeightDecreased() {
+ int mMinWindowSize = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
+ final int startingSize = (int) (mMinWindowSize * 1.1);
+ final float changeWindowSizeAmount = mContext.getResources().getFraction(
+ R.fraction.magnification_resize_window_size_amount,
+ /* base= */ 1,
+ /* pbase= */ 1);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+ Float.NaN);
+ mWindowMagnificationController.setWindowSize(startingSize, startingSize);
+ mWindowMagnificationController.setEditMagnifierSizeMode(true);
+ });
+
+ final View mirrorView = mWindowManager.getAttachedView();
+ final AtomicInteger actualWindowHeight = new AtomicInteger();
+ final AtomicInteger actualWindowWidth = new AtomicInteger();
+
+ mInstrumentation.runOnMainSync(
+ () -> {
+ mirrorView.performAccessibilityAction(
+ R.id.accessibility_action_decrease_window_height, null);
+ actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height);
+ actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width);
+ });
+
+ final int mirrorSurfaceMargin = mResources.getDimensionPixelSize(
+ R.dimen.magnification_mirror_surface_margin);
+ // Window height includes the magnifier frame and the margin. Decreasing the window size
+ // will be decreasing the amount of the frame size only.
+ int newWindowHeight =
+ (int) ((startingSize - 2 * mirrorSurfaceMargin) * (1 - changeWindowSizeAmount))
+ + 2 * mirrorSurfaceMargin;
+ assertEquals(startingSize, actualWindowWidth.get());
+ assertEquals(newWindowHeight, actualWindowHeight.get());
+ }
+
+ @Test
+ public void windowWidthIsMin_noDecreaseWindowWidthA11yAction() {
+ int mMinWindowSize = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
+ final int startingSize = mMinWindowSize;
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+ Float.NaN);
+ mWindowMagnificationController.setWindowSize(startingSize, startingSize);
+ mWindowMagnificationController.setEditMagnifierSizeMode(true);
+ });
+
+ final View mirrorView = mWindowManager.getAttachedView();
+ final AccessibilityNodeInfo accessibilityNodeInfo =
+ mirrorView.createAccessibilityNodeInfo();
+ assertFalse(accessibilityNodeInfo.getActionList().contains(
+ new AccessibilityAction(R.id.accessibility_action_decrease_window_width, null)));
+ }
+
+ @Test
+ public void windowHeightIsMin_noDecreaseWindowHeightA11yAcyion() {
+ int mMinWindowSize = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
+ final int startingSize = mMinWindowSize;
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
+ Float.NaN);
+ mWindowMagnificationController.setWindowSize(startingSize, startingSize);
+ mWindowMagnificationController.setEditMagnifierSizeMode(true);
+ });
+
+ final View mirrorView = mWindowManager.getAttachedView();
+ final AccessibilityNodeInfo accessibilityNodeInfo =
+ mirrorView.createAccessibilityNodeInfo();
+ assertFalse(accessibilityNodeInfo.getActionList().contains(
+ new AccessibilityAction(R.id.accessibility_action_decrease_window_height, null)));
+ }
+
+ @Test
public void enableWindowMagnification_hasA11yWindowTitle() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
@@ -1166,4 +1405,5 @@
when(mContext.getDisplay()).thenReturn(display);
return newRotation;
}
+
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 9584d88..bddc4c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -41,7 +41,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
import com.android.systemui.biometrics.data.repository.FakePromptRepository
-import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository
+import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
import com.android.systemui.biometrics.domain.interactor.FakeCredentialInteractor
import com.android.systemui.biometrics.domain.interactor.PromptCredentialInteractor
@@ -110,7 +110,7 @@
private val fakeExecutor = FakeExecutor(FakeSystemClock())
private val biometricPromptRepository = FakePromptRepository()
private val fingerprintRepository = FakeFingerprintPropertyRepository()
- private val rearDisplayStateRepository = FakeRearDisplayStateRepository()
+ private val displayStateRepository = FakeDisplayStateRepository()
private val credentialInteractor = FakeCredentialInteractor()
private val bpCredentialInteractor = PromptCredentialInteractor(
Dispatchers.Main.immediate,
@@ -129,7 +129,7 @@
testScope.backgroundScope,
mContext,
fakeExecutor,
- rearDisplayStateRepository
+ displayStateRepository
)
@@ -531,6 +531,7 @@
displayStateInteractor,
promptSelectorInteractor,
vibrator,
+ context,
featureFlags
),
{ credentialViewModel },
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index 994db46..c71ef47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -56,7 +56,7 @@
import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestableContext
-import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository
+import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
@@ -120,7 +120,7 @@
private lateinit var displayStateInteractor: DisplayStateInteractor
private val executor = FakeExecutor(FakeSystemClock())
- private val rearDisplayStateRepository = FakeRearDisplayStateRepository()
+ private val displayStateRepository = FakeDisplayStateRepository()
private val testScope = TestScope(StandardTestDispatcher())
private lateinit var overlayController: ISidefpsController
@@ -157,7 +157,7 @@
testScope.backgroundScope,
context,
executor,
- rearDisplayStateRepository
+ displayStateRepository
)
context.addMockSystemService(DisplayManager::class.java, displayManager)
@@ -268,7 +268,7 @@
TestCoroutineScope(),
dumpManager
)
- rearDisplayStateRepository.setIsInRearDisplayMode(inRearDisplayMode)
+ displayStateRepository.setIsInRearDisplayMode(inRearDisplayMode)
overlayController =
ArgumentCaptor.forClass(ISidefpsController::class.java)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/DisplayStateRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/DisplayStateRepositoryTest.kt
new file mode 100644
index 0000000..c9c46cb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/DisplayStateRepositoryTest.kt
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.data.repository
+
+import android.hardware.devicestate.DeviceStateManager
+import android.hardware.display.DisplayManager
+import android.os.Handler
+import android.view.Display
+import android.view.DisplayInfo
+import android.view.Surface
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.data.repository.DisplayStateRepository
+import com.android.systemui.biometrics.data.repository.DisplayStateRepositoryImpl
+import com.android.systemui.biometrics.shared.model.DisplayRotation
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.mockito.withArgCaptor
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.same
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+private const val NORMAL_DISPLAY_MODE_DEVICE_STATE = 2
+private const val REAR_DISPLAY_MODE_DEVICE_STATE = 3
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class DisplayStateRepositoryTest : SysuiTestCase() {
+ @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
+ @Mock private lateinit var deviceStateManager: DeviceStateManager
+ @Mock private lateinit var displayManager: DisplayManager
+ @Mock private lateinit var handler: Handler
+ @Mock private lateinit var display: Display
+ private lateinit var underTest: DisplayStateRepository
+
+ private val testScope = TestScope(StandardTestDispatcher())
+ private val fakeExecutor = FakeExecutor(FakeSystemClock())
+
+ @Captor
+ private lateinit var displayListenerCaptor: ArgumentCaptor<DisplayManager.DisplayListener>
+
+ @Before
+ fun setUp() {
+ val rearDisplayDeviceStates = intArrayOf(REAR_DISPLAY_MODE_DEVICE_STATE)
+ mContext.orCreateTestableResources.addOverride(
+ com.android.internal.R.array.config_rearDisplayDeviceStates,
+ rearDisplayDeviceStates
+ )
+
+ mContext = spy(mContext)
+ whenever(mContext.display).thenReturn(display)
+
+ underTest =
+ DisplayStateRepositoryImpl(
+ testScope.backgroundScope,
+ mContext,
+ deviceStateManager,
+ displayManager,
+ handler,
+ fakeExecutor
+ )
+ }
+
+ @Test
+ fun updatesIsInRearDisplayMode_whenRearDisplayStateChanges() =
+ testScope.runTest {
+ val isInRearDisplayMode by collectLastValue(underTest.isInRearDisplayMode)
+ runCurrent()
+
+ val callback = deviceStateManager.captureCallback()
+
+ callback.onStateChanged(NORMAL_DISPLAY_MODE_DEVICE_STATE)
+ assertThat(isInRearDisplayMode).isFalse()
+
+ callback.onStateChanged(REAR_DISPLAY_MODE_DEVICE_STATE)
+ assertThat(isInRearDisplayMode).isTrue()
+ }
+
+ @Test
+ fun updatesCurrentRotation_whenDisplayStateChanges() =
+ testScope.runTest {
+ val currentRotation by collectLastValue(underTest.currentRotation)
+ runCurrent()
+
+ verify(displayManager)
+ .registerDisplayListener(
+ displayListenerCaptor.capture(),
+ same(handler),
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED)
+ )
+
+ whenever(display.getDisplayInfo(any())).then {
+ val info = it.getArgument<DisplayInfo>(0)
+ info.rotation = Surface.ROTATION_90
+ return@then true
+ }
+ displayListenerCaptor.value.onDisplayChanged(Surface.ROTATION_90)
+ assertThat(currentRotation).isEqualTo(DisplayRotation.ROTATION_90)
+
+ whenever(display.getDisplayInfo(any())).then {
+ val info = it.getArgument<DisplayInfo>(0)
+ info.rotation = Surface.ROTATION_180
+ return@then true
+ }
+ displayListenerCaptor.value.onDisplayChanged(Surface.ROTATION_180)
+ assertThat(currentRotation).isEqualTo(DisplayRotation.ROTATION_180)
+ }
+}
+
+private fun DeviceStateManager.captureCallback() =
+ withArgCaptor<DeviceStateManager.DeviceStateCallback> {
+ verify(this@captureCallback).registerCallback(any(), capture())
+ }
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 239e317..ed9ae5e 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
@@ -29,6 +29,7 @@
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.coroutines.collectLastValue
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
@@ -44,6 +45,7 @@
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(JUnit4::class)
class FingerprintRepositoryImplTest : SysuiTestCase() {
@@ -73,10 +75,15 @@
@Test
fun initializeProperties() =
testScope.runTest {
- val isInitialized = collectLastValue(repository.isInitialized)
+ val sensorId by collectLastValue(repository.sensorId)
+ val strength by collectLastValue(repository.strength)
+ val sensorType by collectLastValue(repository.sensorType)
+ val sensorLocations by collectLastValue(repository.sensorLocations)
- assertDefaultProperties()
- assertThat(isInitialized()).isFalse()
+ // Assert default properties.
+ assertThat(sensorId).isEqualTo(-1)
+ assertThat(strength).isEqualTo(SensorStrength.CONVENIENCE)
+ assertThat(sensorType).isEqualTo(FingerprintSensorType.UNKNOWN)
val fingerprintProps =
listOf(
@@ -115,31 +122,24 @@
fingerprintAuthenticatorsCaptor.value.onAllAuthenticatorsRegistered(fingerprintProps)
- assertThat(repository.sensorId.value).isEqualTo(1)
- assertThat(repository.strength.value).isEqualTo(SensorStrength.STRONG)
- assertThat(repository.sensorType.value).isEqualTo(FingerprintSensorType.REAR)
+ assertThat(sensorId).isEqualTo(1)
+ assertThat(strength).isEqualTo(SensorStrength.STRONG)
+ assertThat(sensorType).isEqualTo(FingerprintSensorType.REAR)
- assertThat(repository.sensorLocations.value.size).isEqualTo(2)
- assertThat(repository.sensorLocations.value).containsKey("display_id_1")
- with(repository.sensorLocations.value["display_id_1"]!!) {
+ assertThat(sensorLocations?.size).isEqualTo(2)
+ assertThat(sensorLocations).containsKey("display_id_1")
+ with(sensorLocations?.get("display_id_1")!!) {
assertThat(displayId).isEqualTo("display_id_1")
assertThat(sensorLocationX).isEqualTo(100)
assertThat(sensorLocationY).isEqualTo(300)
assertThat(sensorRadius).isEqualTo(20)
}
- assertThat(repository.sensorLocations.value).containsKey("")
- with(repository.sensorLocations.value[""]!!) {
+ assertThat(sensorLocations).containsKey("")
+ with(sensorLocations?.get("")!!) {
assertThat(displayId).isEqualTo("")
assertThat(sensorLocationX).isEqualTo(540)
assertThat(sensorLocationY).isEqualTo(1636)
assertThat(sensorRadius).isEqualTo(130)
}
- assertThat(isInitialized()).isTrue()
}
-
- private fun assertDefaultProperties() {
- assertThat(repository.sensorId.value).isEqualTo(-1)
- assertThat(repository.strength.value).isEqualTo(SensorStrength.CONVENIENCE)
- assertThat(repository.sensorType.value).isEqualTo(FingerprintSensorType.UNKNOWN)
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/RearDisplayStateRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/RearDisplayStateRepositoryTest.kt
deleted file mode 100644
index dfe8d36..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/RearDisplayStateRepositoryTest.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.keyguard.data.repository
-
-import android.hardware.devicestate.DeviceStateManager
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.RearDisplayStateRepository
-import com.android.systemui.biometrics.data.repository.RearDisplayStateRepositoryImpl
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.withArgCaptor
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
-import org.mockito.Mock
-import org.mockito.Mockito.verify
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-private const val NORMAL_DISPLAY_MODE_DEVICE_STATE = 2
-private const val REAR_DISPLAY_MODE_DEVICE_STATE = 3
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@RunWith(JUnit4::class)
-class RearDisplayStateRepositoryTest : SysuiTestCase() {
- @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
- @Mock private lateinit var deviceStateManager: DeviceStateManager
- private lateinit var underTest: RearDisplayStateRepository
-
- private val testScope = TestScope(StandardTestDispatcher())
- private val fakeExecutor = FakeExecutor(FakeSystemClock())
-
- @Captor
- private lateinit var callbackCaptor: ArgumentCaptor<DeviceStateManager.DeviceStateCallback>
-
- @Before
- fun setUp() {
- val rearDisplayDeviceStates = intArrayOf(REAR_DISPLAY_MODE_DEVICE_STATE)
- mContext.orCreateTestableResources.addOverride(
- com.android.internal.R.array.config_rearDisplayDeviceStates,
- rearDisplayDeviceStates
- )
-
- underTest =
- RearDisplayStateRepositoryImpl(
- testScope.backgroundScope,
- mContext,
- deviceStateManager,
- fakeExecutor
- )
- }
-
- @Test
- fun updatesIsInRearDisplayMode_whenRearDisplayStateChanges() =
- testScope.runTest {
- val isInRearDisplayMode = collectLastValue(underTest.isInRearDisplayMode)
- runCurrent()
-
- val callback = deviceStateManager.captureCallback()
-
- callback.onStateChanged(NORMAL_DISPLAY_MODE_DEVICE_STATE)
- assertThat(isInRearDisplayMode()).isFalse()
-
- callback.onStateChanged(REAR_DISPLAY_MODE_DEVICE_STATE)
- assertThat(isInRearDisplayMode()).isTrue()
- }
-}
-
-private fun DeviceStateManager.captureCallback() =
- withArgCaptor<DeviceStateManager.DeviceStateCallback> {
- verify(this@captureCallback).registerCallback(any(), capture())
- }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt
index 2217c5c..0f84d9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractorImplTest.kt
@@ -2,7 +2,8 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository
+import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
+import com.android.systemui.biometrics.shared.model.DisplayRotation
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.unfold.compat.ScreenSizeFoldProvider
import com.android.systemui.unfold.updates.FoldProvider
@@ -34,7 +35,7 @@
private val fakeExecutor = FakeExecutor(FakeSystemClock())
private val testScope = TestScope(StandardTestDispatcher())
- private val rearDisplayStateRepository = FakeRearDisplayStateRepository()
+ private val displayStateRepository = FakeDisplayStateRepository()
@Mock private lateinit var screenSizeFoldProvider: ScreenSizeFoldProvider
private lateinit var interactor: DisplayStateInteractorImpl
@@ -46,7 +47,7 @@
testScope.backgroundScope,
mContext,
fakeExecutor,
- rearDisplayStateRepository
+ displayStateRepository
)
interactor.setScreenSizeFoldProvider(screenSizeFoldProvider)
}
@@ -56,14 +57,26 @@
testScope.runTest {
val isInRearDisplayMode = collectLastValue(interactor.isInRearDisplayMode)
- rearDisplayStateRepository.setIsInRearDisplayMode(false)
+ displayStateRepository.setIsInRearDisplayMode(false)
assertThat(isInRearDisplayMode()).isFalse()
- rearDisplayStateRepository.setIsInRearDisplayMode(true)
+ displayStateRepository.setIsInRearDisplayMode(true)
assertThat(isInRearDisplayMode()).isTrue()
}
@Test
+ fun currentRotationChanges() =
+ testScope.runTest {
+ val currentRotation = collectLastValue(interactor.currentRotation)
+
+ displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
+ assertThat(currentRotation()).isEqualTo(DisplayRotation.ROTATION_180)
+
+ displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
+ assertThat(currentRotation()).isEqualTo(DisplayRotation.ROTATION_90)
+ }
+
+ @Test
fun isFoldedChanges() =
testScope.runTest {
val isFolded = collectLastValue(interactor.isFolded)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorTest.kt
index fd96cf4..712eef1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractorTest.kt
@@ -22,6 +22,7 @@
import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
+import com.android.systemui.coroutines.collectLastValue
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
@@ -51,7 +52,7 @@
}
@Test
- fun testGetOverlayOffsets() =
+ fun testOverlayOffsetUpdates() =
testScope.runTest {
fingerprintRepository.setProperties(
sensorId = 1,
@@ -76,16 +77,32 @@
)
)
- var offsets = interactor.getOverlayOffsets("display_id_1")
- assertThat(offsets.displayId).isEqualTo("display_id_1")
- assertThat(offsets.sensorLocationX).isEqualTo(100)
- assertThat(offsets.sensorLocationY).isEqualTo(300)
- assertThat(offsets.sensorRadius).isEqualTo(20)
+ val displayId by collectLastValue(interactor.displayId)
+ val offsets by collectLastValue(interactor.overlayOffsets)
- offsets = interactor.getOverlayOffsets("invalid_display_id")
- assertThat(offsets.displayId).isEqualTo("")
- assertThat(offsets.sensorLocationX).isEqualTo(540)
- assertThat(offsets.sensorLocationY).isEqualTo(1636)
- assertThat(offsets.sensorRadius).isEqualTo(130)
+ // Assert offsets of empty displayId.
+ assertThat(displayId).isEqualTo("")
+ assertThat(offsets?.displayId).isEqualTo("")
+ assertThat(offsets?.sensorLocationX).isEqualTo(540)
+ assertThat(offsets?.sensorLocationY).isEqualTo(1636)
+ assertThat(offsets?.sensorRadius).isEqualTo(130)
+
+ // Offsets should be updated correctly.
+ interactor.onDisplayChanged("display_id_1")
+ assertThat(displayId).isEqualTo("display_id_1")
+ assertThat(offsets?.displayId).isEqualTo("display_id_1")
+ assertThat(offsets?.sensorLocationX).isEqualTo(100)
+ assertThat(offsets?.sensorLocationY).isEqualTo(300)
+ assertThat(offsets?.sensorRadius).isEqualTo(20)
+
+ // Should return default offset when the displayId is invalid.
+ interactor.onDisplayChanged("invalid_display_id")
+ assertThat(displayId).isEqualTo("invalid_display_id")
+ assertThat(offsets?.displayId).isEqualTo(SensorLocationInternal.DEFAULT.displayId)
+ assertThat(offsets?.sensorLocationX)
+ .isEqualTo(SensorLocationInternal.DEFAULT.sensorLocationX)
+ assertThat(offsets?.sensorLocationY)
+ .isEqualTo(SensorLocationInternal.DEFAULT.sensorLocationY)
+ assertThat(offsets?.sensorRadius).isEqualTo(SensorLocationInternal.DEFAULT.sensorRadius)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModelTest.kt
index 7697c09..0d61e30 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptFingerprintIconViewModelTest.kt
@@ -4,9 +4,9 @@
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
import com.android.systemui.biometrics.data.repository.FakePromptRepository
-import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
@@ -41,7 +41,7 @@
private val fingerprintRepository = FakeFingerprintPropertyRepository()
private val promptRepository = FakePromptRepository()
- private val rearDisplayStateRepository = FakeRearDisplayStateRepository()
+ private val displayStateRepository = FakeDisplayStateRepository()
private val testScope = TestScope(StandardTestDispatcher())
private val fakeExecutor = FakeExecutor(FakeSystemClock())
@@ -59,7 +59,7 @@
testScope.backgroundScope,
mContext,
fakeExecutor,
- rearDisplayStateRepository
+ displayStateRepository
)
viewModel = PromptFingerprintIconViewModel(displayStateInteractor, promptSelectorInteractor)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index 0ed46da..c53172d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -25,9 +25,9 @@
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthBiometricView
+import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
import com.android.systemui.biometrics.data.repository.FakePromptRepository
-import com.android.systemui.biometrics.data.repository.FakeRearDisplayStateRepository
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractorImpl
@@ -79,14 +79,14 @@
private val testScope = TestScope()
private val fingerprintRepository = FakeFingerprintPropertyRepository()
private val promptRepository = FakePromptRepository()
- private val rearDisplayStateRepository = FakeRearDisplayStateRepository()
+ private val displayStateRepository = FakeDisplayStateRepository()
private val displayStateInteractor =
DisplayStateInteractorImpl(
testScope.backgroundScope,
mContext,
fakeExecutor,
- rearDisplayStateRepository
+ displayStateRepository
)
private lateinit var selector: PromptSelectorInteractor
@@ -99,7 +99,8 @@
PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils)
selector.resetPrompt()
- viewModel = PromptViewModel(displayStateInteractor, selector, vibrator, featureFlags)
+ viewModel =
+ PromptViewModel(displayStateInteractor, selector, vibrator, mContext, featureFlags)
featureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, false)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index f73804d..e568c24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -175,8 +175,6 @@
private @Mock AuthController mAuthController;
private @Mock ShadeExpansionStateManager mShadeExpansionStateManager;
private @Mock ShadeWindowLogger mShadeWindowLogger;
- private @Captor ArgumentCaptor<KeyguardUpdateMonitorCallback>
- mKeyguardUpdateMonitorCallbackCaptor;
private @Captor ArgumentCaptor<KeyguardStateController.Callback>
mKeyguardStateControllerCallback;
private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
@@ -239,25 +237,6 @@
}
@Test
- @TestableLooper.RunWithLooper(setAsMainLooper = true)
- public void onLockdown_showKeyguard_evenIfKeyguardIsNotEnabledExternally() {
- // GIVEN keyguard is not enabled and isn't showing
- mViewMediator.onSystemReady();
- mViewMediator.setKeyguardEnabled(false);
- TestableLooper.get(this).processAllMessages();
- captureKeyguardUpdateMonitorCallback();
- assertFalse(mViewMediator.isShowingAndNotOccluded());
-
- // WHEN lockdown occurs
- when(mLockPatternUtils.isUserInLockdown(anyInt())).thenReturn(true);
- mKeyguardUpdateMonitorCallbackCaptor.getValue().onStrongAuthStateChanged(0);
-
- // THEN keyguard is shown
- TestableLooper.get(this).processAllMessages();
- assertTrue(mViewMediator.isShowingAndNotOccluded());
- }
-
- @Test
public void testOnGoingToSleep_UpdatesKeyguardGoingAway() {
mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER);
verify(mUpdateMonitor).dispatchKeyguardGoingAway(false);
@@ -1000,10 +979,6 @@
mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
}
- private void captureKeyguardUpdateMonitorCallback() {
- verify(mUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallbackCaptor.capture());
- }
-
private void captureKeyguardStateControllerCallback() {
verify(mKeyguardStateController).addCallback(mKeyguardStateControllerCallback.capture());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
index d36e778..b9c0b7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
@@ -20,6 +20,7 @@
import android.graphics.drawable.Drawable
import android.service.quickaccesswallet.GetWalletCardsResponse
import android.service.quickaccesswallet.QuickAccessWalletClient
+import android.service.quickaccesswallet.WalletCard
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.R
@@ -38,6 +39,7 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -92,6 +94,40 @@
}
@Test
+ fun affordance_keyguardShowing_hasNonPaymentCard_modelIsNone() =
+ runTest(UnconfinedTestDispatcher()) {
+ setUpState(cardType = WalletCard.CARD_TYPE_NON_PAYMENT)
+ var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
+
+ val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
+ job.cancel()
+ }
+
+ @Test
+ fun affordance_keyguardShowing_hasPaymentCard_visibleModel() =
+ runTest(UnconfinedTestDispatcher()) {
+ setUpState(cardType = WalletCard.CARD_TYPE_PAYMENT)
+ var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
+
+ val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
+
+ val visibleModel = latest as KeyguardQuickAffordanceConfig.LockScreenState.Visible
+ assertThat(visibleModel.icon)
+ .isEqualTo(
+ Icon.Loaded(
+ drawable = ICON,
+ contentDescription =
+ ContentDescription.Resource(
+ res = R.string.accessibility_wallet_button,
+ ),
+ )
+ )
+ job.cancel()
+ }
+
+ @Test
fun affordance_walletFeatureNotEnabled_modelIsNone() = runBlockingTest {
setUpState(isWalletFeatureAvailable = false)
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
@@ -187,6 +223,7 @@
isWalletServiceAvailable: Boolean = true,
isWalletQuerySuccessful: Boolean = true,
hasSelectedCard: Boolean = true,
+ cardType: Int = WalletCard.CARD_TYPE_UNKNOWN
) {
val walletClient: QuickAccessWalletClient = mock()
whenever(walletClient.tileIcon).thenReturn(ICON)
@@ -202,7 +239,19 @@
if (isWalletQuerySuccessful) {
onWalletCardsRetrieved(
if (hasSelectedCard) {
- GetWalletCardsResponse(listOf(mock()), 0)
+ GetWalletCardsResponse(
+ listOf(
+ WalletCard.Builder(
+ /*cardId= */ CARD_ID,
+ /*cardType= */ cardType,
+ /*cardImage= */ mock(),
+ /*contentDescription= */ CARD_DESCRIPTION,
+ /*pendingIntent= */ mock()
+ )
+ .build()
+ ),
+ 0
+ )
} else {
GetWalletCardsResponse(emptyList(), 0)
}
@@ -216,5 +265,7 @@
companion object {
private val ICON: Drawable = mock()
+ private const val CARD_ID: String = "Id"
+ private const val CARD_DESCRIPTION: String = "Description"
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
index d1299d4..5939bb5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
@@ -16,10 +16,12 @@
package com.android.systemui.media.controls.pipeline
+import android.app.IUriGrantsManager
import android.app.Notification
import android.app.Notification.FLAG_NO_CLEAR
import android.app.Notification.MediaStyle
import android.app.PendingIntent
+import android.app.UriGrantsManager
import android.app.smartspace.SmartspaceAction
import android.app.smartspace.SmartspaceConfig
import android.app.smartspace.SmartspaceManager
@@ -27,12 +29,14 @@
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
+import android.graphics.ImageDecoder
import android.graphics.drawable.Icon
import android.media.MediaDescription
import android.media.MediaMetadata
import android.media.session.MediaController
import android.media.session.MediaSession
import android.media.session.PlaybackState
+import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.service.notification.StatusBarNotification
@@ -40,6 +44,7 @@
import android.testing.TestableLooper.RunWithLooper
import androidx.media.utils.MediaConstants
import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.internal.logging.InstanceId
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.InstanceIdSequenceFake
@@ -83,7 +88,9 @@
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoSession
import org.mockito.junit.MockitoJUnit
+import org.mockito.quality.Strictness
private const val KEY = "KEY"
private const val KEY_2 = "KEY_2"
@@ -149,6 +156,8 @@
@Captor lateinit var stateCallbackCaptor: ArgumentCaptor<(String, PlaybackState) -> Unit>
@Captor lateinit var sessionCallbackCaptor: ArgumentCaptor<(String) -> Unit>
@Captor lateinit var smartSpaceConfigBuilderCaptor: ArgumentCaptor<SmartspaceConfig>
+ @Mock private lateinit var ugm: IUriGrantsManager
+ @Mock private lateinit var imageSource: ImageDecoder.Source
private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20)
@@ -159,8 +168,17 @@
1
)
+ private lateinit var staticMockSession: MockitoSession
+
@Before
fun setup() {
+ staticMockSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic<UriGrantsManager>(UriGrantsManager::class.java)
+ .mockStatic<ImageDecoder>(ImageDecoder::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
+ whenever(UriGrantsManager.getService()).thenReturn(ugm)
foregroundExecutor = FakeExecutor(clock)
backgroundExecutor = FakeExecutor(clock)
uiExecutor = FakeExecutor(clock)
@@ -270,6 +288,7 @@
@After
fun tearDown() {
+ staticMockSession.finishMocking()
session.release()
mediaDataManager.destroy()
Settings.Secure.putInt(
@@ -2198,6 +2217,66 @@
verify(listener).onMediaDataRemoved(eq(KEY))
}
+ @Test
+ fun testResumeMediaLoaded_hasArtPermission_artLoaded() {
+ // When resume media is loaded and user/app has permission to access the art URI,
+ whenever(
+ ugm.checkGrantUriPermission_ignoreNonSystem(
+ anyInt(),
+ any(),
+ any(),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenReturn(1)
+ val artwork = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
+ val uri = Uri.parse("content://example")
+ whenever(ImageDecoder.createSource(any(), eq(uri))).thenReturn(imageSource)
+ whenever(ImageDecoder.decodeBitmap(any(), any())).thenReturn(artwork)
+
+ val desc =
+ MediaDescription.Builder().run {
+ setTitle(SESSION_TITLE)
+ setIconUri(uri)
+ build()
+ }
+ addResumeControlAndLoad(desc)
+
+ // Then the artwork is loaded
+ assertThat(mediaDataCaptor.value.artwork).isNotNull()
+ }
+
+ @Test
+ fun testResumeMediaLoaded_noArtPermission_noArtLoaded() {
+ // When resume media is loaded and user/app does not have permission to access the art URI
+ whenever(
+ ugm.checkGrantUriPermission_ignoreNonSystem(
+ anyInt(),
+ any(),
+ any(),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenThrow(SecurityException("Test no permission"))
+ val artwork = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
+ val uri = Uri.parse("content://example")
+ whenever(ImageDecoder.createSource(any(), eq(uri))).thenReturn(imageSource)
+ whenever(ImageDecoder.decodeBitmap(any(), any())).thenReturn(artwork)
+
+ val desc =
+ MediaDescription.Builder().run {
+ setTitle(SESSION_TITLE)
+ setIconUri(uri)
+ build()
+ }
+ addResumeControlAndLoad(desc)
+
+ // Then the artwork is not loaded
+ assertThat(mediaDataCaptor.value.artwork).isNull()
+ }
+
/** Helper function to add a basic media notification and capture the resulting MediaData */
private fun addNotificationAndLoad() {
addNotificationAndLoad(mediaNotification)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
index 5e7f68c..e5c55d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
@@ -168,7 +168,7 @@
val btDevice = mock<BluetoothDevice>()
whenever(cachedDevice2.device).thenReturn(btDevice)
whenever(btDevice.getMetadata(BluetoothDevice.METADATA_MAIN_BATTERY)).thenReturn(null)
- whenever(cachedDevice2.batteryLevel).thenReturn(25)
+ whenever(cachedDevice2.minBatteryLevelWithMemberDevices).thenReturn(25)
addConnectedDevice(cachedDevice2)
tile.handleUpdateState(state, /* arg= */ null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index b00ae39..dd55bad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -395,7 +395,7 @@
PendingIntent.getActivity(mContext, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
WalletCard walletCard =
new WalletCard.Builder(
- CARD_ID, mCardImage, CARD_DESCRIPTION, pendingIntent).build();
+ CARD_ID, mCardImage, CARD_DESCRIPTION, pendingIntent).build();
GetWalletCardsResponse response =
new GetWalletCardsResponse(Collections.singletonList(walletCard), 0);
@@ -410,6 +410,22 @@
}
@Test
+ public void testQueryCards_cardDataPayment_updateSideViewDrawable() {
+ when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+ setUpWalletCardWithType(/* hasCard =*/ true, WalletCard.CARD_TYPE_PAYMENT);
+
+ assertNotNull(mTile.getState().sideViewCustomDrawable);
+ }
+
+ @Test
+ public void testQueryCards_cardDataNonPayment_updateSideViewDrawable() {
+ when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+ setUpWalletCardWithType(/* hasCard =*/ true, WalletCard.CARD_TYPE_NON_PAYMENT);
+
+ assertNull(mTile.getState().sideViewCustomDrawable);
+ }
+
+ @Test
public void testQueryCards_noCards_notUpdateSideViewDrawable() {
setUpWalletCard(/* hasCard= */ false);
@@ -438,6 +454,29 @@
verifyZeroInteractions(mQuickAccessWalletClient);
}
+ private WalletCard createWalletCardWithType(Context context, int cardType) {
+ PendingIntent pendingIntent =
+ PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+ return new WalletCard.Builder(CARD_ID, cardType, CARD_IMAGE, CARD_DESCRIPTION,
+ pendingIntent).build();
+ }
+
+ private void setUpWalletCardWithType(boolean hasCard, int cardType) {
+ GetWalletCardsResponse response =
+ new GetWalletCardsResponse(
+ hasCard
+ ? Collections.singletonList(
+ createWalletCardWithType(mContext, cardType))
+ : Collections.EMPTY_LIST, 0);
+
+ mTile.handleSetListening(true);
+
+ verify(mController).queryWalletCards(mCallbackCaptor.capture());
+
+ mCallbackCaptor.getValue().onWalletCardsRetrieved(response);
+ mTestableLooper.processAllMessages();
+ }
+
private void setUpWalletCard(boolean hasCard) {
GetWalletCardsResponse response =
new GetWalletCardsResponse(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManagerTest.kt
new file mode 100644
index 0000000..e38adeb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotifInflationErrorManagerTest.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager.NotifInflationErrorListener
+import com.android.systemui.util.mockito.any
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class NotifInflationErrorManagerTest : SysuiTestCase() {
+ private lateinit var manager: NotifInflationErrorManager
+
+ private val listener1 = mock(NotifInflationErrorListener::class.java)
+ private val listener2 = mock(NotifInflationErrorListener::class.java)
+
+ private val foo: NotificationEntry = NotificationEntryBuilder().setPkg("foo").build()
+ private val bar: NotificationEntry = NotificationEntryBuilder().setPkg("bar").build()
+ private val baz: NotificationEntry = NotificationEntryBuilder().setPkg("baz").build()
+
+ private val fooException = Exception("foo")
+ private val barException = Exception("bar")
+
+ @Before
+ fun setUp() {
+ // Reset manager instance before each test.
+ manager = NotifInflationErrorManager()
+ }
+
+ @Test
+ fun testTracksInflationErrors() {
+ manager.setInflationError(foo, fooException)
+ manager.setInflationError(bar, barException)
+
+ assertThat(manager.hasInflationError(foo)).isTrue()
+ assertThat(manager.hasInflationError(bar)).isTrue()
+ assertThat(manager.hasInflationError(baz)).isFalse()
+
+ manager.clearInflationError(bar)
+
+ assertThat(manager.hasInflationError(bar)).isFalse()
+ }
+
+ @Test
+ fun testNotifiesListeners() {
+ manager.addInflationErrorListener(listener1)
+ manager.setInflationError(foo, fooException)
+
+ verify(listener1).onNotifInflationError(foo, fooException)
+
+ manager.addInflationErrorListener(listener2)
+ manager.setInflationError(bar, barException)
+
+ verify(listener1).onNotifInflationError(bar, barException)
+ verify(listener2).onNotifInflationError(bar, barException)
+
+ manager.clearInflationError(foo)
+
+ verify(listener1).onNotifInflationErrorCleared(foo)
+ verify(listener2).onNotifInflationErrorCleared(foo)
+ }
+
+ @Test
+ fun testClearUnknownEntry() {
+ manager.addInflationErrorListener(listener1)
+ manager.clearInflationError(foo)
+
+ verify(listener1, never()).onNotifInflationErrorCleared(any())
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 6f431be..79cf932 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -628,6 +628,16 @@
verify(mNotificationStackScrollLayout).updateEmptyShadeView(eq(false), anyBoolean());
}
+ @Test
+ public void updateEmptyShadeView_onKeyguardOccludedTransitionToAod_hidesView() {
+ initController(/* viewIsAttached= */ true);
+ mController.onKeyguardTransitionChanged(
+ new TransitionStep(
+ /* from= */ KeyguardState.OCCLUDED,
+ /* to= */ KeyguardState.AOD));
+ verify(mNotificationStackScrollLayout).updateEmptyShadeView(eq(false), anyBoolean());
+ }
+
private LogMaker logMatcher(int category, int type) {
return argThat(new LogMatcher(category, type));
}
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 39b2948..de00747 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
@@ -516,7 +516,7 @@
mNotificationShadeWindowViewControllerLazy,
mNotificationShelfController,
mStackScrollerController,
- mNotificationPresenter,
+ () -> mNotificationPresenter,
new NotificationExpansionRepository(),
mDozeParameters,
mScrimController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 0b31523..af0d6b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -103,6 +103,21 @@
}
@Test
+ fun onViewAttachedAndDrawn_startListeningConfigurationControllerCallback() {
+ val view = createViewMock()
+ val argumentCaptor = ArgumentCaptor.forClass(
+ ConfigurationController.ConfigurationListener::class.java)
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ controller = createAndInitController(view)
+ }
+
+ verify(configurationController).addCallback(argumentCaptor.capture())
+ argumentCaptor.value.onDensityOrFontScaleChanged()
+
+ verify(view).onDensityOrFontScaleChanged()
+ }
+
+ @Test
fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() {
whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS))
.thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
index a0d4d13..bbf048d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
@@ -22,6 +22,7 @@
import android.testing.TestableLooper.RunWithLooper
import android.testing.ViewUtils
import android.view.View
+import android.view.ViewGroup
import android.widget.ImageView
import androidx.test.filters.SmallTest
import com.android.systemui.R
@@ -138,7 +139,7 @@
ViewUtils.attachView(view)
testableLooper.processAllMessages()
- assertThat(view.getIconGroupView().visibility).isEqualTo(View.GONE)
+ assertThat(view.getIconGroupView().visibility).isEqualTo(View.INVISIBLE)
assertThat(view.getDotView().visibility).isEqualTo(View.VISIBLE)
ViewUtils.detachView(view)
@@ -153,8 +154,36 @@
ViewUtils.attachView(view)
testableLooper.processAllMessages()
- assertThat(view.getIconGroupView().visibility).isEqualTo(View.GONE)
- assertThat(view.getDotView().visibility).isEqualTo(View.GONE)
+ assertThat(view.getIconGroupView().visibility).isEqualTo(View.INVISIBLE)
+ assertThat(view.getDotView().visibility).isEqualTo(View.INVISIBLE)
+
+ ViewUtils.detachView(view)
+ }
+
+ /* Regression test for b/296864006. When STATE_HIDDEN we need to ensure the wifi view width
+ * would not break the StatusIconContainer translation calculation. */
+ @Test
+ fun setVisibleState_hidden_keepWidth() {
+ val view = ModernStatusBarWifiView.constructAndBind(context, SLOT_NAME, viewModel)
+
+ view.setVisibleState(STATE_ICON, /* animate= */ false)
+
+ // get the view width when it's in visible state
+ ViewUtils.attachView(view)
+ val lp = view.layoutParams
+ lp.width = ViewGroup.LayoutParams.WRAP_CONTENT
+ lp.height = ViewGroup.LayoutParams.WRAP_CONTENT
+ view.layoutParams = lp
+ testableLooper.processAllMessages()
+ val currentWidth = view.width
+
+ view.setVisibleState(STATE_HIDDEN, /* animate= */ false)
+ testableLooper.processAllMessages()
+
+ // the view width when STATE_HIDDEN should be at least the width when STATE_ICON. Because
+ // when STATE_HIDDEN the invisible dot view width might be larger than group view width,
+ // then the wifi view width would be enlarged.
+ assertThat(view.width).isAtLeast(currentWidth)
ViewUtils.detachView(view)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index d01e0a6..2f563dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -44,6 +44,7 @@
import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.Log;
import android.view.Gravity;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -84,7 +85,7 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class VolumeDialogImplTest extends SysuiTestCase {
VolumeDialogImpl mDialog;
View mActiveRinger;
@@ -98,6 +99,8 @@
private ConfigurationController mConfigurationController;
private int mOriginalOrientation;
+ private static final String TAG = "VolumeDialogImplTest";
+
@Mock
VolumeDialogController mVolumeDialogController;
@Mock
@@ -141,6 +144,7 @@
getContext().addMockSystemService(KeyguardManager.class, mKeyguard);
mTestableLooper = TestableLooper.get(this);
+ allowTestableLooperAsMainThread();
when(mPostureController.getDevicePosture())
.thenReturn(DevicePostureController.DEVICE_POSTURE_CLOSED);
@@ -651,12 +655,20 @@
@After
public void teardown() {
+ // Detailed logs to track down timeout issues in b/299491332
+ Log.d(TAG, "teardown: entered");
setOrientation(mOriginalOrientation);
+ Log.d(TAG, "teardown: after setOrientation");
mAnimatorTestRule.advanceTimeBy(mLongestHideShowAnimationDuration);
+ Log.d(TAG, "teardown: after advanceTimeBy");
mTestableLooper.moveTimeForward(mLongestHideShowAnimationDuration);
+ Log.d(TAG, "teardown: after moveTimeForward");
mTestableLooper.processAllMessages();
+ Log.d(TAG, "teardown: after processAllMessages");
reset(mPostureController);
+ Log.d(TAG, "teardown: after reset");
cleanUp(mDialog);
+ Log.d(TAG, "teardown: after cleanUp");
}
private void cleanUp(VolumeDialogImpl dialog) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
index 692af6a..c1d11aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
@@ -459,7 +459,7 @@
WalletCard.CARD_TYPE_UNKNOWN),
createWalletCardWithType(mContext, WalletCard.CARD_TYPE_PAYMENT),
createWalletCardWithType(mContext, WalletCard.CARD_TYPE_NON_PAYMENT)
- );
+ );
GetWalletCardsResponse response = new GetWalletCardsResponse(walletCardList, 0);
mController.onWalletCardsRetrieved(response);
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/util/WalletCardUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wallet/util/WalletCardUtilsTest.kt
new file mode 100644
index 0000000..e46c1f5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/util/WalletCardUtilsTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.wallet.util
+
+import android.service.quickaccesswallet.WalletCard
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Test class for WalletCardUtils */
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+@SmallTest
+class WalletCardUtilsTest : SysuiTestCase() {
+
+ private val paymentCard = createWalletCardWithType(WalletCard.CARD_TYPE_PAYMENT)
+ private val nonPaymentCard = createWalletCardWithType(WalletCard.CARD_TYPE_NON_PAYMENT)
+ private val unknownCard = createWalletCardWithType(WalletCard.CARD_TYPE_UNKNOWN)
+
+ @Test
+ fun paymentCards_cardTypesAllUnknown_getsAllCards() {
+ val walletCardList =
+ mutableListOf(
+ createWalletCardWithType(WalletCard.CARD_TYPE_UNKNOWN),
+ createWalletCardWithType(WalletCard.CARD_TYPE_UNKNOWN),
+ createWalletCardWithType(WalletCard.CARD_TYPE_UNKNOWN)
+ )
+
+ assertThat(walletCardList).isEqualTo(getPaymentCards(walletCardList))
+ }
+
+ @Test
+ fun paymentCards_cardTypesDifferent_onlyGetsPayment() {
+ val walletCardList = mutableListOf(paymentCard, nonPaymentCard, unknownCard)
+
+ assertThat(getPaymentCards(walletCardList)).isEqualTo(mutableListOf(paymentCard))
+ }
+
+ private fun createWalletCardWithType(cardType: Int): WalletCard {
+ return WalletCard.Builder(
+ /*cardId= */ CARD_ID,
+ /*cardType= */ cardType,
+ /*cardImage= */ mock(),
+ /*contentDescription= */ CARD_DESCRIPTION,
+ /*pendingIntent= */ mock()
+ )
+ .build()
+ }
+
+ companion object {
+ private const val CARD_ID: String = "ID"
+ private const val CARD_DESCRIPTION: String = "Description"
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeRearDisplayStateRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt
similarity index 71%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeRearDisplayStateRepository.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt
index fd91391..60291ee 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeRearDisplayStateRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeDisplayStateRepository.kt
@@ -17,15 +17,23 @@
package com.android.systemui.biometrics.data.repository
+import com.android.systemui.biometrics.shared.model.DisplayRotation
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
-class FakeRearDisplayStateRepository : RearDisplayStateRepository {
+class FakeDisplayStateRepository : DisplayStateRepository {
private val _isInRearDisplayMode = MutableStateFlow<Boolean>(false)
override val isInRearDisplayMode: StateFlow<Boolean> = _isInRearDisplayMode.asStateFlow()
+ private val _currentRotation = MutableStateFlow<DisplayRotation>(DisplayRotation.ROTATION_0)
+ override val currentRotation: StateFlow<DisplayRotation> = _currentRotation.asStateFlow()
+
fun setIsInRearDisplayMode(isInRearDisplayMode: Boolean) {
_isInRearDisplayMode.value = isInRearDisplayMode
}
+
+ fun setCurrentRotation(currentRotation: DisplayRotation) {
+ _currentRotation.value = currentRotation
+ }
}
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 2362a52..0c5e438 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
@@ -20,16 +20,12 @@
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class FakeFingerprintPropertyRepository : FingerprintPropertyRepository {
- private val _isInitialized: MutableStateFlow<Boolean> = MutableStateFlow(false)
- override val isInitialized = _isInitialized.asStateFlow()
-
private val _sensorId: MutableStateFlow<Int> = MutableStateFlow(-1)
- override val sensorId: StateFlow<Int> = _sensorId.asStateFlow()
+ override val sensorId = _sensorId.asStateFlow()
private val _strength: MutableStateFlow<SensorStrength> =
MutableStateFlow(SensorStrength.CONVENIENCE)
@@ -37,12 +33,11 @@
private val _sensorType: MutableStateFlow<FingerprintSensorType> =
MutableStateFlow(FingerprintSensorType.UNKNOWN)
- override val sensorType: StateFlow<FingerprintSensorType> = _sensorType.asStateFlow()
+ override val sensorType = _sensorType.asStateFlow()
private val _sensorLocations: MutableStateFlow<Map<String, SensorLocationInternal>> =
MutableStateFlow(mapOf("" to SensorLocationInternal.DEFAULT))
- override val sensorLocations: StateFlow<Map<String, SensorLocationInternal>> =
- _sensorLocations.asStateFlow()
+ override val sensorLocations = _sensorLocations.asStateFlow()
fun setProperties(
sensorId: Int,
@@ -54,6 +49,5 @@
_strength.value = strength
_sensorType.value = sensorType
_sensorLocations.value = sensorLocations
- _isInitialized.value = true
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 038847e..e1c4aad 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -177,7 +177,8 @@
}
if (!activated) {
- clearAndTransitionToStateDetecting();
+ // cancel the magnification shortcut
+ mDetectingState.setShortcutTriggered(false);
}
}
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index 05327dc..a792db0 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -738,6 +738,9 @@
try {
String transportName = transport.name();
String transportDirName = transport.transportDirName();
+ if (transportName == null || transportDirName == null) {
+ return BackupManager.ERROR_TRANSPORT_INVALID;
+ }
registerTransport(transportComponent, transport);
// If registerTransport() hasn't thrown...
Slog.d(TAG, addUserIdToLogMessage(mUserId, "Transport " + transportString
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 9d6283b8..2511b50 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -64,6 +64,7 @@
import android.companion.IOnMessageReceivedListener;
import android.companion.IOnTransportsChangedListener;
import android.companion.ISystemDataTransferCallback;
+import android.companion.datatransfer.PermissionSyncRequest;
import android.companion.utils.FeatureUtils;
import android.content.ComponentName;
import android.content.Context;
@@ -794,6 +795,24 @@
}
@Override
+ public void enablePermissionsSync(int associationId) {
+ getAssociationWithCallerChecks(associationId);
+ mSystemDataTransferProcessor.enablePermissionsSync(associationId);
+ }
+
+ @Override
+ public void disablePermissionsSync(int associationId) {
+ getAssociationWithCallerChecks(associationId);
+ mSystemDataTransferProcessor.disablePermissionsSync(associationId);
+ }
+
+ @Override
+ public PermissionSyncRequest getPermissionSyncRequest(int associationId) {
+ getAssociationWithCallerChecks(associationId);
+ return mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
+ }
+
+ @Override
public void enableSecureTransport(boolean enabled) {
mTransportManager.enableSecureTransport(enabled);
}
@@ -934,7 +953,7 @@
String[] args, ShellCallback callback, ResultReceiver resultReceiver)
throws RemoteException {
new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, mAssociationStore,
- mDevicePresenceMonitor, mTransportManager, mSystemDataTransferRequestStore,
+ mDevicePresenceMonitor, mTransportManager, mSystemDataTransferProcessor,
mAssociationRequestsProcessor)
.exec(this, in, out, err, args, callback, resultReceiver);
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index 04fbab4..d56436b1 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -25,7 +25,7 @@
import android.os.ShellCommand;
import android.util.proto.ProtoOutputStream;
-import com.android.server.companion.datatransfer.SystemDataTransferRequestStore;
+import com.android.server.companion.datatransfer.SystemDataTransferProcessor;
import com.android.server.companion.datatransfer.contextsync.BitmapUtils;
import com.android.server.companion.datatransfer.contextsync.CrossDeviceSyncController;
import com.android.server.companion.presence.CompanionDevicePresenceMonitor;
@@ -43,20 +43,20 @@
private final CompanionDevicePresenceMonitor mDevicePresenceMonitor;
private final CompanionTransportManager mTransportManager;
- private final SystemDataTransferRequestStore mSystemDataTransferRequestStore;
+ private final SystemDataTransferProcessor mSystemDataTransferProcessor;
private final AssociationRequestsProcessor mAssociationRequestsProcessor;
CompanionDeviceShellCommand(CompanionDeviceManagerService service,
AssociationStoreImpl associationStore,
CompanionDevicePresenceMonitor devicePresenceMonitor,
CompanionTransportManager transportManager,
- SystemDataTransferRequestStore systemDataTransferRequestStore,
+ SystemDataTransferProcessor systemDataTransferProcessor,
AssociationRequestsProcessor associationRequestsProcessor) {
mService = service;
mAssociationStore = associationStore;
mDevicePresenceMonitor = devicePresenceMonitor;
mTransportManager = transportManager;
- mSystemDataTransferRequestStore = systemDataTransferRequestStore;
+ mSystemDataTransferProcessor = systemDataTransferProcessor;
mAssociationRequestsProcessor = associationRequestsProcessor;
}
@@ -265,16 +265,47 @@
break;
}
- case "allow-permission-sync": {
- int userId = getNextIntArgRequired();
+ case "get-perm-sync-state": {
associationId = getNextIntArgRequired();
- boolean enabled = getNextBooleanArgRequired();
- PermissionSyncRequest request = new PermissionSyncRequest(associationId);
- request.setUserId(userId);
- request.setUserConsented(enabled);
- mSystemDataTransferRequestStore.writeRequest(userId, request);
+ PermissionSyncRequest request =
+ mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
+ out.println((request == null ? "null" : request.isUserConsented()));
+ break;
}
- break;
+
+ case "remove-perm-sync-state": {
+ associationId = getNextIntArgRequired();
+ PermissionSyncRequest request =
+ mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
+ out.print((request == null ? "null" : request.isUserConsented()));
+ mSystemDataTransferProcessor.removePermissionSyncRequest(associationId);
+ request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
+ // should print " -> null"
+ out.println(" -> " + (request == null ? "null" : request.isUserConsented()));
+ break;
+ }
+
+ case "enable-perm-sync": {
+ associationId = getNextIntArgRequired();
+ PermissionSyncRequest request =
+ mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
+ out.print((request == null ? "null" : request.isUserConsented()));
+ mSystemDataTransferProcessor.enablePermissionsSync(associationId);
+ request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
+ out.println(" -> " + request.isUserConsented()); // should print " -> true"
+ break;
+ }
+
+ case "disable-perm-sync": {
+ associationId = getNextIntArgRequired();
+ PermissionSyncRequest request =
+ mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
+ out.print((request == null ? "null" : request.isUserConsented()));
+ mSystemDataTransferProcessor.disablePermissionsSync(associationId);
+ request = mSystemDataTransferProcessor.getPermissionSyncRequest(associationId);
+ out.println(" -> " + request.isUserConsented()); // should print " -> false"
+ break;
+ }
default:
return handleDefaultCommands(cmd);
@@ -346,5 +377,14 @@
pw.println(" create-emulated-transport <ASSOCIATION_ID>");
pw.println(" Create an EmulatedTransport for testing purposes only");
+
+ pw.println(" enable-perm-sync <ASSOCIATION_ID>");
+ pw.println(" Enable perm sync for the association.");
+ pw.println(" disable-perm-sync <ASSOCIATION_ID>");
+ pw.println(" Disable perm sync for the association.");
+ pw.println(" get-perm-sync-state <ASSOCIATION_ID>");
+ pw.println(" Get perm sync state for the association.");
+ pw.println(" remove-perm-sync-state <ASSOCIATION_ID>");
+ pw.println(" Remove perm sync state for the association.");
}
}
diff --git a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
index 800a3d9..aeb273b 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
@@ -138,6 +138,13 @@
@UserIdInt int userId, int associationId) {
if (PackageUtils.isPackageAllowlisted(mContext, mPackageManager, packageName)) {
Slog.i(LOG_TAG, "User consent Intent should be skipped. Returning null.");
+ // Auto enable perm sync for the allowlisted packages, but don't override user decision
+ PermissionSyncRequest request = getPermissionSyncRequest(associationId);
+ if (request == null) {
+ PermissionSyncRequest newRequest = new PermissionSyncRequest(associationId);
+ newRequest.setUserConsented(true);
+ mSystemDataTransferRequestStore.writeRequest(userId, newRequest);
+ }
return null;
}
@@ -184,29 +191,17 @@
final AssociationInfo association = resolveAssociation(packageName, userId, associationId);
// Check if the request has been consented by the user.
- if (PackageUtils.isPackageAllowlisted(mContext, mPackageManager, packageName)) {
- Slog.i(LOG_TAG, "Skip user consent check due to the same OEM package.");
- } else {
- List<SystemDataTransferRequest> storedRequests =
- mSystemDataTransferRequestStore.readRequestsByAssociationId(userId,
- associationId);
- boolean hasConsented = false;
- for (SystemDataTransferRequest storedRequest : storedRequests) {
- if (storedRequest instanceof PermissionSyncRequest
- && storedRequest.isUserConsented()) {
- hasConsented = true;
- break;
- }
+ PermissionSyncRequest request = getPermissionSyncRequest(associationId);
+ if (request == null || !request.isUserConsented()) {
+ String message =
+ "User " + userId + " hasn't consented permission sync for associationId ["
+ + associationId + ".";
+ Slog.e(LOG_TAG, message);
+ try {
+ callback.onError(message);
+ } catch (RemoteException ignored) {
}
- if (!hasConsented) {
- String message = "User " + userId + " hasn't consented permission sync.";
- Slog.e(LOG_TAG, message);
- try {
- callback.onError(message);
- } catch (RemoteException ignored) {
- }
- return;
- }
+ return;
}
// Start permission sync
@@ -224,6 +219,66 @@
}
}
+ /**
+ * Enable perm sync for the association
+ */
+ public void enablePermissionsSync(int associationId) {
+ final long callingIdentityToken = Binder.clearCallingIdentity();
+ try {
+ int userId = mAssociationStore.getAssociationById(associationId).getUserId();
+ PermissionSyncRequest request = new PermissionSyncRequest(associationId);
+ request.setUserConsented(true);
+ mSystemDataTransferRequestStore.writeRequest(userId, request);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentityToken);
+ }
+ }
+
+ /**
+ * Disable perm sync for the association
+ */
+ public void disablePermissionsSync(int associationId) {
+ final long callingIdentityToken = Binder.clearCallingIdentity();
+ try {
+ int userId = mAssociationStore.getAssociationById(associationId).getUserId();
+ PermissionSyncRequest request = new PermissionSyncRequest(associationId);
+ request.setUserConsented(false);
+ mSystemDataTransferRequestStore.writeRequest(userId, request);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentityToken);
+ }
+ }
+
+ /**
+ * Get perm sync request for the association.
+ */
+ @Nullable
+ public PermissionSyncRequest getPermissionSyncRequest(int associationId) {
+ final long callingIdentityToken = Binder.clearCallingIdentity();
+ try {
+ int userId = mAssociationStore.getAssociationById(associationId).getUserId();
+ List<SystemDataTransferRequest> requests =
+ mSystemDataTransferRequestStore.readRequestsByAssociationId(userId,
+ associationId);
+ for (SystemDataTransferRequest request : requests) {
+ if (request instanceof PermissionSyncRequest) {
+ return (PermissionSyncRequest) request;
+ }
+ }
+ return null;
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentityToken);
+ }
+ }
+
+ /**
+ * Remove perm sync request for the association.
+ */
+ public void removePermissionSyncRequest(int associationId) {
+ int userId = mAssociationStore.getAssociationById(associationId).getUserId();
+ mSystemDataTransferRequestStore.removeRequestsByAssociationId(userId, associationId);
+ }
+
private void onReceivePermissionRestore(byte[] message) {
Slog.i(LOG_TAG, "Applying permissions.");
// Start applying permissions
diff --git a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java
index 720cefa..9f489e8 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferRequestStore.java
@@ -104,7 +104,7 @@
}
@NonNull
- List<SystemDataTransferRequest> readRequestsByAssociationId(@UserIdInt int userId,
+ public List<SystemDataTransferRequest> readRequestsByAssociationId(@UserIdInt int userId,
int associationId) {
List<SystemDataTransferRequest> cachedRequests;
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/SmartStorageMaintIdler.java b/services/core/java/com/android/server/SmartStorageMaintIdler.java
index 8996926..44f1e76 100644
--- a/services/core/java/com/android/server/SmartStorageMaintIdler.java
+++ b/services/core/java/com/android/server/SmartStorageMaintIdler.java
@@ -25,6 +25,7 @@
import android.util.Slog;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
public class SmartStorageMaintIdler extends JobService {
private static final String TAG = "SmartStorageMaintIdler";
@@ -34,15 +35,15 @@
private static final int SMART_MAINT_JOB_ID = 2808;
- private boolean mStarted;
+ private final AtomicBoolean mStarted = new AtomicBoolean(false);
private JobParameters mJobParams;
private final Runnable mFinishCallback = new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Got smart storage maintenance service completion callback");
- if (mStarted) {
+ if (mStarted.get()) {
jobFinished(mJobParams, false);
- mStarted = false;
+ mStarted.set(false);
}
// ... and try again in a next period
scheduleSmartIdlePass(SmartStorageMaintIdler.this,
@@ -52,18 +53,26 @@
@Override
public boolean onStartJob(JobParameters params) {
- mJobParams = params;
- StorageManagerService ms = StorageManagerService.sSelf;
- if (ms != null) {
- mStarted = true;
- ms.runSmartIdleMaint(mFinishCallback);
+ final StorageManagerService ms = StorageManagerService.sSelf;
+ if (mStarted.compareAndSet(false, true)) {
+ new Thread() {
+ public void run() {
+ mJobParams = params;
+ if (ms != null) {
+ ms.runSmartIdleMaint(mFinishCallback);
+ } else {
+ mStarted.set(false);
+ }
+ }
+ }.start();
+ return ms != null;
}
- return ms != null;
+ return false;
}
@Override
public boolean onStopJob(JobParameters params) {
- mStarted = false;
+ mStarted.set(false);
return false;
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d47573d..2606757 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2771,7 +2771,7 @@
return true;
}
- void runSmartIdleMaint(Runnable callback) {
+ synchronized void runSmartIdleMaint(Runnable callback) {
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9671772..1fa60fe 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -314,6 +314,7 @@
import android.net.Proxy;
import android.net.Uri;
import android.os.AppZygote;
+import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.BinderProxy;
@@ -15029,6 +15030,16 @@
}
}
+ // STOPSHIP(b/298884211): Remove this logging
+ if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
+ final int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+ if (level < 0) {
+ Slog.wtf(BroadcastQueue.TAG, "Unexpected broadcast: " + intent
+ + "; callingUid: " + callingUid + ", callingPid: " + callingPid,
+ new Throwable());
+ }
+ }
+
int[] users;
if (userId == UserHandle.USER_ALL) {
// Caller wants broadcast to go to all started users.
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 5d0fefc..d5343a9 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -59,6 +59,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.BatteryManager;
import android.os.Bundle;
import android.os.BundleMerger;
import android.os.Handler;
@@ -1074,6 +1075,16 @@
queue.lastProcessState = app.mState.getCurProcState();
if (receiver instanceof BroadcastFilter) {
notifyScheduleRegisteredReceiver(app, r, (BroadcastFilter) receiver);
+ // STOPSHIP(b/298884211): Remove this logging
+ if (Intent.ACTION_BATTERY_CHANGED.equals(receiverIntent.getAction())) {
+ int level = receiverIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+ if (level < 0) {
+ Slog.wtf(TAG, "Dispatching unexpected broadcast: " + receiverIntent
+ + " to " + receiver
+ + "; callingUid: " + r.callingUid
+ + ", callingPid: " + r.callingPid);
+ }
+ }
thread.scheduleRegisteredReceiver(
((BroadcastFilter) receiver).receiverList.receiver,
receiverIntent, r.resultCode, r.resultData, r.resultExtras,
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 459c6ff..9a4ff54 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -2513,9 +2513,7 @@
}
}
- if (schedGroup < SCHED_GROUP_TOP_APP
- && cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP)
- && clientIsSystem) {
+ if (cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP) && clientIsSystem) {
schedGroup = SCHED_GROUP_TOP_APP;
scheduleLikeTopApp = true;
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index bf3f63c..d2737e81 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -539,6 +539,62 @@
}
}
}
+
+ // check playback or record activity after 6 seconds for UIDs
+ private static final int CHECK_CLIENT_STATE_DELAY_MS = 6000;
+
+ /*package */
+ void postCheckCommunicationRouteClientState(int uid, boolean wasActive, int delay) {
+ CommunicationRouteClient client = getCommunicationRouteClientForUid(uid);
+ if (client != null) {
+ sendMsgForCheckClientState(MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE,
+ SENDMSG_REPLACE,
+ uid,
+ wasActive ? 1 : 0,
+ client,
+ delay);
+ }
+ }
+
+ @GuardedBy("mDeviceStateLock")
+ void onCheckCommunicationRouteClientState(int uid, boolean wasActive) {
+ CommunicationRouteClient client = getCommunicationRouteClientForUid(uid);
+ if (client == null) {
+ return;
+ }
+ updateCommunicationRouteClientState(client, wasActive);
+ }
+
+ @GuardedBy("mDeviceStateLock")
+ /*package*/ void updateCommunicationRouteClientState(
+ CommunicationRouteClient client, boolean wasActive) {
+ boolean wasBtScoRequested = isBluetoothScoRequested();
+ client.setPlaybackActive(mAudioService.isPlaybackActiveForUid(client.getUid()));
+ client.setRecordingActive(mAudioService.isRecordingActiveForUid(client.getUid()));
+ if (wasActive != client.isActive()) {
+ postUpdateCommunicationRouteClient(
+ wasBtScoRequested, "updateCommunicationRouteClientState");
+ }
+ }
+
+ @GuardedBy("mDeviceStateLock")
+ /*package*/ void setForceCommunicationClientStateAndDelayedCheck(
+ CommunicationRouteClient client,
+ boolean forcePlaybackActive,
+ boolean forceRecordingActive) {
+ if (client == null) {
+ return;
+ }
+ if (forcePlaybackActive) {
+ client.setPlaybackActive(true);
+ }
+ if (forceRecordingActive) {
+ client.setRecordingActive(true);
+ }
+ postCheckCommunicationRouteClientState(
+ client.getUid(), client.isActive(), CHECK_CLIENT_STATE_DELAY_MS);
+ }
+
/* package */ static List<AudioDeviceInfo> getAvailableCommunicationDevices() {
ArrayList<AudioDeviceInfo> commDevices = new ArrayList<>();
AudioDeviceInfo[] allDevices =
@@ -1901,6 +1957,12 @@
case MSG_PERSIST_AUDIO_DEVICE_SETTINGS:
onPersistAudioDeviceSettings();
break;
+
+ case MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE: {
+ synchronized (mDeviceStateLock) {
+ onCheckCommunicationRouteClientState(msg.arg1, msg.arg2 == 1);
+ }
+ } break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
}
@@ -1982,6 +2044,8 @@
private static final int MSG_L_RECEIVED_BT_EVENT = 55;
+ private static final int MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE = 56;
+
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
@@ -2095,6 +2159,23 @@
}
}
+ private void removeMsgForCheckClientState(int uid) {
+ CommunicationRouteClient crc = getCommunicationRouteClientForUid(uid);
+ if (crc != null) {
+ mBrokerHandler.removeEqualMessages(MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE, crc);
+ }
+ }
+
+ private void sendMsgForCheckClientState(int msg, int existingMsgPolicy,
+ int arg1, int arg2, Object obj, int delay) {
+ if ((existingMsgPolicy == SENDMSG_REPLACE) && (obj != null)) {
+ mBrokerHandler.removeEqualMessages(msg, obj);
+ }
+
+ long time = SystemClock.uptimeMillis() + delay;
+ mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), time);
+ }
+
/** List of messages for which music is muted while processing is pending */
private static final Set<Integer> MESSAGES_MUTE_MUSIC;
static {
@@ -2367,6 +2448,7 @@
if (unregister) {
cl.unregisterDeathRecipient();
}
+ removeMsgForCheckClientState(cl.getUid());
mCommunicationRouteClients.remove(cl);
return cl;
}
@@ -2383,6 +2465,13 @@
new CommunicationRouteClient(cb, uid, device, isPrivileged);
if (client.registerDeathRecipient()) {
mCommunicationRouteClients.add(0, client);
+ if (!client.isActive()) {
+ // initialize the inactive client's state as active and check it after 6 seconds
+ setForceCommunicationClientStateAndDelayedCheck(
+ client,
+ !mAudioService.isPlaybackActiveForUid(client.getUid()),
+ !mAudioService.isRecordingActiveForUid(client.getUid()));
+ }
return client;
}
return null;
@@ -2439,16 +2528,16 @@
List<AudioRecordingConfiguration> recordConfigs) {
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
- final boolean wasBtScoRequested = isBluetoothScoRequested();
- boolean updateCommunicationRoute = false;
for (CommunicationRouteClient crc : mCommunicationRouteClients) {
boolean wasActive = crc.isActive();
+ boolean updateClientState = false;
if (playbackConfigs != null) {
crc.setPlaybackActive(false);
for (AudioPlaybackConfiguration config : playbackConfigs) {
if (config.getClientUid() == crc.getUid()
&& config.isActive()) {
crc.setPlaybackActive(true);
+ updateClientState = true;
break;
}
}
@@ -2459,18 +2548,23 @@
if (config.getClientUid() == crc.getUid()
&& !config.isClientSilenced()) {
crc.setRecordingActive(true);
+ updateClientState = true;
break;
}
}
}
- if (wasActive != crc.isActive()) {
- updateCommunicationRoute = true;
+ if (updateClientState) {
+ removeMsgForCheckClientState(crc.getUid());
+ updateCommunicationRouteClientState(crc, wasActive);
+ } else {
+ if (wasActive) {
+ setForceCommunicationClientStateAndDelayedCheck(
+ crc,
+ playbackConfigs != null /* forcePlaybackActive */,
+ recordConfigs != null /* forceRecordingActive */);
+ }
}
}
- if (updateCommunicationRoute) {
- postUpdateCommunicationRouteClient(
- wasBtScoRequested, "updateCommunicationRouteClientsActivity");
- }
}
}
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 60af280..e08fdd6 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1437,6 +1437,7 @@
}
});
new MediaMetrics.Item(mMetricsId + "disconnectA2dp")
+ .set(MediaMetrics.Property.EVENT, "disconnectA2dp")
.record();
if (toRemove.size() > 0) {
final int delay = checkSendBecomingNoisyIntentInt(
@@ -1459,6 +1460,7 @@
}
});
new MediaMetrics.Item(mMetricsId + "disconnectA2dpSink")
+ .set(MediaMetrics.Property.EVENT, "disconnectA2dpSink")
.record();
toRemove.stream().forEach(deviceAddress -> makeA2dpSrcUnavailable(deviceAddress));
}
@@ -1474,6 +1476,7 @@
}
});
new MediaMetrics.Item(mMetricsId + "disconnectHearingAid")
+ .set(MediaMetrics.Property.EVENT, "disconnectHearingAid")
.record();
if (toRemove.size() > 0) {
final int delay = checkSendBecomingNoisyIntentInt(
@@ -1531,6 +1534,7 @@
}
});
new MediaMetrics.Item(mMetricsId + "disconnectLeAudio")
+ .set(MediaMetrics.Property.EVENT, "disconnectLeAudio")
.record();
if (toRemove.size() > 0) {
final int delay = checkSendBecomingNoisyIntentInt(device,
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 58f48f3..a6be434a 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -164,6 +164,7 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.ServiceDebugInfo;
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.SystemClock;
@@ -12945,12 +12946,25 @@
private static final String AUDIO_HAL_SERVICE_PREFIX = "android.hardware.audio";
- private Set<Integer> getAudioHalPids() {
+ private void getAudioAidlHalPids(HashSet<Integer> pids) {
+ try {
+ ServiceDebugInfo[] infos = ServiceManager.getServiceDebugInfo();
+ if (infos == null) return;
+ for (ServiceDebugInfo info : infos) {
+ if (info.debugPid > 0 && info.name.startsWith(AUDIO_HAL_SERVICE_PREFIX)) {
+ pids.add(info.debugPid);
+ }
+ }
+ } catch (RuntimeException e) {
+ // ignored, pid hashset does not change
+ }
+ }
+
+ private void getAudioHalHidlPids(HashSet<Integer> pids) {
try {
IServiceManager serviceManager = IServiceManager.getService();
ArrayList<IServiceManager.InstanceDebugInfo> dump =
serviceManager.debugDump();
- HashSet<Integer> pids = new HashSet<>();
for (IServiceManager.InstanceDebugInfo info : dump) {
if (info.pid != IServiceManager.PidConstant.NO_PID
&& info.interfaceName != null
@@ -12958,12 +12972,18 @@
pids.add(info.pid);
}
}
- return pids;
} catch (RemoteException | RuntimeException e) {
- return new HashSet<Integer>();
+ // ignored, pid hashset does not change
}
}
+ private Set<Integer> getAudioHalPids() {
+ HashSet<Integer> pids = new HashSet<>();
+ getAudioAidlHalPids(pids);
+ getAudioHalHidlPids(pids);
+ return pids;
+ }
+
private void updateAudioHalPids() {
Set<Integer> pidsSet = getAudioHalPids();
if (pidsSet.isEmpty()) {
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 5ebc1c0..95b6c2c 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -334,9 +334,8 @@
SAFE_MEDIA_VOLUME_UNINITIALIZED);
mSafeMediaVolumeDevices.append(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
SAFE_MEDIA_VOLUME_UNINITIALIZED);
- // TODO(b/278265907): enable A2DP when we can distinguish A2DP headsets
- // mSafeMediaVolumeDevices.append(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
- // SAFE_MEDIA_VOLUME_UNINITIALIZED);
+ mSafeMediaVolumeDevices.append(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+ SAFE_MEDIA_VOLUME_UNINITIALIZED);
}
float getOutputRs2UpperBound() {
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index 2ae3118..b9ccbfb 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -275,7 +275,8 @@
}
sensor.goToStateWaitingForCookie(requireConfirmation, mToken, mOperationId,
mUserId, mSensorReceiver, mOpPackageName, mRequestId, cookie,
- mPromptInfo.isAllowBackgroundAuthentication());
+ mPromptInfo.isAllowBackgroundAuthentication(),
+ mPromptInfo.isForLegacyFingerprintManager());
}
}
@@ -747,7 +748,7 @@
Slog.v(TAG, "Confirmed! Modality: " + statsModality()
+ ", User: " + mUserId
+ ", IsCrypto: " + isCrypto()
- + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
+ + ", Client: " + getStatsClient()
+ ", RequireConfirmation: " + mPreAuthInfo.confirmationRequested
+ ", State: " + FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED
+ ", Latency: " + latency
@@ -758,7 +759,7 @@
mOperationContext,
statsModality(),
BiometricsProtoEnums.ACTION_UNKNOWN,
- BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
+ getStatsClient(),
mDebugEnabled,
latency,
FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
@@ -784,7 +785,7 @@
+ ", User: " + mUserId
+ ", IsCrypto: " + isCrypto()
+ ", Action: " + BiometricsProtoEnums.ACTION_AUTHENTICATE
- + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
+ + ", Client: " + getStatsClient()
+ ", Reason: " + reason
+ ", Error: " + error
+ ", Latency: " + latency
@@ -796,7 +797,7 @@
mOperationContext,
statsModality(),
BiometricsProtoEnums.ACTION_AUTHENTICATE,
- BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
+ getStatsClient(),
mDebugEnabled,
latency,
error,
@@ -998,6 +999,12 @@
}
}
+ private int getStatsClient() {
+ return mPromptInfo.isForLegacyFingerprintManager()
+ ? BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER
+ : BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT;
+ }
+
@Override
public String toString() {
return "State: " + mState
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
index fdf607d..b2b6ee6 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
@@ -53,7 +53,11 @@
static final int MAXIMUM_ENROLLMENT_NOTIFICATIONS = 1;
@NonNull private final Context mContext;
+ @NonNull private final PackageManager mPackageManager;
+ @NonNull private final FaceManager mFaceManager;
+ @NonNull private final FingerprintManager mFingerprintManager;
+ private final boolean mEnabled;
private final float mThreshold;
private final int mModality;
private boolean mPersisterInitialized = false;
@@ -80,12 +84,17 @@
public AuthenticationStatsCollector(@NonNull Context context, int modality,
@NonNull BiometricNotification biometricNotification) {
mContext = context;
+ mEnabled = context.getResources().getBoolean(R.bool.config_biometricFrrNotificationEnabled);
mThreshold = context.getResources()
.getFraction(R.fraction.config_biometricNotificationFrrThreshold, 1, 1);
mUserAuthenticationStatsMap = new HashMap<>();
mModality = modality;
mBiometricNotification = biometricNotification;
+ mPackageManager = context.getPackageManager();
+ mFaceManager = mContext.getSystemService(FaceManager.class);
+ mFingerprintManager = mContext.getSystemService(FingerprintManager.class);
+
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
context.registerReceiver(mBroadcastReceiver, intentFilter);
@@ -108,6 +117,18 @@
/** Update total authentication and rejected attempts. */
public void authenticate(int userId, boolean authenticated) {
+
+ // Don't collect data if the feature is disabled.
+ if (!mEnabled) {
+ return;
+ }
+
+ // Don't collect data for single-modality devices or user has both biometrics enrolled.
+ if (isSingleModalityDevice()
+ || (hasEnrolledFace(userId) && hasEnrolledFingerprint(userId))) {
+ return;
+ }
+
// SharedPreference is not ready when starting system server, initialize
// mUserAuthenticationStatsMap in authentication to ensure SharedPreference
// is ready for application use.
@@ -150,25 +171,9 @@
authenticationStats.resetData();
- final PackageManager packageManager = mContext.getPackageManager();
+ final boolean hasEnrolledFace = hasEnrolledFace(userId);
+ final boolean hasEnrolledFingerprint = hasEnrolledFingerprint(userId);
- // Don't send notification to single-modality devices.
- if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
- || !packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) {
- return;
- }
-
- final FaceManager faceManager = mContext.getSystemService(FaceManager.class);
- final boolean hasEnrolledFace = faceManager.hasEnrolledTemplates(userId);
-
- final FingerprintManager fingerprintManager = mContext
- .getSystemService(FingerprintManager.class);
- final boolean hasEnrolledFingerprint = fingerprintManager.hasEnrolledTemplates(userId);
-
- // Don't send notification when both face and fingerprint are enrolled.
- if (hasEnrolledFace && hasEnrolledFingerprint) {
- return;
- }
if (hasEnrolledFace && !hasEnrolledFingerprint) {
mBiometricNotification.sendFpEnrollNotification(mContext);
authenticationStats.updateNotificationCounter();
@@ -199,6 +204,19 @@
}
}
+ private boolean isSingleModalityDevice() {
+ return !mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
+ || !mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE);
+ }
+
+ private boolean hasEnrolledFace(int userId) {
+ return mFaceManager.hasEnrolledTemplates(userId);
+ }
+
+ private boolean hasEnrolledFingerprint(int userId) {
+ return mFingerprintManager.hasEnrolledTemplates(userId);
+ }
+
/**
* Only being used in tests. Callers should not make any changes to the returned
* authentication stats.
diff --git a/services/core/java/com/android/server/biometrics/BiometricSensor.java b/services/core/java/com/android/server/biometrics/BiometricSensor.java
index 937e3f8..42dd36a 100644
--- a/services/core/java/com/android/server/biometrics/BiometricSensor.java
+++ b/services/core/java/com/android/server/biometrics/BiometricSensor.java
@@ -106,12 +106,13 @@
void goToStateWaitingForCookie(boolean requireConfirmation, IBinder token, long sessionId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
- long requestId, int cookie, boolean allowBackgroundAuthentication)
+ long requestId, int cookie, boolean allowBackgroundAuthentication,
+ boolean isForLegacyFingerprintManager)
throws RemoteException {
mCookie = cookie;
impl.prepareForAuthentication(requireConfirmation, token,
sessionId, userId, sensorReceiver, opPackageName, requestId, mCookie,
- allowBackgroundAuthentication);
+ allowBackgroundAuthentication, isForLegacyFingerprintManager);
mSensorState = STATE_WAITING_FOR_COOKIE;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 6ac1631..78c95ad 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -283,7 +283,11 @@
}
try {
- listener.onAuthenticationFailed(getSensorId());
+ if (listener != null) {
+ listener.onAuthenticationFailed(getSensorId());
+ } else {
+ Slog.e(TAG, "Received failed auth, but client was not listening");
+ }
} catch (RemoteException e) {
Slog.e(TAG, "Unable to notify listener", e);
mCallback.onClientFinished(this, false);
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
index f1c74f0..2aec9ae 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
@@ -176,6 +176,7 @@
.setSmallIcon(R.drawable.ic_lock)
.setContentTitle(title)
.setContentText(content)
+ .setStyle(new Notification.BigTextStyle().bigText(content))
.setSubText(name)
.setOnlyAlertOnce(true)
.setLocalOnly(true)
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
index fb64bcc..2211003 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
@@ -62,7 +62,8 @@
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
+ String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication,
+ boolean isForLegacyFingerprintManager)
throws RemoteException {
mFaceService.prepareForAuthentication(requireConfirmation, token, operationId,
sensorReceiver, new FaceAuthenticateOptions.Builder()
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
index d47a57a..b6fa0c1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
@@ -62,7 +62,8 @@
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
+ String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication,
+ boolean isForLegacyFingerprintManager)
throws RemoteException {
mFingerprintService.prepareForAuthentication(token, operationId, sensorReceiver,
new FingerprintAuthenticateOptions.Builder()
@@ -70,7 +71,7 @@
.setUserId(userId)
.setOpPackageName(opPackageName)
.build(),
- requestId, cookie, allowBackgroundAuthentication);
+ requestId, cookie, allowBackgroundAuthentication, isForLegacyFingerprintManager);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 7cc6940..5ce0c8b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -464,7 +464,8 @@
public void prepareForAuthentication(IBinder token, long operationId,
IBiometricSensorReceiver sensorReceiver,
@NonNull FingerprintAuthenticateOptions options,
- long requestId, int cookie, boolean allowBackgroundAuthentication) {
+ long requestId, int cookie, boolean allowBackgroundAuthentication,
+ boolean isForLegacyFingerprintManager) {
super.prepareForAuthentication_enforcePermission();
final ServiceProvider provider = mRegistry.getProviderForSensor(options.getSensorId());
@@ -473,10 +474,13 @@
return;
}
+ final int statsClient =
+ isForLegacyFingerprintManager ? BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER
+ : BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT;
final boolean restricted = true; // BiometricPrompt is always restricted
provider.scheduleAuthenticate(token, operationId, cookie,
new ClientMonitorCallbackConverter(sensorReceiver), options, requestId,
- restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
+ restricted, statsClient,
allowBackgroundAuthentication);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index 51a9385..4502e5d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -128,7 +128,11 @@
vibrateSuccess();
try {
- getListener().onDetected(getSensorId(), getTargetUserId(), mIsStrongBiometric);
+ if (getListener() != null) {
+ getListener().onDetected(getSensorId(), getTargetUserId(), mIsStrongBiometric);
+ } else {
+ Slog.e(TAG, "Listener is null!");
+ }
mCallback.onClientFinished(this, true /* success */);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when sending onDetected", e);
diff --git a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
index 5c0c362..01d1e378 100644
--- a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java
@@ -59,7 +59,8 @@
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long sessionId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
+ String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication,
+ boolean isForLegacyFingerprintManager)
throws RemoteException {
}
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
index adea13f..24c7b87 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
@@ -323,10 +323,15 @@
static ProgramIdentifier identifierToHalProgramIdentifier(ProgramSelector.Identifier id) {
ProgramIdentifier hwId = new ProgramIdentifier();
hwId.type = id.getType();
- if (hwId.type == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT) {
+ if (id.getType() == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT) {
hwId.type = IdentifierType.DAB_SID_EXT;
}
- hwId.value = id.getValue();
+ long value = id.getValue();
+ if (id.getType() == ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT) {
+ hwId.value = (value & 0xFFFF) | ((value >>> 16) << 32);
+ } else {
+ hwId.value = value;
+ }
return hwId;
}
@@ -609,6 +614,9 @@
|| isNewIdentifierInU(info.getPhysicallyTunedTo())) {
return false;
}
+ if (info.getRelatedContent() == null) {
+ return true;
+ }
Iterator<ProgramSelector.Identifier> relatedContentIt = info.getRelatedContent().iterator();
while (relatedContentIt.hasNext()) {
if (isNewIdentifierInU(relatedContentIt.next())) {
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 46cd496..46d56ba 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -401,6 +401,12 @@
}
}
+ void stop() {
+ if (mEglContext != null && mEglDisplay != null) {
+ EGL14.eglDestroyContext(mEglDisplay, mEglContext);
+ }
+ }
+
/**
* Draws an animation frame showing the color fade activated at the
* specified level.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 898a3c4..53921d4 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -143,6 +143,7 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.SettingsWrapper;
import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
@@ -155,7 +156,7 @@
import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.display.utils.SensorUtils;
import com.android.server.input.InputManagerInternal;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -468,6 +469,8 @@
private SensorManager mSensorManager;
private BrightnessTracker mBrightnessTracker;
+ private SmallAreaDetectionController mSmallAreaDetectionController;
+
// Whether minimal post processing is allowed by the user.
@GuardedBy("mSyncRoot")
@@ -540,9 +543,9 @@
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
- mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,
- new LogicalDisplayListener(), mSyncRoot, mHandler,
- new FoldSettingWrapper(mContext.getContentResolver()));
+ mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
+ new FoldSettingProvider(mContext, new SettingsWrapper()), mDisplayDeviceRepo,
+ new LogicalDisplayListener(), mSyncRoot, mHandler);
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
Resources resources = mContext.getResources();
@@ -731,6 +734,8 @@
filter.addAction(Intent.ACTION_DOCK_EVENT);
mContext.registerReceiver(mIdleModeReceiver, filter);
+
+ mSmallAreaDetectionController = SmallAreaDetectionController.create(mContext);
}
@VisibleForTesting
@@ -3046,6 +3051,9 @@
pw.println();
mDisplayModeDirector.dump(pw);
mBrightnessSynchronizer.dump(pw);
+ if (mSmallAreaDetectionController != null) {
+ mSmallAreaDetectionController.dump(pw);
+ }
}
private static float[] getFloatArray(TypedArray array) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 59b8871..e8a954a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -3519,7 +3519,8 @@
DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
int displayId, int displayState) {
- return new DisplayPowerState(blanker, colorFade, displayId, displayState);
+ return new DisplayPowerState(blanker, colorFade, displayId, displayState,
+ new Handler(/*async=*/ true));
}
DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 4db8777..7558c6a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -324,8 +324,6 @@
// Must only be accessed on the handler thread.
private DisplayPowerState mPowerState;
-
-
// The currently active screen on unblocker. This field is non-null whenever
// we are waiting for a callback to release it and unblock the screen.
private ScreenOnUnblocker mPendingScreenOnUnblocker;
@@ -2884,7 +2882,8 @@
DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
int displayId, int displayState) {
- return new DisplayPowerState(blanker, colorFade, displayId, displayState);
+ return new DisplayPowerState(blanker, colorFade, displayId, displayState,
+ new Handler(/*async=*/ true));
}
DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 2c257a1..85c6a6d 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -74,8 +74,9 @@
private volatile boolean mStopped;
DisplayPowerState(
- DisplayBlanker blanker, ColorFade colorFade, int displayId, int displayState) {
- mHandler = new Handler(true /*async*/);
+ DisplayBlanker blanker, ColorFade colorFade, int displayId, int displayState,
+ Handler handler) {
+ mHandler = handler;
mChoreographer = Choreographer.getInstance();
mBlanker = blanker;
mColorFade = colorFade;
@@ -317,6 +318,7 @@
mStopped = true;
mPhotonicModulator.interrupt();
dismissColorFade();
+ stopColorFade();
mCleanListener = null;
mHandler.removeCallbacksAndMessages(null);
}
@@ -376,6 +378,11 @@
}
}
+ // Clears up color fade resources.
+ private void stopColorFade() {
+ if (mColorFade != null) mColorFade.stop();
+ }
+
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 26f8029..f99c051 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -42,7 +42,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -143,7 +143,7 @@
private final Listener mListener;
private final DisplayManagerService.SyncRoot mSyncRoot;
private final LogicalDisplayMapperHandler mHandler;
- private final FoldSettingWrapper mFoldSettingWrapper;
+ private final FoldSettingProvider mFoldSettingProvider;
private final PowerManager mPowerManager;
/**
@@ -189,25 +189,26 @@
private boolean mBootCompleted = false;
private boolean mInteractive;
- LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
+ LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
- @NonNull Handler handler, FoldSettingWrapper foldSettingWrapper) {
- this(context, repo, listener, syncRoot, handler,
+ @NonNull Handler handler) {
+ this(context, foldSettingProvider, repo, listener, syncRoot, handler,
new DeviceStateToLayoutMap((isDefault) -> isDefault ? DEFAULT_DISPLAY
- : sNextNonDefaultDisplayId++), foldSettingWrapper);
+ : sNextNonDefaultDisplayId++));
}
- LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
+ LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
- @NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap,
- FoldSettingWrapper foldSettingWrapper) {
+ @NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap) {
mSyncRoot = syncRoot;
mPowerManager = context.getSystemService(PowerManager.class);
mInteractive = mPowerManager.isInteractive();
mHandler = new LogicalDisplayMapperHandler(handler.getLooper());
mDisplayDeviceRepo = repo;
mListener = listener;
- mFoldSettingWrapper = foldSettingWrapper;
+ mFoldSettingProvider = foldSettingProvider;
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
mSupportsConcurrentInternalDisplays = context.getResources().getBoolean(
com.android.internal.R.bool.config_supportsConcurrentInternalDisplays);
@@ -479,10 +480,13 @@
});
} else if (sleepDevice) {
// Send the device to sleep when required.
+ int goToSleepFlag =
+ mFoldSettingProvider.shouldSleepOnFold() ? 0
+ : PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP;
mHandler.post(() -> {
mPowerManager.goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD,
- PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP);
+ goToSleepFlag);
});
}
}
@@ -556,7 +560,8 @@
&& mDeviceStatesOnWhichToSleep.get(pendingState)
&& !mDeviceStatesOnWhichToSleep.get(currentState)
&& !isOverrideActive
- && isInteractive && isBootCompleted && !mFoldSettingWrapper.shouldStayAwakeOnFold();
+ && isInteractive && isBootCompleted
+ && !mFoldSettingProvider.shouldStayAwakeOnFold();
}
private boolean areAllTransitioningDisplaysOffLocked() {
diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java
index 52b92c4..378cdba 100644
--- a/services/core/java/com/android/server/display/RampAnimator.java
+++ b/services/core/java/com/android/server/display/RampAnimator.java
@@ -31,7 +31,12 @@
private final FloatProperty<T> mProperty;
private float mCurrentValue;
- private float mTargetValue;
+
+ // target in HLG space
+ private float mTargetHlgValue;
+
+ // target in linear space
+ private float mTargetLinearValue;
private float mRate;
private float mAnimationIncreaseMaxTimeSecs;
private float mAnimationDecreaseMaxTimeSecs;
@@ -78,7 +83,8 @@
if (mFirstTime || target != mCurrentValue) {
mFirstTime = false;
mRate = 0;
- mTargetValue = target;
+ mTargetHlgValue = target;
+ mTargetLinearValue = targetLinear;
mCurrentValue = target;
setPropertyValue(target);
mAnimating = false;
@@ -105,13 +111,14 @@
// Otherwise, continue at the previous rate.
if (!mAnimating
|| rate > mRate
- || (target <= mCurrentValue && mCurrentValue <= mTargetValue)
- || (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
+ || (target <= mCurrentValue && mCurrentValue <= mTargetHlgValue)
+ || (mTargetHlgValue <= mCurrentValue && mCurrentValue <= target)) {
mRate = rate;
}
- final boolean changed = (mTargetValue != target);
- mTargetValue = target;
+ final boolean changed = (mTargetHlgValue != target);
+ mTargetHlgValue = target;
+ mTargetLinearValue = targetLinear;
// Start animating.
if (!mAnimating && target != mCurrentValue) {
@@ -135,7 +142,11 @@
* into linear space.
*/
private void setPropertyValue(float val) {
- final float linearVal = BrightnessUtils.convertGammaToLinear(val);
+ // To avoid linearVal inconsistency when converting to HLG and back to linear space
+ // used original target linear value for final animation step
+ float linearVal =
+ val == mTargetHlgValue ? mTargetLinearValue : BrightnessUtils.convertGammaToLinear(
+ val);
mProperty.setValue(mObject, linearVal);
}
@@ -150,13 +161,13 @@
final float scale = ValueAnimator.getDurationScale();
if (scale == 0) {
// Animation off.
- mAnimatedValue = mTargetValue;
+ mAnimatedValue = mTargetHlgValue;
} else {
final float amount = timeDelta * mRate / scale;
- if (mTargetValue > mCurrentValue) {
- mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
+ if (mTargetHlgValue > mCurrentValue) {
+ mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetHlgValue);
} else {
- mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
+ mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetHlgValue);
}
}
final float oldCurrentValue = mCurrentValue;
@@ -164,7 +175,7 @@
if (oldCurrentValue != mCurrentValue) {
setPropertyValue(mCurrentValue);
}
- if (mTargetValue == mCurrentValue) {
+ if (mTargetHlgValue == mCurrentValue) {
mAnimating = false;
}
}
diff --git a/services/core/java/com/android/server/display/SmallAreaDetectionController.java b/services/core/java/com/android/server/display/SmallAreaDetectionController.java
new file mode 100644
index 0000000..adaa539
--- /dev/null
+++ b/services/core/java/com/android/server/display/SmallAreaDetectionController.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManagerInternal;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfigInterface;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Map;
+
+final class SmallAreaDetectionController {
+ private static native void nativeUpdateSmallAreaDetection(int[] uids, float[] thresholds);
+ private static native void nativeSetSmallAreaDetectionThreshold(int uid, float threshold);
+
+ // TODO(b/281720315): Move this to DeviceConfig once server side ready.
+ private static final String KEY_SMALL_AREA_DETECTION_ALLOWLIST =
+ "small_area_detection_allowlist";
+
+ private final Object mLock = new Object();
+ private final Context mContext;
+ private final PackageManagerInternal mPackageManager;
+ private final UserManagerInternal mUserManager;
+ @GuardedBy("mLock")
+ private final Map<String, Float> mAllowPkgMap = new ArrayMap<>();
+ // TODO(b/298722189): Update allowlist when user changes
+ @GuardedBy("mLock")
+ private int[] mUserIds;
+
+ static SmallAreaDetectionController create(@NonNull Context context) {
+ final SmallAreaDetectionController controller =
+ new SmallAreaDetectionController(context, DeviceConfigInterface.REAL);
+ final String property = DeviceConfigInterface.REAL.getProperty(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_SMALL_AREA_DETECTION_ALLOWLIST);
+ controller.updateAllowlist(property);
+ return controller;
+ }
+
+ @VisibleForTesting
+ SmallAreaDetectionController(Context context, DeviceConfigInterface deviceConfig) {
+ mContext = context;
+ mPackageManager = LocalServices.getService(PackageManagerInternal.class);
+ mUserManager = LocalServices.getService(UserManagerInternal.class);
+ deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ BackgroundThread.getExecutor(),
+ new SmallAreaDetectionController.OnPropertiesChangedListener());
+ mPackageManager.getPackageList(new PackageReceiver());
+ }
+
+ @VisibleForTesting
+ void updateAllowlist(@Nullable String property) {
+ synchronized (mLock) {
+ mAllowPkgMap.clear();
+ if (property != null) {
+ final String[] mapStrings = property.split(",");
+ for (String mapString : mapStrings) putToAllowlist(mapString);
+ } else {
+ final String[] defaultMapStrings = mContext.getResources()
+ .getStringArray(R.array.config_smallAreaDetectionAllowlist);
+ for (String defaultMapString : defaultMapStrings) putToAllowlist(defaultMapString);
+ }
+ updateSmallAreaDetection();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void putToAllowlist(String rowData) {
+ // Data format: package:threshold - e.g. "com.abc.music:0.05"
+ final String[] items = rowData.split(":");
+ if (items.length == 2) {
+ try {
+ final String pkg = items[0];
+ final float threshold = Float.valueOf(items[1]);
+ mAllowPkgMap.put(pkg, threshold);
+ } catch (Exception e) {
+ // Just skip if items[1] - the threshold is not parsable number
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void updateUidListForAllUsers(SparseArray<Float> list, String pkg, float threshold) {
+ for (int i = 0; i < mUserIds.length; i++) {
+ final int userId = mUserIds[i];
+ final int uid = mPackageManager.getPackageUid(pkg, 0, userId);
+ if (uid > 0) list.put(uid, threshold);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void updateSmallAreaDetection() {
+ if (mAllowPkgMap.isEmpty()) return;
+
+ mUserIds = mUserManager.getUserIds();
+
+ final SparseArray<Float> uidThresholdList = new SparseArray<>();
+ for (String pkg : mAllowPkgMap.keySet()) {
+ final float threshold = mAllowPkgMap.get(pkg);
+ updateUidListForAllUsers(uidThresholdList, pkg, threshold);
+ }
+
+ final int[] uids = new int[uidThresholdList.size()];
+ final float[] thresholds = new float[uidThresholdList.size()];
+ for (int i = 0; i < uidThresholdList.size(); i++) {
+ uids[i] = uidThresholdList.keyAt(i);
+ thresholds[i] = uidThresholdList.valueAt(i);
+ }
+ updateSmallAreaDetection(uids, thresholds);
+ }
+
+ @VisibleForTesting
+ void updateSmallAreaDetection(int[] uids, float[] thresholds) {
+ nativeUpdateSmallAreaDetection(uids, thresholds);
+ }
+
+ void setSmallAreaDetectionThreshold(int uid, float threshold) {
+ nativeSetSmallAreaDetectionThreshold(uid, threshold);
+ }
+
+ void dump(PrintWriter pw) {
+ pw.println("Small area detection allowlist");
+ pw.println(" Packages:");
+ synchronized (mLock) {
+ for (String pkg : mAllowPkgMap.keySet()) {
+ pw.println(" " + pkg + " threshold = " + mAllowPkgMap.get(pkg));
+ }
+ pw.println(" mUserIds=" + Arrays.toString(mUserIds));
+ }
+ }
+
+ private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
+ public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+ if (properties.getKeyset().contains(KEY_SMALL_AREA_DETECTION_ALLOWLIST)) {
+ updateAllowlist(
+ properties.getString(KEY_SMALL_AREA_DETECTION_ALLOWLIST, null /*default*/));
+ }
+ }
+ }
+
+ private final class PackageReceiver implements PackageManagerInternal.PackageListObserver {
+ @Override
+ public void onPackageAdded(@NonNull String packageName, int uid) {
+ synchronized (mLock) {
+ if (mAllowPkgMap.containsKey(packageName)) {
+ setSmallAreaDetectionThreshold(uid, mAllowPkgMap.get(packageName));
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 9f480b6..d76568f 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -161,6 +161,8 @@
int width, int height, int densityDpi) {
VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
if (device != null) {
+ Slog.v(TAG, "Resize VirtualDisplay " + device.mName + " to " + width
+ + " " + height);
device.resizeLocked(width, height, densityDpi);
}
}
@@ -177,6 +179,7 @@
public void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) {
VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
if (device != null) {
+ Slog.v(TAG, "Update surface for VirtualDisplay " + device.mName);
device.setSurfaceLocked(surface);
}
}
@@ -191,6 +194,7 @@
public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) {
VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
if (device != null) {
+ Slog.v(TAG, "Release VirtualDisplay " + device.mName);
device.destroyLocked(true);
appToken.unlinkToDeath(device, 0);
}
diff --git a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
index aa99dab..7b61387 100644
--- a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
+++ b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
@@ -235,6 +235,7 @@
@Nullable
HandwritingSession startHandwritingSession(
int requestId, int imePid, int imeUid, IBinder focusedWindowToken) {
+ clearPendingHandwritingDelegation();
if (mHandwritingSurface == null) {
Slog.e(TAG, "Cannot start handwriting session: Handwriting was not initialized.");
return null;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 6509126..a1d28da 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3071,8 +3071,13 @@
ConcurrentUtils.waitForFutureNoInterrupt(mImeDrawsImeNavBarResLazyInitFuture,
"Waiting for the lazy init of mImeDrawsImeNavBarRes");
}
+ // Whether the current display has a navigation bar. When this is false (e.g. emulator),
+ // the IME should not draw the IME navigation bar.
+ final boolean hasNavigationBar = mWindowManagerInternal
+ .hasNavigationBar(mCurTokenDisplayId != INVALID_DISPLAY
+ ? mCurTokenDisplayId : DEFAULT_DISPLAY);
final boolean canImeDrawsImeNavBar =
- mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get();
+ mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get() && hasNavigationBar;
final boolean shouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherLocked(
InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE);
return (canImeDrawsImeNavBar ? InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR : 0)
@@ -3359,15 +3364,18 @@
} else {
// If subtype is null, try to find the most applicable one from
// getCurrentInputMethodSubtype.
+ subtypeId = NOT_A_SUBTYPE_ID;
newSubtype = getCurrentInputMethodSubtypeLocked();
+ if (newSubtype != null) {
+ for (int i = 0; i < subtypeCount; ++i) {
+ if (Objects.equals(newSubtype, info.getSubtypeAt(i))) {
+ subtypeId = i;
+ break;
+ }
+ }
+ }
}
- if (newSubtype == null || oldSubtype == null) {
- Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
- + ", new subtype = " + newSubtype);
- notifyInputMethodSubtypeChangedLocked(userId, info, null);
- return;
- }
- if (!newSubtype.equals(oldSubtype)) {
+ if (!Objects.equals(newSubtype, oldSubtype)) {
setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
IInputMethodInvoker curMethod = getCurMethodLocked();
if (curMethod != null) {
@@ -3432,13 +3440,19 @@
@BinderThread
@Override
public void startStylusHandwriting(IInputMethodClient client) {
+ startStylusHandwriting(client, false /* usesDelegation */);
+ }
+
+ private void startStylusHandwriting(IInputMethodClient client, boolean usesDelegation) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.startStylusHandwriting");
try {
ImeTracing.getInstance().triggerManagerServiceDump(
"InputMethodManagerService#startStylusHandwriting");
int uid = Binder.getCallingUid();
synchronized (ImfLock.class) {
- mHwController.clearPendingHandwritingDelegation();
+ if (!usesDelegation) {
+ mHwController.clearPendingHandwritingDelegation();
+ }
if (!canInteractWithImeLocked(uid, client, "startStylusHandwriting",
null /* statsToken */)) {
return;
@@ -3520,7 +3534,7 @@
return false;
}
- startStylusHandwriting(client);
+ startStylusHandwriting(client, true /* usesDelegation */);
return true;
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 24dbce4..390a3b2 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -194,8 +194,12 @@
mApplicationKeyStorage = applicationKeyStorage;
mTestCertHelper = testOnlyInsecureCertificateHelper;
mCleanupManager = cleanupManager;
- // Clears data for removed users.
- mCleanupManager.verifyKnownUsers();
+ try {
+ // Clears data for removed users.
+ mCleanupManager.verifyKnownUsers();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to verify known users", e);
+ }
try {
mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mDatabase);
} catch (NoSuchAlgorithmException e) {
diff --git a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
index e31a7fc..1980403 100644
--- a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
@@ -508,7 +508,11 @@
case BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED:
clearActiveRoutesWithType(MediaRoute2Info.TYPE_BLUETOOTH_A2DP);
if (device != null) {
- addActiveRoute(mBluetoothRoutes.get(device.getAddress()));
+ if (DEBUG) {
+ Log.d(TAG, "Setting active a2dp devices. device=" + device);
+ }
+
+ addActiveDevices(device);
}
notifyBluetoothRoutesUpdated();
break;
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 802a7f2..dfd317c 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -956,6 +956,7 @@
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
+ Slog.v(TAG, "Start the token instance " + this);
// Cache result of calling into ActivityManagerService outside of the lock, to prevent
// deadlock with WindowManagerService.
final boolean hasFGS = mActivityManagerInternal.hasRunningForegroundService(
@@ -975,9 +976,6 @@
throw new SecurityException("Media projections require a foreground service"
+ " of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION");
}
-
- mCallback = callback;
- registerCallback(mCallback);
try {
mToken = callback.asBinder();
mDeathEater = () -> {
@@ -1022,6 +1020,11 @@
}
}
startProjectionLocked(this);
+
+ // Register new callbacks after stop has been dispatched to previous session.
+ mCallback = callback;
+ registerCallback(mCallback);
+
// Mark this token as used when the app gets the MediaProjection instance.
mCountStarts++;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d662aae..204e358 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1365,11 +1365,13 @@
assertCallerIsOwnerRootOrVerifier();
synchronized (mLock) {
assertPreparedAndNotDestroyedLocked("getNames");
+ String[] names;
if (!isCommitted()) {
- return getNamesLocked();
+ names = getNamesLocked();
} else {
- return getStageDirContentsLocked();
+ names = getStageDirContentsLocked();
}
+ return ArrayUtils.removeString(names, APP_METADATA_FILE_NAME);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index cab90d2..f5c5867 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2665,7 +2665,8 @@
}
}
- private void setUserRestrictionInner(int userId, @NonNull String key, boolean value) {
+ @VisibleForTesting
+ void setUserRestrictionInner(int userId, @NonNull String key, boolean value) {
if (!UserRestrictionsUtils.isValidRestriction(key)) {
Slog.e(LOG_TAG, "Setting invalid restriction " + key);
return;
@@ -4273,11 +4274,11 @@
UserRestrictionsUtils.writeRestrictions(serializer,
mDevicePolicyUserRestrictions.getRestrictions(UserHandle.USER_ALL),
- TAG_DEVICE_POLICY_RESTRICTIONS);
+ TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS);
UserRestrictionsUtils.writeRestrictions(serializer,
mDevicePolicyUserRestrictions.getRestrictions(userInfo.id),
- TAG_DEVICE_POLICY_RESTRICTIONS);
+ TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS);
}
if (userData.account != null) {
diff --git a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
index 4f221b5..9718194 100644
--- a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
@@ -244,6 +244,8 @@
&& mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting
&& mUserId == that.mUserId && mUserConfigAllowed == that.mUserConfigAllowed
&& mSystemClockUpdateThresholdMillis == that.mSystemClockUpdateThresholdMillis
+ && mSystemClockConfidenceThresholdMillis
+ == that.mSystemClockConfidenceThresholdMillis
&& mAutoSuggestionLowerBound.equals(that.mAutoSuggestionLowerBound)
&& mManualSuggestionLowerBound.equals(that.mManualSuggestionLowerBound)
&& mSuggestionUpperBound.equals(that.mSuggestionUpperBound)
@@ -253,7 +255,8 @@
@Override
public int hashCode() {
int result = Objects.hash(mAutoDetectionSupported, mAutoDetectionEnabledSetting, mUserId,
- mUserConfigAllowed, mSystemClockUpdateThresholdMillis, mAutoSuggestionLowerBound,
+ mUserConfigAllowed, mSystemClockUpdateThresholdMillis,
+ mSystemClockConfidenceThresholdMillis, mAutoSuggestionLowerBound,
mManualSuggestionLowerBound, mSuggestionUpperBound);
result = 31 * result + Arrays.hashCode(mOriginPriorities);
return result;
diff --git a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
index fc960d8..c52f8f8 100644
--- a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
+++ b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
@@ -22,15 +22,16 @@
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.server.AlarmManagerInternal;
import com.android.server.LocalServices;
import com.android.server.SystemClockTime;
import com.android.server.SystemClockTime.TimeConfidence;
-import com.android.server.timezonedetector.StateChangeListener;
-import java.io.PrintWriter;
+import java.time.Duration;
+import java.time.Instant;
import java.util.Objects;
/**
@@ -41,14 +42,11 @@
private static final String LOG_TAG = TimeDetectorService.TAG;
@NonNull private final Handler mHandler;
- @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
@NonNull private final PowerManager.WakeLock mWakeLock;
@NonNull private final AlarmManagerInternal mAlarmManagerInternal;
- EnvironmentImpl(@NonNull Context context, @NonNull Handler handler,
- @NonNull ServiceConfigAccessor serviceConfigAccessor) {
+ EnvironmentImpl(@NonNull Context context, @NonNull Handler handler) {
mHandler = Objects.requireNonNull(handler);
- mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
PowerManager powerManager = context.getSystemService(PowerManager.class);
mWakeLock = Objects.requireNonNull(
@@ -59,19 +57,6 @@
}
@Override
- public void setConfigurationInternalChangeListener(
- @NonNull StateChangeListener listener) {
- StateChangeListener stateChangeListener =
- () -> mHandler.post(listener::onChange);
- mServiceConfigAccessor.addConfigurationInternalChangeListener(stateChangeListener);
- }
-
- @Override
- public ConfigurationInternal getCurrentUserConfigurationInternal() {
- return mServiceConfigAccessor.getCurrentUserConfigurationInternal();
- }
-
- @Override
public void acquireWakeLock() {
if (mWakeLock.isHeld()) {
Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " already held");
@@ -126,8 +111,19 @@
}
@Override
- public void dumpDebugLog(@NonNull PrintWriter printWriter) {
- SystemClockTime.dump(printWriter);
+ public void dumpDebugLog(@NonNull IndentingPrintWriter pw) {
+ long elapsedRealtimeMillis = elapsedRealtimeMillis();
+ pw.printf("elapsedRealtimeMillis()=%s (%s)\n",
+ Duration.ofMillis(elapsedRealtimeMillis), elapsedRealtimeMillis);
+ long systemClockMillis = systemClockMillis();
+ pw.printf("systemClockMillis()=%s (%s)\n",
+ Instant.ofEpochMilli(systemClockMillis), systemClockMillis);
+ pw.println("systemClockConfidence()=" + systemClockConfidence());
+
+ pw.println("SystemClockTime debug log:");
+ pw.increaseIndent();
+ SystemClockTime.dump(pw);
+ pw.decreaseIndent();
}
@Override
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 22f096b..d88f426 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -96,8 +96,8 @@
CallerIdentityInjector callerIdentityInjector = CallerIdentityInjector.REAL;
TimeDetectorService service = new TimeDetectorService(
- context, handler, callerIdentityInjector, serviceConfigAccessor,
- timeDetectorStrategy, NtpTrustedTime.getInstance(context));
+ context, handler, callerIdentityInjector, timeDetectorStrategy,
+ NtpTrustedTime.getInstance(context));
// Publish the binder service so it can be accessed from other (appropriately
// permissioned) processes.
@@ -108,7 +108,6 @@
@NonNull private final Handler mHandler;
@NonNull private final Context mContext;
@NonNull private final CallerIdentityInjector mCallerIdentityInjector;
- @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
@NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;
@NonNull private final NtpTrustedTime mNtpTrustedTime;
@@ -123,20 +122,18 @@
@VisibleForTesting
public TimeDetectorService(@NonNull Context context, @NonNull Handler handler,
@NonNull CallerIdentityInjector callerIdentityInjector,
- @NonNull ServiceConfigAccessor serviceConfigAccessor,
@NonNull TimeDetectorStrategy timeDetectorStrategy,
@NonNull NtpTrustedTime ntpTrustedTime) {
mContext = Objects.requireNonNull(context);
mHandler = Objects.requireNonNull(handler);
mCallerIdentityInjector = Objects.requireNonNull(callerIdentityInjector);
- mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
mTimeDetectorStrategy = Objects.requireNonNull(timeDetectorStrategy);
mNtpTrustedTime = Objects.requireNonNull(ntpTrustedTime);
- // Wire up a change listener so that ITimeZoneDetectorListeners can be notified when
- // the configuration changes for any reason.
- mServiceConfigAccessor.addConfigurationInternalChangeListener(
- () -> mHandler.post(this::handleConfigurationInternalChangedOnHandlerThread));
+ // Wire up a change listener so that ITimeDetectorListeners can be notified when the
+ // detector state changes for any reason.
+ mTimeDetectorStrategy.addChangeListener(
+ () -> mHandler.post(this::handleChangeOnHandlerThread));
}
@Override
@@ -151,10 +148,8 @@
final long token = mCallerIdentityInjector.clearCallingIdentity();
try {
- ConfigurationInternal configurationInternal =
- mServiceConfigAccessor.getConfigurationInternal(userId);
- final boolean bypassUserPolicyCheck = false;
- return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyCheck);
+ final boolean bypassUserPolicyChecks = false;
+ return mTimeDetectorStrategy.getCapabilitiesAndConfig(userId, bypassUserPolicyChecks);
} finally {
mCallerIdentityInjector.restoreCallingIdentity(token);
}
@@ -180,9 +175,9 @@
final long token = mCallerIdentityInjector.clearCallingIdentity();
try {
- final boolean bypassUserPolicyCheck = false;
- return mServiceConfigAccessor.updateConfiguration(
- resolvedUserId, configuration, bypassUserPolicyCheck);
+ final boolean bypassUserPolicyChecks = false;
+ return mTimeDetectorStrategy.updateConfiguration(
+ resolvedUserId, configuration, bypassUserPolicyChecks);
} finally {
mCallerIdentityInjector.restoreCallingIdentity(token);
}
@@ -262,7 +257,7 @@
}
}
- private void handleConfigurationInternalChangedOnHandlerThread() {
+ private void handleChangeOnHandlerThread() {
// Configuration has changed, but each user may have a different view of the configuration.
// It's possible that this will cause unnecessary notifications but that shouldn't be a
// problem.
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index 11cec66..15c0a80 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -21,6 +21,8 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.time.ExternalTimeSuggestion;
+import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
import android.app.time.TimeState;
import android.app.time.UnixEpochTime;
import android.app.timedetector.ManualTimeSuggestion;
@@ -87,6 +89,48 @@
*/
boolean confirmTime(@NonNull UnixEpochTime confirmationTime);
+ /**
+ * Adds a listener that will be triggered when something changes that could affect the result
+ * of the {@link #getCapabilitiesAndConfig} call for the <em>current user only</em>. This
+ * includes the current user changing. This is exposed so that (indirect) users like SettingsUI
+ * can monitor for changes to data derived from {@link TimeCapabilitiesAndConfig} and update
+ * the UI accordingly.
+ */
+ void addChangeListener(@NonNull StateChangeListener listener);
+
+ /**
+ * Returns a {@link TimeCapabilitiesAndConfig} object for the specified user.
+ *
+ * <p>The strategy is dependent on device state like current user, settings and device config.
+ * These updates are usually handled asynchronously, so callers should expect some delay between
+ * a change being made directly to services like settings and the strategy becoming aware of
+ * them. Changes made via {@link #updateConfiguration} will be visible immediately.
+ *
+ * @param userId the user ID to retrieve the information for
+ * @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
+ * policy restrictions that should apply to actual users can be ignored
+ */
+ TimeCapabilitiesAndConfig getCapabilitiesAndConfig(
+ @UserIdInt int userId, boolean bypassUserPolicyChecks);
+
+ /**
+ * Updates the configuration properties that control a device's time behavior.
+ *
+ * <p>This method returns {@code true} if the configuration was changed, {@code false}
+ * otherwise.
+ *
+ * <p>See {@link #getCapabilitiesAndConfig} for guarantees about visibility of updates to
+ * subsequent calls.
+ *
+ * @param userId the current user ID, supplied to make sure that the asynchronous process
+ * that happens when users switch is completed when the call is made
+ * @param configuration the configuration changes
+ * @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
+ * policy restrictions that should apply to actual users can be ignored
+ */
+ boolean updateConfiguration(@UserIdInt int userId,
+ @NonNull TimeConfiguration configuration, boolean bypassUserPolicyChecks);
+
/** Processes the suggested time from telephony sources. */
void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion suggestion);
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index b293bac..fd35df6 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -30,6 +30,7 @@
import android.app.time.ExternalTimeSuggestion;
import android.app.time.TimeCapabilities;
import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
import android.app.time.TimeState;
import android.app.time.UnixEpochTime;
import android.app.timedetector.ManualTimeSuggestion;
@@ -48,10 +49,10 @@
import com.android.server.timezonedetector.ReferenceWithHistory;
import com.android.server.timezonedetector.StateChangeListener;
-import java.io.PrintWriter;
-import java.time.Duration;
import java.time.Instant;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
/**
@@ -94,6 +95,12 @@
@NonNull
private final Environment mEnvironment;
+ @NonNull
+ private final ServiceConfigAccessor mServiceConfigAccessor;
+
+ @GuardedBy("this")
+ @NonNull private final List<StateChangeListener> mStateChangeListeners = new ArrayList<>();
+
@GuardedBy("this")
@NonNull
private ConfigurationInternal mCurrentConfigurationInternal;
@@ -139,16 +146,6 @@
*/
public interface Environment {
- /**
- * Sets a {@link StateChangeListener} that will be invoked when there are any changes that
- * could affect the content of {@link ConfigurationInternal}.
- * This is invoked during system server setup.
- */
- void setConfigurationInternalChangeListener(@NonNull StateChangeListener listener);
-
- /** Returns the {@link ConfigurationInternal} for the current user. */
- @NonNull ConfigurationInternal getCurrentUserConfigurationInternal();
-
/** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */
void acquireWakeLock();
@@ -174,16 +171,15 @@
/** Release the wake lock acquired by a call to {@link #acquireWakeLock()}. */
void releaseWakeLock();
-
/**
* Adds a standalone entry to the time debug log.
*/
void addDebugLogEntry(@NonNull String logMsg);
/**
- * Dumps the time debug log to the supplied {@link PrintWriter}.
+ * Dumps the time debug log to the supplied {@link IndentingPrintWriter}.
*/
- void dumpDebugLog(PrintWriter printWriter);
+ void dumpDebugLog(IndentingPrintWriter ipw);
/**
* Requests that the supplied runnable is invoked asynchronously.
@@ -195,19 +191,23 @@
@NonNull Context context, @NonNull Handler handler,
@NonNull ServiceConfigAccessor serviceConfigAccessor) {
- TimeDetectorStrategyImpl.Environment environment =
- new EnvironmentImpl(context, handler, serviceConfigAccessor);
- return new TimeDetectorStrategyImpl(environment);
+ TimeDetectorStrategyImpl.Environment environment = new EnvironmentImpl(context, handler);
+ return new TimeDetectorStrategyImpl(environment, serviceConfigAccessor);
}
@VisibleForTesting
- TimeDetectorStrategyImpl(@NonNull Environment environment) {
+ TimeDetectorStrategyImpl(@NonNull Environment environment,
+ @NonNull ServiceConfigAccessor serviceConfigAccessor) {
mEnvironment = Objects.requireNonNull(environment);
+ mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
synchronized (this) {
- mEnvironment.setConfigurationInternalChangeListener(
- this::handleConfigurationInternalChanged);
- mCurrentConfigurationInternal = mEnvironment.getCurrentUserConfigurationInternal();
+ // Listen for config and user changes and get an initial snapshot of configuration.
+ StateChangeListener stateChangeListener = this::handleConfigurationInternalMaybeChanged;
+ mServiceConfigAccessor.addConfigurationInternalChangeListener(stateChangeListener);
+
+ // Initialize mCurrentConfigurationInternal with a starting value.
+ updateCurrentConfigurationInternalIfRequired("TimeDetectorStrategyImpl:");
}
}
@@ -421,6 +421,57 @@
}
}
+ @GuardedBy("this")
+ private void notifyStateChangeListenersAsynchronously() {
+ for (StateChangeListener listener : mStateChangeListeners) {
+ // This is queuing asynchronous notification, so no need to surrender the "this" lock.
+ mEnvironment.runAsync(listener::onChange);
+ }
+ }
+
+ @Override
+ public synchronized void addChangeListener(@NonNull StateChangeListener listener) {
+ mStateChangeListeners.add(listener);
+ }
+
+ @Override
+ public synchronized TimeCapabilitiesAndConfig getCapabilitiesAndConfig(@UserIdInt int userId,
+ boolean bypassUserPolicyChecks) {
+ ConfigurationInternal configurationInternal;
+ if (mCurrentConfigurationInternal.getUserId() == userId) {
+ // Use the cached snapshot we have.
+ configurationInternal = mCurrentConfigurationInternal;
+ } else {
+ // This is not a common case: It would be unusual to want the configuration for a user
+ // other than the "current" user, but it is supported because it is trivial to do so.
+ // Unlike the current user config, there's no cached copy to worry about so read it
+ // directly from mServiceConfigAccessor.
+ configurationInternal = mServiceConfigAccessor.getConfigurationInternal(userId);
+ }
+ return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
+ }
+
+ @Override
+ public synchronized boolean updateConfiguration(@UserIdInt int userId,
+ @NonNull TimeConfiguration configuration, boolean bypassUserPolicyChecks) {
+ // Write-through
+ boolean updateSuccessful = mServiceConfigAccessor.updateConfiguration(
+ userId, configuration, bypassUserPolicyChecks);
+
+ // The update above will trigger config update listeners asynchronously if they are needed,
+ // but that could mean an immediate call to getCapabilitiesAndConfig() for the current user
+ // wouldn't see the update. So, handle the cache update and notifications here. When the
+ // async update listener triggers it will find everything already up to date and do nothing.
+ if (updateSuccessful) {
+ String logMsg = "updateConfiguration:"
+ + " userId=" + userId
+ + ", configuration=" + configuration
+ + ", bypassUserPolicyChecks=" + bypassUserPolicyChecks;
+ updateCurrentConfigurationInternalIfRequired(logMsg);
+ }
+ return updateSuccessful;
+ }
+
@Override
public synchronized void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion suggestion) {
// Empty time suggestion means that telephony network connectivity has been lost.
@@ -448,26 +499,49 @@
doAutoTimeDetection(reason);
}
- private synchronized void handleConfigurationInternalChanged() {
- ConfigurationInternal currentUserConfig =
- mEnvironment.getCurrentUserConfigurationInternal();
- String logMsg = "handleConfigurationInternalChanged:"
- + " oldConfiguration=" + mCurrentConfigurationInternal
- + ", newConfiguration=" + currentUserConfig;
- addDebugLogEntry(logMsg);
- mCurrentConfigurationInternal = currentUserConfig;
+ /**
+ * Handles a configuration change notification.
+ */
+ private synchronized void handleConfigurationInternalMaybeChanged() {
+ String logMsg = "handleConfigurationInternalMaybeChanged:";
+ updateCurrentConfigurationInternalIfRequired(logMsg);
+ }
- boolean autoDetectionEnabled =
- mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior();
- // When automatic time detection is enabled we update the system clock instantly if we can.
- // Conversely, when automatic time detection is disabled we leave the clock as it is.
- if (autoDetectionEnabled) {
- String reason = "Auto time zone detection config changed.";
- doAutoTimeDetection(reason);
- } else {
- // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what
- // it should be in future.
- mLastAutoSystemClockTimeSet = null;
+ @GuardedBy("this")
+ private void updateCurrentConfigurationInternalIfRequired(@NonNull String logMsg) {
+ ConfigurationInternal newCurrentConfigurationInternal =
+ mServiceConfigAccessor.getCurrentUserConfigurationInternal();
+ // mCurrentConfigurationInternal is null the first time this method is called.
+ ConfigurationInternal oldCurrentConfigurationInternal = mCurrentConfigurationInternal;
+
+ // If the configuration actually changed, update the cached copy synchronously and do
+ // other necessary house-keeping / (async) listener notifications.
+ if (!newCurrentConfigurationInternal.equals(oldCurrentConfigurationInternal)) {
+ mCurrentConfigurationInternal = newCurrentConfigurationInternal;
+
+ logMsg = new StringBuilder(logMsg)
+ .append(" [oldConfiguration=").append(oldCurrentConfigurationInternal)
+ .append(", newConfiguration=").append(newCurrentConfigurationInternal)
+ .append("]")
+ .toString();
+ addDebugLogEntry(logMsg);
+
+ // The configuration and maybe the status changed so notify listeners.
+ notifyStateChangeListenersAsynchronously();
+
+ boolean autoDetectionEnabled =
+ mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior();
+ // When automatic time detection is enabled we update the system clock instantly if we
+ // can. Conversely, when automatic time detection is disabled we leave the clock as it
+ // is.
+ if (autoDetectionEnabled) {
+ String reason = "Auto time zone detection config changed.";
+ doAutoTimeDetection(reason);
+ } else {
+ // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict
+ // what it should be in future.
+ mLastAutoSystemClockTimeSet = null;
+ }
}
}
@@ -489,13 +563,11 @@
ipw.println("[Capabilities="
+ mCurrentConfigurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks)
+ "]");
- long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
- ipw.printf("mEnvironment.elapsedRealtimeMillis()=%s (%s)\n",
- Duration.ofMillis(elapsedRealtimeMillis), elapsedRealtimeMillis);
- long systemClockMillis = mEnvironment.systemClockMillis();
- ipw.printf("mEnvironment.systemClockMillis()=%s (%s)\n",
- Instant.ofEpochMilli(systemClockMillis), systemClockMillis);
- ipw.println("mEnvironment.systemClockConfidence()=" + mEnvironment.systemClockConfidence());
+
+ ipw.println("mEnvironment:");
+ ipw.increaseIndent();
+ mEnvironment.dumpDebugLog(ipw);
+ ipw.decreaseIndent();
ipw.println("Time change log:");
ipw.increaseIndent(); // level 2
@@ -525,6 +597,11 @@
ipw.decreaseIndent(); // level 1
}
+ @VisibleForTesting
+ public synchronized ConfigurationInternal getCachedCapabilitiesAndConfigForTests() {
+ return mCurrentConfigurationInternal;
+ }
+
@GuardedBy("this")
private boolean storeTelephonySuggestion(@NonNull TelephonyTimeSuggestion suggestion) {
UnixEpochTime newUnixEpochTime = suggestion.getUnixEpochTime();
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 01fdc88..7862f58 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -41,6 +41,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
@@ -62,6 +63,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -1304,6 +1306,46 @@
return false;
}
+ /**
+ * Check if the targetPkg can be granted permission to access uri by
+ * the callingUid using the given modeFlags. See {@link #checkGrantUriPermissionUnlocked}.
+ *
+ * @param callingUid The uid of the grantor app that has permissions to the uri.
+ * @param targetPkg The package name of the granted app that needs permissions to the uri.
+ * @param uri The uri for which permissions should be granted.
+ * @param modeFlags The modes to grant. See {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}, etc.
+ * @param userId The userId in which the uri is to be resolved.
+ * @return uid of the target or -1 if permission grant not required. Returns -1 if the caller
+ * does not hold INTERACT_ACROSS_USERS_FULL
+ * @throws SecurityException if the grant is not allowed.
+ */
+ @Override
+ @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ public int checkGrantUriPermission_ignoreNonSystem(int callingUid, String targetPkg, Uri uri,
+ int modeFlags, int userId) {
+ if (!isCallerIsSystemOrPrivileged()) {
+ return Process.INVALID_UID;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ return checkGrantUriPermissionUnlocked(callingUid, targetPkg, uri, modeFlags,
+ userId);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ private boolean isCallerIsSystemOrPrivileged() {
+ final int uid = Binder.getCallingUid();
+ if (uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) {
+ return true;
+ }
+ return ActivityManager.checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ uid, /* owningUid = */-1, /* exported = */ true)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public ArrayList<UriPermission> providePersistentUriGrants() {
final ArrayList<UriPermission> result = new ArrayList<>();
diff --git a/services/core/java/com/android/server/utils/FoldSettingProvider.java b/services/core/java/com/android/server/utils/FoldSettingProvider.java
new file mode 100644
index 0000000..d62628b
--- /dev/null
+++ b/services/core/java/com/android/server/utils/FoldSettingProvider.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.R;
+import com.android.internal.util.SettingsWrapper;
+
+import java.util.Set;
+
+/**
+ * This class provides a convenient way to access the {@link Settings.System#FOLD_LOCK_BEHAVIOR}.
+ * The {@link Settings.System#FOLD_LOCK_BEHAVIOR} setting controls the behavior of the device when
+ * it is folded, and provides the user with three different options to choose from. Those are:
+ * 1. Stay awake on fold: The device will remain unlocked when it is folded.
+ * 2. Selective stay awake: The device will remain unlocked when it is folded only if there are
+ * apps with wakelocks running. This is also the set default behavior.
+ * 3. Sleep on fold: The device will lock when it is folded, regardless of which apps are running
+ * or whether any wakelocks are held.
+ *
+ * Keep the setting values in this class in sync with the values in
+ * {@link com.android.settings.display.FoldLockBehaviorSettings}
+ */
+public class FoldSettingProvider {
+
+ public static final String SETTING_VALUE_STAY_AWAKE_ON_FOLD = "stay_awake_on_fold_key";
+ public static final String SETTING_VALUE_SELECTIVE_STAY_AWAKE = "selective_stay_awake_key";
+ public static final String SETTING_VALUE_SLEEP_ON_FOLD = "sleep_on_fold_key";
+ private static final String SETTING_VALUE_DEFAULT = SETTING_VALUE_SELECTIVE_STAY_AWAKE;
+ private static final Set<String> SETTING_VALUES = Set.of(SETTING_VALUE_STAY_AWAKE_ON_FOLD,
+ SETTING_VALUE_SELECTIVE_STAY_AWAKE, SETTING_VALUE_SLEEP_ON_FOLD);
+ private static final String TAG = "FoldSettingProvider";
+
+ private final ContentResolver mContentResolver;
+ private final boolean mIsFoldLockBehaviorAvailable;
+ private final SettingsWrapper mSettingsWrapper;
+
+ public FoldSettingProvider(Context context, SettingsWrapper settingsWrapper) {
+ mContentResolver = context.getContentResolver();
+ mSettingsWrapper = settingsWrapper;
+ mIsFoldLockBehaviorAvailable = context.getResources().getBoolean(
+ R.bool.config_fold_lock_behavior);
+ }
+
+ /**
+ * Returns whether the device should remain awake after folding.
+ */
+ public boolean shouldStayAwakeOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ }
+
+ /**
+ * Returns whether the device should selective remain awake after folding.
+ */
+ public boolean shouldSelectiveStayAwakeOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_SELECTIVE_STAY_AWAKE);
+ }
+
+ /**
+ * Returns whether the device should strictly sleep after folding.
+ */
+ public boolean shouldSleepOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_SLEEP_ON_FOLD);
+ }
+
+ private String getFoldSettingValue() {
+ if (!mIsFoldLockBehaviorAvailable) {
+ return SETTING_VALUE_DEFAULT;
+ }
+ String foldSettingValue = mSettingsWrapper.getStringForUser(
+ mContentResolver,
+ Settings.System.FOLD_LOCK_BEHAVIOR,
+ UserHandle.USER_CURRENT);
+ foldSettingValue = (foldSettingValue != null) ? foldSettingValue : SETTING_VALUE_DEFAULT;
+ if (!SETTING_VALUES.contains(foldSettingValue)) {
+ Log.e(TAG,
+ "getFoldSettingValue: Invalid setting value, returning default setting value");
+ foldSettingValue = SETTING_VALUE_DEFAULT;
+ }
+
+ return foldSettingValue;
+ }
+}
diff --git a/services/core/java/com/android/server/utils/FoldSettingWrapper.java b/services/core/java/com/android/server/utils/FoldSettingWrapper.java
deleted file mode 100644
index 97a1ac0..0000000
--- a/services/core/java/com/android/server/utils/FoldSettingWrapper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.utils;
-
-import android.content.ContentResolver;
-import android.provider.Settings;
-
-/**
- * A wrapper class for the {@link Settings.System#STAY_AWAKE_ON_FOLD} setting.
- *
- * This class provides a convenient way to access the {@link Settings.System#STAY_AWAKE_ON_FOLD}
- * setting for testing.
- */
-public class FoldSettingWrapper {
- private final ContentResolver mContentResolver;
-
- public FoldSettingWrapper(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
- }
-
- /**
- * Returns whether the device should remain awake after folding.
- */
- public boolean shouldStayAwakeOnFold() {
- try {
- return (Settings.System.getIntForUser(
- mContentResolver,
- Settings.System.STAY_AWAKE_ON_FOLD,
- 0) == 1);
- } catch (Settings.SettingNotFoundException e) {
- return false;
- }
- }
-}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 309a9c0..6601467 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -321,9 +321,6 @@
if (DEBUG) {
Slog.d(TAG, "publish system wallpaper changed!");
}
- if (localSync != null) {
- localSync.complete();
- }
notifyWallpaperChanged(wallpaper);
}
};
@@ -331,7 +328,7 @@
// If this was the system wallpaper, rebind...
bindWallpaperComponentLocked(mImageWallpaper, true, false, wallpaper,
callback);
- notifyColorsWhich |= FLAG_SYSTEM;
+ notifyColorsWhich |= wallpaper.mWhich;
}
if (lockWallpaperChanged) {
@@ -345,9 +342,6 @@
if (DEBUG) {
Slog.d(TAG, "publish lock wallpaper changed!");
}
- if (localSync != null) {
- localSync.complete();
- }
notifyWallpaperChanged(wallpaper);
}
};
@@ -372,9 +366,8 @@
}
saveSettingsLocked(wallpaper.userId);
- // Notify the client immediately if only lockscreen wallpaper changed.
- if (lockWallpaperChanged && !sysWallpaperChanged) {
- notifyWallpaperChanged(wallpaper);
+ if ((sysWallpaperChanged || lockWallpaperChanged) && localSync != null) {
+ localSync.complete();
}
}
@@ -1006,12 +999,11 @@
return;
}
- if (!mWallpaper.wallpaperUpdating
- && mWallpaper.userId == mCurrentUserId) {
+ if (!mWallpaper.wallpaperUpdating && mWallpaper.userId == mCurrentUserId) {
Slog.w(TAG, "Wallpaper reconnect timed out for " + mWallpaper.wallpaperComponent
+ ", reverting to built-in wallpaper!");
- clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId,
- null);
+ int which = mIsLockscreenLiveWallpaperEnabled ? mWallpaper.mWhich : FLAG_SYSTEM;
+ clearWallpaperLocked(true, which, mWallpaper.userId, null);
}
}
};
@@ -1191,7 +1183,7 @@
} else {
// Timeout
Slog.w(TAG, "Reverting to built-in wallpaper!");
- clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
+ clearWallpaperLocked(true, mWallpaper.mWhich, mWallpaper.userId, null);
final String flattened = wpService.flattenToString();
EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
flattened.substring(0, Math.min(flattened.length(),
@@ -1220,7 +1212,7 @@
&& mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
> SystemClock.uptimeMillis()) {
Slog.w(TAG, "Reverting to built-in wallpaper!");
- clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
+ clearWallpaperLocked(true, mWallpaper.mWhich, mWallpaper.userId, null);
} else {
mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
tryToRebind();
@@ -1383,7 +1375,6 @@
lockWp.connection.mWallpaper = lockWp;
mOriginalSystem.mWhich = FLAG_LOCK;
updateEngineFlags(mOriginalSystem);
- notifyWallpaperColorsChanged(lockWp, FLAG_LOCK);
} else {
// Failed rename, use current system wp for both
if (DEBUG) {
@@ -1403,7 +1394,6 @@
updateEngineFlags(mOriginalSystem);
mLockWallpaperMap.put(mNewWallpaper.userId, mOriginalSystem);
mLastLockWallpaper = mOriginalSystem;
- notifyWallpaperColorsChanged(mOriginalSystem, FLAG_LOCK);
}
} else if (mNewWallpaper.mWhich == FLAG_LOCK) {
// New wp is lock only, so old system+lock is now system only
@@ -1417,10 +1407,7 @@
}
}
}
-
- synchronized (mLock) {
- saveSettingsLocked(mNewWallpaper.userId);
- }
+ saveSettingsLocked(mNewWallpaper.userId);
if (DEBUG) {
Slog.v(TAG, "--- wallpaper changed --");
@@ -1439,8 +1426,7 @@
if (mCurrentUserId != getChangingUserId()) {
return;
}
- WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
- if (wallpaper != null) {
+ for (WallpaperData wallpaper: getWallpapers()) {
final ComponentName wpService = wallpaper.wallpaperComponent;
if (wpService != null && wpService.getPackageName().equals(packageName)) {
if (DEBUG_LIVE) {
@@ -1452,7 +1438,9 @@
wallpaper, null)) {
Slog.w(TAG, "Wallpaper " + wpService
+ " no longer available; reverting to default");
- clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
+ int which = mIsLockscreenLiveWallpaperEnabled
+ ? wallpaper.mWhich : FLAG_SYSTEM;
+ clearWallpaperLocked(false, which, wallpaper.userId, null);
}
}
}
@@ -1465,13 +1453,11 @@
if (mCurrentUserId != getChangingUserId()) {
return;
}
- WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
- if (wallpaper != null) {
- if (wallpaper.wallpaperComponent == null
- || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
- return;
+ for (WallpaperData wallpaper: getWallpapers()) {
+ if (wallpaper.wallpaperComponent != null
+ && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
+ doPackagesChangedLocked(true, wallpaper);
}
- doPackagesChangedLocked(true, wallpaper);
}
}
}
@@ -1482,8 +1468,7 @@
if (mCurrentUserId != getChangingUserId()) {
return;
}
- WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
- if (wallpaper != null) {
+ for (WallpaperData wallpaper: getWallpapers()) {
if (wallpaper.wallpaperComponent != null
&& wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
if (DEBUG_LIVE) {
@@ -1507,8 +1492,7 @@
if (mCurrentUserId != getChangingUserId()) {
return false;
}
- WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
- if (wallpaper != null) {
+ for (WallpaperData wallpaper: getWallpapers()) {
boolean res = doPackagesChangedLocked(doit, wallpaper);
changed |= res;
}
@@ -1522,8 +1506,7 @@
if (mCurrentUserId != getChangingUserId()) {
return;
}
- WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
- if (wallpaper != null) {
+ for (WallpaperData wallpaper: getWallpapers()) {
doPackagesChangedLocked(true, wallpaper);
}
}
@@ -1531,6 +1514,7 @@
boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
boolean changed = false;
+ int which = mIsLockscreenLiveWallpaperEnabled ? wallpaper.mWhich : FLAG_SYSTEM;
if (wallpaper.wallpaperComponent != null) {
int change = isPackageDisappearing(wallpaper.wallpaperComponent
.getPackageName());
@@ -1540,7 +1524,7 @@
if (doit) {
Slog.w(TAG, "Wallpaper uninstalled, removing: "
+ wallpaper.wallpaperComponent);
- clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
+ clearWallpaperLocked(false, which, wallpaper.userId, null);
}
}
}
@@ -1561,7 +1545,7 @@
} catch (NameNotFoundException e) {
Slog.w(TAG, "Wallpaper component gone, removing: "
+ wallpaper.wallpaperComponent);
- clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
+ clearWallpaperLocked(false, which, wallpaper.userId, null);
}
}
if (wallpaper.nextWallpaperComponent != null
@@ -1676,7 +1660,8 @@
if (DEBUG) {
Slog.i(TAG, "Unable to regenerate crop; resetting");
}
- clearWallpaperLocked(false, FLAG_SYSTEM, UserHandle.USER_SYSTEM, null);
+ int which = isLockscreenLiveWallpaperEnabled() ? wallpaper.mWhich : FLAG_SYSTEM;
+ clearWallpaperLocked(false, which, UserHandle.USER_SYSTEM, null);
}
} else {
if (DEBUG) {
@@ -1956,12 +1941,7 @@
WallpaperData wallpaper, IRemoteCallback reply, ServiceInfo serviceInfo) {
if (serviceInfo == null) {
- if (wallpaper.mWhich == (FLAG_LOCK | FLAG_SYSTEM)) {
- clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
- clearWallpaperLocked(false, FLAG_LOCK, wallpaper.userId, reply);
- } else {
- clearWallpaperLocked(false, wallpaper.mWhich, wallpaper.userId, reply);
- }
+ clearWallpaperLocked(false, wallpaper.mWhich, wallpaper.userId, reply);
return;
}
Slog.w(TAG, "Wallpaper isn't direct boot aware; using fallback until unlocked");
@@ -1982,7 +1962,7 @@
@Override
public void clearWallpaper(String callingPackage, int which, int userId) {
- if (DEBUG) Slog.v(TAG, "clearWallpaper");
+ if (DEBUG) Slog.v(TAG, "clearWallpaper: " + which);
checkPermission(android.Manifest.permission.SET_WALLPAPER);
if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
return;
@@ -1993,7 +1973,8 @@
WallpaperData data = null;
synchronized (mLock) {
if (mIsLockscreenLiveWallpaperEnabled) {
- clearWallpaperLocked(callingPackage, false, which, userId);
+ boolean fromForeground = isFromForegroundApp(callingPackage);
+ clearWallpaperLocked(false, which, userId, fromForeground, null);
} else {
clearWallpaperLocked(false, which, userId, null);
}
@@ -2013,8 +1994,8 @@
}
}
- private void clearWallpaperLocked(String callingPackage, boolean defaultFailed,
- int which, int userId) {
+ private void clearWallpaperLocked(boolean defaultFailed,
+ int which, int userId, boolean fromForeground, IRemoteCallback reply) {
// Might need to bring it in the first time to establish our rewrite
if (!mWallpaperMap.contains(userId)) {
@@ -2053,8 +2034,10 @@
finalWhich = which;
}
- boolean success = withCleanCallingIdentity(() -> setWallpaperComponent(
- component, callingPackage, finalWhich, userId));
+ // except for the lock case (for which we keep the system wallpaper as-is), force rebind
+ boolean force = which != FLAG_LOCK;
+ boolean success = withCleanCallingIdentity(() -> setWallpaperComponentInternal(
+ component, finalWhich, userId, force, fromForeground, reply));
if (success) return;
} catch (IllegalArgumentException e1) {
e = e1;
@@ -2066,11 +2049,24 @@
// wallpaper.
Slog.e(TAG, "Default wallpaper component not found!", e);
withCleanCallingIdentity(() -> clearWallpaperComponentLocked(wallpaper));
+ if (reply != null) {
+ try {
+ reply.sendResult(null);
+ } catch (RemoteException e1) {
+ Slog.w(TAG, "Failed to notify callback after wallpaper clear", e1);
+ }
+ }
}
- // TODO(b/266818039) remove this version of the method
+ // TODO(b/266818039) remove
private void clearWallpaperLocked(boolean defaultFailed, int which, int userId,
IRemoteCallback reply) {
+
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ clearWallpaperLocked(defaultFailed, which, userId, false, reply);
+ return;
+ }
+
if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to clear");
}
@@ -2787,6 +2783,18 @@
: new WallpaperData[0];
}
+ // TODO(b/266818039) remove
+ private WallpaperData[] getWallpapers() {
+ WallpaperData systemWallpaper = mWallpaperMap.get(mCurrentUserId);
+ WallpaperData lockWallpaper = mLockWallpaperMap.get(mCurrentUserId);
+ boolean systemValid = systemWallpaper != null;
+ boolean lockValid = lockWallpaper != null && !isLockscreenLiveWallpaperEnabled();
+ return systemValid && lockValid ? new WallpaperData[]{systemWallpaper, lockWallpaper}
+ : systemValid ? new WallpaperData[]{systemWallpaper}
+ : lockValid ? new WallpaperData[]{lockWallpaper}
+ : new WallpaperData[0];
+ }
+
private IWallpaperEngine getEngine(int which, int userId, int displayId) {
WallpaperData wallpaperData = findWallpaperAtDisplay(userId, displayId);
if (wallpaperData == null) return null;
@@ -3244,15 +3252,16 @@
boolean setWallpaperComponent(ComponentName name, String callingPackage,
@SetWallpaperFlags int which, int userId) {
if (mIsLockscreenLiveWallpaperEnabled) {
- return setWallpaperComponentInternal(name, callingPackage, which, userId);
+ boolean fromForeground = isFromForegroundApp(callingPackage);
+ return setWallpaperComponentInternal(name, which, userId, false, fromForeground, null);
} else {
setWallpaperComponentInternalLegacy(name, callingPackage, which, userId);
return true;
}
}
- private boolean setWallpaperComponentInternal(ComponentName name, String callingPackage,
- @SetWallpaperFlags int which, int userIdIn) {
+ private boolean setWallpaperComponentInternal(ComponentName name, @SetWallpaperFlags int which,
+ int userIdIn, boolean force, boolean fromForeground, IRemoteCallback reply) {
if (DEBUG) {
Slog.v(TAG, "Setting new live wallpaper: which=" + which + ", component: " + name);
}
@@ -3266,7 +3275,7 @@
final WallpaperData newWallpaper;
synchronized (mLock) {
- Slog.v(TAG, "setWallpaperComponent name=" + name);
+ Slog.v(TAG, "setWallpaperComponent name=" + name + ", which = " + which);
final WallpaperData originalSystemWallpaper = mWallpaperMap.get(userId);
if (originalSystemWallpaper == null) {
throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
@@ -3289,30 +3298,21 @@
newWallpaper.imageWallpaperPending = false;
newWallpaper.mWhich = which;
newWallpaper.mSystemWasBoth = systemIsBoth;
- newWallpaper.fromForegroundApp = isFromForegroundApp(callingPackage);
+ newWallpaper.fromForegroundApp = fromForeground;
final WallpaperDestinationChangeHandler
liveSync = new WallpaperDestinationChangeHandler(
newWallpaper);
boolean same = changingToSame(name, newWallpaper);
- IRemoteCallback.Stub callback = new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) throws RemoteException {
- if (DEBUG) {
- Slog.d(TAG, "publish system wallpaper changed!");
- }
- liveSync.complete();
- }
- };
/*
* If we have a shared system+lock wallpaper, and we reapply the same wallpaper
* to system only, force rebind: the current wallpaper will be migrated to lock
* and a new engine with the same wallpaper will be applied to system.
*/
- boolean forceRebind = same && systemIsBoth && which == FLAG_SYSTEM;
+ boolean forceRebind = force || (same && systemIsBoth && which == FLAG_SYSTEM);
bindSuccess = bindWallpaperComponentLocked(name, /* force */
- forceRebind, /* fromUser */ true, newWallpaper, callback);
+ forceRebind, /* fromUser */ true, newWallpaper, reply);
if (bindSuccess) {
if (!same) {
newWallpaper.primaryColors = null;
@@ -3356,6 +3356,7 @@
}
mLockWallpaperMap.remove(newWallpaper.userId);
}
+ if (liveSync != null) liveSync.complete();
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -3381,7 +3382,7 @@
WallpaperData wallpaper;
synchronized (mLock) {
- Slog.v(TAG, "setWallpaperComponent name=" + name + ", which=" + which);
+ Slog.v(TAG, "setWallpaperComponentLegacy name=" + name + ", which=" + which);
wallpaper = mWallpaperMap.get(userId);
if (wallpaper == null) {
throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
@@ -3474,6 +3475,11 @@
}
// Has the component changed?
if (!force && changingToSame(componentName, wallpaper)) {
+ try {
+ if (reply != null) reply.sendResult(null);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to send callback", e);
+ }
return true;
}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index aafff2c..a70f339 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1162,9 +1162,7 @@
fullscreenRequest, r);
reportMultiwindowFullscreenRequestValidatingResult(callback, validateResult);
if (validateResult != RESULT_APPROVED) {
- if (queued) {
- transition.abort();
- }
+ transition.abort();
return;
}
transition.collect(topFocusedRootTask);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index ff2c719..d7489f2 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.BIND_VOICE_INTERACTION;
import static android.Manifest.permission.CHANGE_CONFIGURATION;
+import static android.Manifest.permission.CONTROL_KEYGUARD;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
import static android.Manifest.permission.DETECT_SCREEN_CAPTURE;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
@@ -3539,6 +3540,7 @@
@Override
public void keyguardGoingAway(int flags) {
+ mAmInternal.enforceCallingPermission(CONTROL_KEYGUARD, "unlock keyguard");
enforceNotIsolatedCaller("keyguardGoingAway");
final long token = Binder.clearCallingIdentity();
try {
@@ -3643,6 +3645,9 @@
synchronized (mGlobalLock) {
if (r.getParent() == null) {
Slog.e(TAG, "Skip enterPictureInPictureMode, destroyed " + r);
+ if (transition != null) {
+ transition.abort();
+ }
return;
}
EventLogTags.writeWmEnterPip(r.mUserId, System.identityHashCode(r),
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index 0a2bbd4..4b463c7 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -459,7 +459,7 @@
// insets should keep original position before the start transaction is applied.
return mTransitionOp != OP_LEGACY && (mTransitionOp == OP_APP_SWITCH
|| TransitionController.SYNC_METHOD == BLASTSyncEngine.METHOD_BLAST)
- && !mIsStartTransactionCommitted && isTargetToken(w.mToken);
+ && !mIsStartTransactionCommitted && canBeAsync(w.mToken) && isTargetToken(w.mToken);
}
/**
diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java
index 5aa7c97..b499dad 100644
--- a/services/core/java/com/android/server/wm/ContentRecorder.java
+++ b/services/core/java/com/android/server/wm/ContentRecorder.java
@@ -35,6 +35,7 @@
import android.os.ServiceManager;
import android.provider.DeviceConfig;
import android.view.ContentRecordingSession;
+import android.view.ContentRecordingSession.RecordContent;
import android.view.Display;
import android.view.SurfaceControl;
@@ -82,8 +83,14 @@
@Nullable private Rect mLastRecordedBounds = null;
/**
+ * The last size of the surface mirrored out to.
+ */
+ @Nullable private Point mLastConsumingSurfaceSize = new Point(0, 0);
+
+ /**
* The last configuration orientation.
*/
+ @Configuration.Orientation
private int mLastOrientation = ORIENTATION_UNDEFINED;
ContentRecorder(@NonNull DisplayContent displayContent) {
@@ -139,45 +146,64 @@
*/
void onConfigurationChanged(@Configuration.Orientation int lastOrientation) {
// Update surface for MediaProjection, if this DisplayContent is being used for recording.
- if (isCurrentlyRecording() && mLastRecordedBounds != null) {
- // Recording has already begun, but update recording since the display is now on.
- if (mRecordedWindowContainer == null) {
+ if (!isCurrentlyRecording() || mLastRecordedBounds == null) {
+ return;
+ }
+
+ // Recording has already begun, but update recording since the display is now on.
+ if (mRecordedWindowContainer == null) {
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Content Recording: Unexpectedly null window container; unable to update "
+ + "recording for display %d",
+ mDisplayContent.getDisplayId());
+ return;
+ }
+
+ // TODO(b/297514518) Do not start capture if the app is in PIP, the bounds are
+ // inaccurate.
+ if (mContentRecordingSession.getContentToRecord() == RECORD_CONTENT_TASK) {
+ final Task capturedTask = mRecordedWindowContainer.asTask();
+ if (capturedTask.inPinnedWindowingMode()) {
ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
- "Content Recording: Unexpectedly null window container; unable to update "
- + "recording for display %d",
+ "Content Recording: Display %d was already recording, but "
+ + "pause capture since the task is in PIP",
mDisplayContent.getDisplayId());
+ pauseRecording();
return;
}
+ }
- ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
- "Content Recording: Display %d was already recording, so apply "
- + "transformations if necessary",
- mDisplayContent.getDisplayId());
- // Retrieve the size of the region to record, and continue with the update
- // if the bounds or orientation has changed.
- final Rect recordedContentBounds = mRecordedWindowContainer.getBounds();
- int recordedContentOrientation = mRecordedWindowContainer.getOrientation();
- if (!mLastRecordedBounds.equals(recordedContentBounds)
- || lastOrientation != recordedContentOrientation) {
- Point surfaceSize = fetchSurfaceSizeIfPresent();
- if (surfaceSize != null) {
- ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
- "Content Recording: Going ahead with updating recording for display "
- + "%d to new bounds %s and/or orientation %d.",
- mDisplayContent.getDisplayId(), recordedContentBounds,
- recordedContentOrientation);
- updateMirroredSurface(mRecordedWindowContainer.getSyncTransaction(),
- recordedContentBounds, surfaceSize);
- } else {
- // If the surface removed, do nothing. We will handle this via onDisplayChanged
- // (the display will be off if the surface is removed).
- ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
- "Content Recording: Unable to update recording for display %d to new "
- + "bounds %s and/or orientation %d, since the surface is not "
- + "available.",
- mDisplayContent.getDisplayId(), recordedContentBounds,
- recordedContentOrientation);
- }
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Content Recording: Display %d was already recording, so apply "
+ + "transformations if necessary",
+ mDisplayContent.getDisplayId());
+ // Retrieve the size of the region to record, and continue with the update
+ // if the bounds or orientation has changed.
+ final Rect recordedContentBounds = mRecordedWindowContainer.getBounds();
+ @Configuration.Orientation int recordedContentOrientation =
+ mRecordedWindowContainer.getConfiguration().orientation;
+ final Point surfaceSize = fetchSurfaceSizeIfPresent();
+ if (!mLastRecordedBounds.equals(recordedContentBounds)
+ || lastOrientation != recordedContentOrientation
+ || !mLastConsumingSurfaceSize.equals(surfaceSize)) {
+ if (surfaceSize != null) {
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Content Recording: Going ahead with updating recording for display "
+ + "%d to new bounds %s and/or orientation %d and/or surface "
+ + "size %s",
+ mDisplayContent.getDisplayId(), recordedContentBounds,
+ recordedContentOrientation, surfaceSize);
+ updateMirroredSurface(mRecordedWindowContainer.getSyncTransaction(),
+ recordedContentBounds, surfaceSize);
+ } else {
+ // If the surface removed, do nothing. We will handle this via onDisplayChanged
+ // (the display will be off if the surface is removed).
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Content Recording: Unable to update recording for display %d to new "
+ + "bounds %s and/or orientation %d and/or surface size %s, "
+ + "since the surface is not available.",
+ mDisplayContent.getDisplayId(), recordedContentBounds,
+ recordedContentOrientation, surfaceSize);
}
}
}
@@ -289,6 +315,17 @@
return;
}
+ // TODO(b/297514518) Do not start capture if the app is in PIP, the bounds are inaccurate.
+ if (mContentRecordingSession.getContentToRecord() == RECORD_CONTENT_TASK) {
+ if (mRecordedWindowContainer.asTask().inPinnedWindowingMode()) {
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Content Recording: Display %d should start recording, but "
+ + "don't yet since the task is in PIP",
+ mDisplayContent.getDisplayId());
+ return;
+ }
+ }
+
final Point surfaceSize = fetchSurfaceSizeIfPresent();
if (surfaceSize == null) {
ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
@@ -302,9 +339,6 @@
+ "state %d",
mDisplayContent.getDisplayId(), mDisplayContent.getDisplayInfo().state);
- // TODO(b/274790702): Do not start recording if waiting for consent - for now,
- // go ahead.
-
// Create a mirrored hierarchy for the SurfaceControl of the DisplayArea to capture.
mRecordedSurface = SurfaceControl.mirrorSurface(
mRecordedWindowContainer.getSurfaceControl());
@@ -356,7 +390,7 @@
*/
@Nullable
private WindowContainer retrieveRecordedWindowContainer() {
- final int contentToRecord = mContentRecordingSession.getContentToRecord();
+ @RecordContent final int contentToRecord = mContentRecordingSession.getContentToRecord();
final IBinder tokenToRecord = mContentRecordingSession.getTokenToRecord();
switch (contentToRecord) {
case RECORD_CONTENT_DISPLAY:
@@ -472,6 +506,15 @@
shiftedY = (surfaceSize.y - scaledHeight) / 2;
}
+ ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+ "Content Recording: Apply transformations of shift %d x %d, scale %f, crop (aka "
+ + "recorded content size) %d x %d for display %d; display has size %d x "
+ + "%d; surface has size %d x %d",
+ shiftedX, shiftedY, scale, recordedContentBounds.width(),
+ recordedContentBounds.height(), mDisplayContent.getDisplayId(),
+ mDisplayContent.getConfiguration().screenWidthDp,
+ mDisplayContent.getConfiguration().screenHeightDp, surfaceSize.x, surfaceSize.y);
+
transaction
// Crop the area to capture to exclude the 'extra' wallpaper that is used
// for parallax (b/189930234).
@@ -484,6 +527,8 @@
// the content will no longer be centered in the output surface.
.setPosition(mRecordedSurface, shiftedX /* x */, shiftedY /* y */);
mLastRecordedBounds = new Rect(recordedContentBounds);
+ mLastConsumingSurfaceSize.x = surfaceSize.x;
+ mLastConsumingSurfaceSize.y = surfaceSize.y;
// Request to notify the client about the resize.
mMediaProjectionManager.notifyActiveProjectionCapturedContentResized(
mLastRecordedBounds.width(), mLastRecordedBounds.height());
@@ -492,6 +537,7 @@
/**
* Returns a non-null {@link Point} if the surface is present, or null otherwise
*/
+ @Nullable
private Point fetchSurfaceSizeIfPresent() {
// Retrieve the default size of the surface the app provided to
// MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface,
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4a40395..47e90ce 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -6061,8 +6061,9 @@
mOffTokenAcquirer.release(mDisplayId);
}
ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
- "Content Recording: Display %d state is now (%d), so update recording?",
- mDisplayId, displayState);
+ "Content Recording: Display %d state was (%d), is now (%d), so update "
+ + "recording?",
+ mDisplayId, lastDisplayState, displayState);
if (lastDisplayState != displayState) {
// If state is on due to surface being added, then start recording.
// If state is off due to surface being removed, then stop recording.
@@ -6525,14 +6526,6 @@
}
/**
- * @return whether AOD is showing on this display
- */
- boolean isAodShowing() {
- return mRootWindowContainer.mTaskSupervisor
- .getKeyguardController().isAodShowing(mDisplayId);
- }
-
- /**
* @return whether this display maintains its own focus and touch mode.
*/
boolean hasOwnFocus() {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 354b0db..4a740f4 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR;
import static android.view.Display.TYPE_INTERNAL;
import static android.view.InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE;
import static android.view.InsetsFrameProvider.SOURCE_CONTAINER_BOUNDS;
@@ -268,6 +269,8 @@
private boolean mIsFreeformWindowOverlappingWithNavBar;
+ private @InsetsType int mForciblyShownTypes;
+
private boolean mIsImmersiveMode;
// The windows we were told about in focusChanged.
@@ -1201,8 +1204,8 @@
throw new IllegalArgumentException("IME insets must be provided by a window.");
}
- if (mNavigationBar != null && navigationBarPosition(displayFrames.mRotation)
- == NAV_BAR_BOTTOM) {
+ if (!ENABLE_HIDE_IME_CAPTION_BAR && mNavigationBar != null
+ && navigationBarPosition(displayFrames.mRotation) == NAV_BAR_BOTTOM) {
// In gesture navigation, nav bar frame is larger than frame to calculate insets.
// IME should not provide frame which is smaller than the nav bar frame. Otherwise,
// nav bar might be overlapped with the content of the client when IME is shown.
@@ -1401,6 +1404,7 @@
mAllowLockscreenWhenOn = false;
mShowingDream = false;
mIsFreeformWindowOverlappingWithNavBar = false;
+ mForciblyShownTypes = 0;
}
/**
@@ -1458,6 +1462,10 @@
}
}
+ if (win.mSession.mCanForceShowingInsets) {
+ mForciblyShownTypes |= win.mAttrs.forciblyShownTypes;
+ }
+
if (!affectsSystemUi) {
return;
}
@@ -1639,6 +1647,10 @@
mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn);
}
+ boolean areTypesForciblyShownTransiently(@InsetsType int types) {
+ return (mForciblyShownTypes & types) == types;
+ }
+
/**
* Applies the keyguard policy to a specific window.
*
@@ -1665,18 +1677,6 @@
}
private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
- // If AOD is showing, the IME should be hidden. However, sometimes the AOD is considered
- // hidden because it's in the process of hiding, but it's still being shown on screen.
- // In that case, we want to continue hiding the IME until the windows have completed
- // drawing. This way, we know that the IME can be safely shown since the other windows are
- // now shown.
- final boolean hideIme = win.mIsImWindow
- && (mDisplayContent.isAodShowing()
- || (mDisplayContent.isDefaultDisplay && !mWindowManagerDrawComplete));
- if (hideIme) {
- return true;
- }
-
if (!mDisplayContent.isDefaultDisplay || !isKeyguardShowing()) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 835c92d..d0d7f49 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -23,8 +23,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.InsetsSource.ID_IME;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import android.annotation.NonNull;
@@ -77,6 +75,18 @@
/** Used to show system bars permanently. This will affect the layout. */
private final InsetsControlTarget mPermanentControlTarget;
+ /**
+ * Used to override the visibility of {@link Type#statusBars()} when dispatching insets to
+ * clients.
+ */
+ private InsetsControlTarget mFakeStatusControlTarget;
+
+ /**
+ * Used to override the visibility of {@link Type#navigationBars()} when dispatching insets to
+ * clients.
+ */
+ private InsetsControlTarget mFakeNavControlTarget;
+
private WindowState mFocusedWin;
private final BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
private final BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
@@ -103,25 +113,25 @@
abortTransient();
}
mFocusedWin = focusedWin;
- final InsetsControlTarget statusControlTarget =
- getStatusControlTarget(focusedWin, false /* fake */);
- final InsetsControlTarget navControlTarget =
- getNavControlTarget(focusedWin, false /* fake */);
final WindowState notificationShade = mPolicy.getNotificationShade();
final WindowState topApp = mPolicy.getTopFullscreenOpaqueWindow();
+ final InsetsControlTarget statusControlTarget =
+ getStatusControlTarget(focusedWin, false /* fake */);
+ mFakeStatusControlTarget = statusControlTarget == mTransientControlTarget
+ ? getStatusControlTarget(focusedWin, true /* fake */)
+ : statusControlTarget == notificationShade
+ ? getStatusControlTarget(topApp, true /* fake */)
+ : null;
+ final InsetsControlTarget navControlTarget =
+ getNavControlTarget(focusedWin, false /* fake */);
+ mFakeNavControlTarget = navControlTarget == mTransientControlTarget
+ ? getNavControlTarget(focusedWin, true /* fake */)
+ : navControlTarget == notificationShade
+ ? getNavControlTarget(topApp, true /* fake */)
+ : null;
mStateController.onBarControlTargetChanged(
- statusControlTarget,
- statusControlTarget == mTransientControlTarget
- ? getStatusControlTarget(focusedWin, true /* fake */)
- : statusControlTarget == notificationShade
- ? getStatusControlTarget(topApp, true /* fake */)
- : null,
- navControlTarget,
- navControlTarget == mTransientControlTarget
- ? getNavControlTarget(focusedWin, true /* fake */)
- : navControlTarget == notificationShade
- ? getNavControlTarget(topApp, true /* fake */)
- : null);
+ statusControlTarget, mFakeStatusControlTarget,
+ navControlTarget, mFakeNavControlTarget);
mStatusBar.updateVisibility(statusControlTarget, Type.statusBars());
mNavBar.updateVisibility(navControlTarget, Type.navigationBars());
}
@@ -206,7 +216,7 @@
boolean includesTransient) {
InsetsState state;
if (!includesTransient) {
- state = adjustVisibilityForTransientTypes(originalState);
+ state = adjustVisibilityForFakeControllingSources(originalState);
} else {
state = originalState;
}
@@ -321,24 +331,40 @@
return state;
}
- private InsetsState adjustVisibilityForTransientTypes(InsetsState originalState) {
+ private InsetsState adjustVisibilityForFakeControllingSources(InsetsState originalState) {
+ if (mFakeStatusControlTarget == null && mFakeNavControlTarget == null) {
+ return originalState;
+ }
InsetsState state = originalState;
for (int i = state.sourceSize() - 1; i >= 0; i--) {
final InsetsSource source = state.sourceAt(i);
- if (isTransient(source.getType()) && source.isVisible()) {
- if (state == originalState) {
- // The source will be modified, create a non-deep copy to store the new one.
- state = new InsetsState(originalState);
- }
- // Replace the source with a copy in invisible state.
- final InsetsSource outSource = new InsetsSource(source);
- outSource.setVisible(false);
- state.addSource(outSource);
- }
+ state = adjustVisibilityForFakeControllingSource(state, Type.statusBars(), source,
+ mFakeStatusControlTarget);
+ state = adjustVisibilityForFakeControllingSource(state, Type.navigationBars(), source,
+ mFakeNavControlTarget);
}
return state;
}
+ private static InsetsState adjustVisibilityForFakeControllingSource(InsetsState originalState,
+ @InsetsType int type, InsetsSource source, InsetsControlTarget target) {
+ if (source.getType() != type || target == null) {
+ return originalState;
+ }
+ final boolean isRequestedVisible = target.isRequestedVisible(type);
+ if (source.isVisible() == isRequestedVisible) {
+ return originalState;
+ }
+ // The source will be modified, create a non-deep copy to store the new one.
+ final InsetsState state = new InsetsState(originalState);
+
+ // Replace the source with a copy with the overridden visibility.
+ final InsetsSource outSource = new InsetsSource(source);
+ outSource.setVisible(isRequestedVisible);
+ state.addSource(outSource);
+ return state;
+ }
+
private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
boolean copyState) {
if (w.mIsImWindow) {
@@ -473,7 +499,7 @@
// we will dispatch the real visibility of status bar to the client.
return mPermanentControlTarget;
}
- if (forceShowsStatusBarTransiently() && !fake) {
+ if (mPolicy.areTypesForciblyShownTransiently(Type.statusBars()) && !fake) {
// Status bar is forcibly shown transiently, and its new visibility won't be
// dispatched to the client so that we can keep the layout stable. We will dispatch the
// fake control to the client, so that it can re-show the bar during this scenario.
@@ -505,7 +531,7 @@
if (imeWin != null && imeWin.isVisible() && !mHideNavBarForKeyboard) {
// Force showing navigation bar while IME is visible and if navigation bar is not
// configured to be hidden by the IME.
- return null;
+ return mPermanentControlTarget;
}
if (!fake && isTransient(Type.navigationBars())) {
return mTransientControlTarget;
@@ -533,7 +559,7 @@
// bar, and we will dispatch the real visibility of navigation bar to the client.
return mPermanentControlTarget;
}
- if (forceShowsNavigationBarTransiently() && !fake) {
+ if (mPolicy.areTypesForciblyShownTransiently(Type.navigationBars()) && !fake) {
// Navigation bar is forcibly shown transiently, and its new visibility won't be
// dispatched to the client so that we can keep the layout stable. We will dispatch the
// fake control to the client, so that it can re-show the bar during this scenario.
@@ -603,17 +629,6 @@
&& focusedWin.getAttrs().type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
}
- private boolean forceShowsStatusBarTransiently() {
- final WindowState win = mPolicy.getStatusBar();
- return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0;
- }
-
- private boolean forceShowsNavigationBarTransiently() {
- final WindowState win = mPolicy.getNotificationShade();
- return win != null
- && (win.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
- }
-
private void dispatchTransientSystemBarsVisibilityChanged(
@Nullable WindowState focusedWindow,
boolean areVisible,
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 97b3e32..45cf10b 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -80,10 +80,10 @@
// Whether per-app user aspect ratio override settings is enabled
private static final String KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS =
- "enable_app_compat_user_aspect_ratio_settings";
+ "enable_app_compat_aspect_ratio_user_settings";
// TODO(b/288142656): Enable user aspect ratio settings by default.
- private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS = false;
+ private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS = true;
// Whether per-app fullscreen user aspect ratio override option is enabled
private static final String KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN =
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 01786be..d2d6552 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -661,6 +661,10 @@
@ScreenOrientation
int overrideOrientationIfNeeded(@ScreenOrientation int candidate) {
if (shouldApplyUserFullscreenOverride()) {
+ Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
+ + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_USER)
+ + " by user aspect ratio settings.");
return SCREEN_ORIENTATION_USER;
}
@@ -668,6 +672,14 @@
// orientation.
candidate = mActivityRecord.mWmService.mapOrientationRequest(candidate);
+ if (shouldApplyUserMinAspectRatioOverride() && !isFixedOrientation(candidate)) {
+ Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
+ + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_PORTRAIT)
+ + " by user aspect ratio settings.");
+ return SCREEN_ORIENTATION_PORTRAIT;
+ }
+
if (FALSE.equals(mBooleanPropertyAllowOrientationOverride)) {
return candidate;
}
@@ -1126,11 +1138,25 @@
return computeAspectRatio(bounds);
}
+ /**
+ * Whether we should enable users to resize the current app.
+ */
+ boolean shouldEnableUserAspectRatioSettings() {
+ // We use mBooleanPropertyAllowUserAspectRatioOverride to allow apps to opt-out which has
+ // effect only if explicitly false. If mBooleanPropertyAllowUserAspectRatioOverride is null,
+ // the current app doesn't opt-out so the first part of the predicate is true.
+ return !FALSE.equals(mBooleanPropertyAllowUserAspectRatioOverride)
+ && mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled()
+ && mActivityRecord.mDisplayContent != null
+ && mActivityRecord.mDisplayContent.getIgnoreOrientationRequest();
+ }
+
+ /**
+ * Whether we should apply the user aspect ratio override to the min aspect ratio for the
+ * current app.
+ */
boolean shouldApplyUserMinAspectRatioOverride() {
- if (FALSE.equals(mBooleanPropertyAllowUserAspectRatioOverride)
- || !mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled()
- || mActivityRecord.mDisplayContent == null
- || !mActivityRecord.mDisplayContent.getIgnoreOrientationRequest()) {
+ if (!shouldEnableUserAspectRatioSettings()) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index c914fa1..c863533 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -148,7 +148,8 @@
.setPendingIntentBackgroundActivityStartMode(
options.getPendingIntentBackgroundActivityStartMode())
.setPendingIntentCreatorBackgroundActivityStartMode(
- options.getPendingIntentCreatorBackgroundActivityStartMode());
+ options.getPendingIntentCreatorBackgroundActivityStartMode())
+ .setRemoteTransition(options.getRemoteTransition());
}
/**
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index b49c5fb..2bc7010 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -22,6 +22,7 @@
import static android.Manifest.permission.SET_UNRESTRICTED_GESTURE_EXCLUSION;
import static android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.Manifest.permission.STATUS_BAR_SERVICE;
import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY;
@@ -107,6 +108,7 @@
private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>();
private final DragDropController mDragDropController;
final boolean mCanAddInternalSystemWindow;
+ boolean mCanForceShowingInsets;
private final boolean mCanStartTasksFromRecents;
final boolean mCanCreateSystemApplicationOverlay;
@@ -129,6 +131,9 @@
mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
+ mCanForceShowingInsets = service.mAtmService.isCallerRecents(mUid)
+ || service.mContext.checkCallingOrSelfPermission(STATUS_BAR_SERVICE)
+ == PERMISSION_GRANTED;
mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED
|| service.mContext.checkCallingOrSelfPermission(HIDE_OVERLAY_WINDOWS)
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9f2aff2..60b6a88 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3476,9 +3476,9 @@
}
}
// User Aspect Ratio Settings is enabled if the app is not in SCM
- info.topActivityEligibleForUserAspectRatioButton =
- mWmService.mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled()
- && top != null && !info.topActivityInSizeCompat;
+ info.topActivityEligibleForUserAspectRatioButton = top != null
+ && !info.topActivityInSizeCompat
+ && top.mLetterboxUiController.shouldEnableUserAspectRatioSettings();
info.topActivityBoundsLetterboxed = top != null && top.areBoundsLetterboxed();
}
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index a27cc3a..ea722b6 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -184,14 +184,31 @@
}
void dispose() {
+ boolean wasVisible = false;
for (int i = mOrganizedTaskFragments.size() - 1; i >= 0; i--) {
+ final TaskFragment taskFragment = mOrganizedTaskFragments.get(i);
+ if (taskFragment.isVisibleRequested()) {
+ wasVisible = true;
+ }
// Cleanup the TaskFragmentOrganizer from all TaskFragments it organized before
// removing the windows to prevent it from adding any additional TaskFragment
// pending event.
- final TaskFragment taskFragment = mOrganizedTaskFragments.get(i);
taskFragment.onTaskFragmentOrganizerRemoved();
}
+ final TransitionController transitionController = mAtmService.getTransitionController();
+ if (wasVisible && transitionController.isShellTransitionsEnabled()
+ && !transitionController.isCollecting()) {
+ final Task task = mOrganizedTaskFragments.get(0).getTask();
+ final boolean containsNonEmbeddedActivity =
+ task != null && task.getActivity(a -> !a.isEmbedded()) != null;
+ transitionController.requestStartTransition(
+ transitionController.createTransition(WindowManager.TRANSIT_CLOSE),
+ // The task will be removed if all its activities are embedded, then the
+ // task is the trigger.
+ containsNonEmbeddedActivity ? null : task,
+ null /* remoteTransition */, null /* displayChange */);
+ }
// Defer to avoid unnecessary layout when there are multiple TaskFragments removal.
mAtmService.deferWindowLayout();
try {
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index c49a1d0..f8736e7 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1486,6 +1486,11 @@
return;
}
+ if (mState != STATE_STARTED) {
+ Slog.e(TAG, "Playing a Transition which hasn't started! #" + mSyncId + " This will "
+ + "likely cause an exception in Shell");
+ }
+
mState = STATE_PLAYING;
mStartTransaction = transaction;
mFinishTransaction = mController.mAtm.mWindowManager.mTransactionFactory.get();
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 7545830..0342996 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -1147,7 +1147,7 @@
Transition.asyncTraceBegin("animating", 0x41bfaf1 /* hashcode of TAG */);
} else if (!animatingState && mAnimatingState) {
t.setEarlyWakeupEnd();
- mAtm.mWindowManager.requestTraversal();
+ mAtm.mWindowManager.scheduleAnimationLocked();
mSnapshotController.setPause(false);
mAnimatingState = false;
Transition.asyncTraceEnd(0x41bfaf1 /* hashcode of TAG */);
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 805e7ff..9f1bccb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -954,4 +954,11 @@
/** Returns the SurfaceControl accessibility services should use for accessibility overlays. */
public abstract SurfaceControl getA11yOverlayLayer(int displayId);
+
+ /**
+ * Device has a software navigation bar (separate from the status bar) on specific display.
+ *
+ * @param displayId the id of display to check if there is a software navigation bar.
+ */
+ public abstract boolean hasNavigationBar(int displayId);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b20be55..e6a341f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8380,6 +8380,11 @@
}
@Override
+ public boolean hasNavigationBar(int displayId) {
+ return WindowManagerService.this.hasNavigationBar(displayId);
+ }
+
+ @Override
public void setInputMethodTargetChangeListener(@NonNull ImeTargetChangeListener listener) {
synchronized (mGlobalLock) {
mImeTargetChangeListener = listener;
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index bfe0553..74a0bafd3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -1279,6 +1279,7 @@
mLetterboxConfiguration.resetLetterboxBackgroundWallpaperBlurRadiusPx();
mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha();
mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
+ mLetterboxConfiguration.resetLetterboxVerticalPositionMultiplier();
mLetterboxConfiguration.resetIsHorizontalReachabilityEnabled();
mLetterboxConfiguration.resetIsVerticalReachabilityEnabled();
mLetterboxConfiguration.resetEnabledAutomaticReachabilityInBookMode();
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index d5217c8..77db960 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -41,6 +41,7 @@
"com_android_server_companion_virtual_InputController.cpp",
"com_android_server_devicepolicy_CryptoTestHelper.cpp",
"com_android_server_display_DisplayControl.cpp",
+ "com_android_server_display_SmallAreaDetectionController.cpp",
"com_android_server_connectivity_Vpn.cpp",
"com_android_server_gpu_GpuService.cpp",
"com_android_server_HardwarePropertiesManagerService.cpp",
diff --git a/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp b/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp
new file mode 100644
index 0000000..b256f16
--- /dev/null
+++ b/services/core/jni/com_android_server_display_SmallAreaDetectionController.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SmallAreaDetectionController"
+
+#include <gui/SurfaceComposerClient.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+
+#include "jni.h"
+#include "utils/Log.h"
+
+namespace android {
+static void nativeUpdateSmallAreaDetection(JNIEnv* env, jclass clazz, jintArray juids,
+ jfloatArray jthresholds) {
+ if (juids == nullptr || jthresholds == nullptr) return;
+
+ ScopedIntArrayRO uids(env, juids);
+ ScopedFloatArrayRO thresholds(env, jthresholds);
+
+ if (uids.size() != thresholds.size()) {
+ ALOGE("uids size exceeds thresholds size!");
+ return;
+ }
+
+ std::vector<int32_t> uidVector;
+ std::vector<float> thresholdVector;
+ size_t size = uids.size();
+ uidVector.reserve(size);
+ thresholdVector.reserve(size);
+ for (int i = 0; i < size; i++) {
+ uidVector.push_back(static_cast<int32_t>(uids[i]));
+ thresholdVector.push_back(static_cast<float>(thresholds[i]));
+ }
+ SurfaceComposerClient::updateSmallAreaDetection(uidVector, thresholdVector);
+}
+
+static void nativeSetSmallAreaDetectionThreshold(JNIEnv* env, jclass clazz, jint uid,
+ jfloat threshold) {
+ SurfaceComposerClient::setSmallAreaDetectionThreshold(uid, threshold);
+}
+
+static const JNINativeMethod gMethods[] = {
+ {"nativeUpdateSmallAreaDetection", "([I[F)V", (void*)nativeUpdateSmallAreaDetection},
+ {"nativeSetSmallAreaDetectionThreshold", "(IF)V",
+ (void*)nativeSetSmallAreaDetectionThreshold},
+};
+
+int register_android_server_display_smallAreaDetectionController(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/server/display/SmallAreaDetectionController",
+ gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 290ad8d..63c3b4d 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -66,6 +66,7 @@
int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env);
int register_com_android_server_display_DisplayControl(JNIEnv* env);
int register_com_android_server_SystemClockTime(JNIEnv* env);
+int register_android_server_display_smallAreaDetectionController(JNIEnv* env);
};
using namespace android;
@@ -124,5 +125,6 @@
register_com_android_server_wm_TaskFpsCallbackController(env);
register_com_android_server_display_DisplayControl(env);
register_com_android_server_SystemClockTime(env);
+ register_android_server_display_smallAreaDetectionController(env);
return JNI_VERSION_1_4;
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index d8c684f..4979274 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -96,6 +96,9 @@
private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_MANAGER =
"enable_credential_manager";
+ private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
+ "enable_credential_description_api";
+
private final Context mContext;
/** Cache of system service list per user id. */
@@ -321,7 +324,14 @@
}
public static boolean isCredentialDescriptionApiEnabled() {
- return true;
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API,
+ false);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
}
@SuppressWarnings("GuardedBy") // ErrorProne requires initiateProviderSessionForRequestLocked
@@ -954,7 +964,7 @@
Slog.i(TAG, "registerCredentialDescription with callingPackage: " + callingPackage);
if (!isCredentialDescriptionApiEnabled()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Feature not supported");
}
enforceCallingPackage(callingPackage, Binder.getCallingUid());
@@ -974,7 +984,7 @@
if (!isCredentialDescriptionApiEnabled()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("Feature not supported");
}
enforceCallingPackage(callingPackage, Binder.getCallingUid());
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 9c1d765..016e85b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -624,6 +624,27 @@
}
/**
+ * Retrieves the global policy set by the admin for the provided {@code policyDefinition} and
+ * if one was set, otherwise returns {@code null}.
+ */
+ @Nullable
+ <V> V getGlobalPolicySetByAdmin(
+ @NonNull PolicyDefinition<V> policyDefinition,
+ @NonNull EnforcingAdmin enforcingAdmin) {
+ Objects.requireNonNull(policyDefinition);
+ Objects.requireNonNull(enforcingAdmin);
+
+ synchronized (mLock) {
+ if (!hasGlobalPolicyLocked(policyDefinition)) {
+ return null;
+ }
+ PolicyValue<V> value = getGlobalPolicyStateLocked(policyDefinition)
+ .getPoliciesSetByAdmins().get(enforcingAdmin);
+ return value == null ? null : value.getValue();
+ }
+ }
+
+ /**
* Retrieves the values set for the provided {@code policyDefinition} by each admin.
*/
@NonNull
@@ -1451,11 +1472,10 @@
synchronized (mLock) {
clear();
new DevicePoliciesReaderWriter().readFromFileLocked();
- reapplyAllPoliciesLocked();
}
}
- private <V> void reapplyAllPoliciesLocked() {
+ <V> void reapplyAllPoliciesLocked() {
for (PolicyKey policy : mGlobalPolicies.keySet()) {
PolicyState<?> policyState = mGlobalPolicies.get(policy);
// Policy definition and value will always be of the same type
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b104185..6885a89 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -241,6 +241,7 @@
import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
import static android.provider.Telephony.Carriers.INVALID_APN_ID;
import static android.security.keystore.AttestationUtils.USE_INDIVIDUAL_ATTESTATION;
+
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
@@ -2143,9 +2144,7 @@
mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener());
mDeviceManagementResourcesProvider.load();
- if (isPermissionCheckFlagEnabled() || isPolicyEngineForFinanceFlagEnabled()) {
- mDevicePolicyEngine.load();
- }
+ mDevicePolicyEngine.load();
mContactSystemRoleHolders = fetchOemSystemHolders(/* roleResIds...= */
com.android.internal.R.string.config_defaultSms,
@@ -3379,6 +3378,11 @@
mOwners.systemReady();
applyManagedSubscriptionsPolicyIfRequired();
break;
+ case SystemService.PHASE_SYSTEM_SERVICES_READY:
+ synchronized (getLockObject()) {
+ mDevicePolicyEngine.reapplyAllPoliciesLocked();
+ }
+ break;
case SystemService.PHASE_ACTIVITY_MANAGER_READY:
synchronized (getLockObject()) {
migrateToProfileOnOrganizationOwnedDeviceIfCompLocked();
@@ -9328,16 +9332,20 @@
}
int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
-
if (isPolicyEngineForFinanceFlagEnabled()) {
PolicyDefinition<Boolean> policy =
PolicyDefinition.getPolicyDefinitionForUserRestriction(
UserManager.DISALLOW_CAMERA);
if (who != null) {
EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackageName);
- return Boolean.TRUE.equals(
- mDevicePolicyEngine.getLocalPolicySetByAdmin(
- policy, admin, affectedUserId));
+ Boolean value = null;
+ if (isDeviceOwner(caller)) {
+ value = mDevicePolicyEngine.getGlobalPolicySetByAdmin(policy, admin);
+ } else {
+ value = mDevicePolicyEngine.getLocalPolicySetByAdmin(
+ policy, admin, affectedUserId);
+ }
+ return Boolean.TRUE.equals(value);
} else {
return Boolean.TRUE.equals(
mDevicePolicyEngine.getResolvedPolicy(policy, affectedUserId));
@@ -11279,25 +11287,18 @@
}
}
- private void dumpPerUserData(IndentingPrintWriter pw) {
+ private void dumpPersonalAppInfoForSystemUserNoLock(IndentingPrintWriter pw) {
+ wtfIfInLock();
+ PersonalAppsSuspensionHelper.forUser(mContext, UserHandle.USER_SYSTEM).dump(pw);
+ }
+
+ private void dumpPerUserPolicyData(IndentingPrintWriter pw) {
int userCount = mUserData.size();
for (int i = 0; i < userCount; i++) {
int userId = mUserData.keyAt(i);
DevicePolicyData policy = getUserData(userId);
policy.dump(pw);
pw.println();
-
- if (userId == UserHandle.USER_SYSTEM) {
- pw.increaseIndent();
- PersonalAppsSuspensionHelper.forUser(mContext, userId).dump(pw);
- pw.decreaseIndent();
- pw.println();
- } else {
- // pm.getUnsuspendablePackages() will fail if it's called for a different user;
- // as this dump is mostly useful for system user anyways, we can just ignore the
- // others (rather than changing the permission check in the PM method)
- Slogf.d(LOG_TAG, "skipping PersonalAppsSuspensionHelper.dump() for user " + userId);
- }
}
}
@@ -11315,7 +11316,7 @@
pw.println();
mDeviceAdminServiceController.dump(pw);
pw.println();
- dumpPerUserData(pw);
+ dumpPerUserPolicyData(pw);
pw.println();
mConstants.dump(pw);
pw.println();
@@ -11342,6 +11343,7 @@
mStateCache.dump(pw);
pw.println();
}
+ dumpPersonalAppInfoForSystemUserNoLock(pw);
synchronized (mSubscriptionsChangedListenerLock) {
pw.println("Subscription changed listener : " + mSubscriptionsChangedListener);
@@ -16567,6 +16569,83 @@
}
/**
+ * @param restriction The restriction enforced by admin. It could be any user restriction or
+ * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA},
+ * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE} and {@link
+ * DevicePolicyManager#POLICY_SUSPEND_PACKAGES}.
+ */
+ private Set<android.app.admin.EnforcingAdmin> getEnforcingAdminsForRestrictionInternal(
+ int userId, @NonNull String restriction) {
+ Objects.requireNonNull(restriction);
+ Set<android.app.admin.EnforcingAdmin> admins = new HashSet<>();
+ // For POLICY_SUSPEND_PACKAGES return PO or DO to keep the behavior same as
+ // before the bug fix for b/192245204.
+ if (DevicePolicyManager.POLICY_SUSPEND_PACKAGES.equals(
+ restriction)) {
+ ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId);
+ if (profileOwner != null) {
+ EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
+ profileOwner, userId);
+ admins.add(admin.getParcelableAdmin());
+ return admins;
+ }
+ final Pair<Integer, ComponentName> deviceOwner =
+ mOwners.getDeviceOwnerUserIdAndComponent();
+ if (deviceOwner != null && deviceOwner.first == userId) {
+ EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
+ deviceOwner.second, deviceOwner.first);
+ admins.add(admin.getParcelableAdmin());
+ return admins;
+ }
+ } else {
+ long ident = mInjector.binderClearCallingIdentity();
+ try {
+ PolicyDefinition<Boolean> policyDefinition = getPolicyDefinitionForRestriction(
+ restriction);
+ Boolean value = mDevicePolicyEngine.getResolvedPolicy(policyDefinition, userId);
+ if (value != null && value) {
+ Map<EnforcingAdmin, PolicyValue<Boolean>> globalPolicies =
+ mDevicePolicyEngine.getGlobalPoliciesSetByAdmins(policyDefinition);
+ for (EnforcingAdmin admin : globalPolicies.keySet()) {
+ if (globalPolicies.get(admin) != null
+ && Boolean.TRUE.equals(globalPolicies.get(admin).getValue())) {
+ admins.add(admin.getParcelableAdmin());
+ }
+ }
+
+ Map<EnforcingAdmin, PolicyValue<Boolean>> localPolicies =
+ mDevicePolicyEngine.getLocalPoliciesSetByAdmins(
+ policyDefinition, userId);
+ for (EnforcingAdmin admin : localPolicies.keySet()) {
+ if (localPolicies.get(admin) != null
+ && Boolean.TRUE.equals(localPolicies.get(admin).getValue())) {
+ admins.add(admin.getParcelableAdmin());
+ }
+ }
+ return admins;
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(ident);
+ }
+ }
+ return admins;
+ }
+
+ private static PolicyDefinition<Boolean> getPolicyDefinitionForRestriction(
+ @NonNull String restriction) {
+ Objects.requireNonNull(restriction);
+ if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) {
+ return PolicyDefinition.getPolicyDefinitionForUserRestriction(
+ UserManager.DISALLOW_CAMERA);
+ } else if (DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) {
+ return PolicyDefinition.SCREEN_CAPTURE_DISABLED;
+ } else {
+ return PolicyDefinition.getPolicyDefinitionForUserRestriction(restriction);
+ }
+ }
+
+
+ /**
* Excludes restrictions imposed by UserManager.
*/
private List<UserManager.EnforcingUser> getDevicePolicySources(
@@ -16604,6 +16683,13 @@
return getEnforcingAdminAndUserDetailsInternal(userId, restriction);
}
+ @Override
+ public List<android.app.admin.EnforcingAdmin> getEnforcingAdminsForRestriction(
+ int userId, String restriction) {
+ Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()));
+ return new ArrayList<>(getEnforcingAdminsForRestrictionInternal(userId, restriction));
+ }
+
/**
* @param restriction The restriction enforced by admin. It could be any user restriction or
* policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
index 5243d14..0066422 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnforcingAdmin.java
@@ -228,7 +228,8 @@
return new android.app.admin.EnforcingAdmin(
mPackageName,
authority,
- UserHandle.of(mUserId));
+ UserHandle.of(mUserId),
+ mComponentName);
}
/**
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
index 9a8e421..8684dbe 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
@@ -111,7 +111,7 @@
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- mInjector.getNotificationManager().cancel(LOG_TAG, NOTIFICATION_ID);
+ cancelNotification();
if (ACTION_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
onBugreportSharingAccepted();
} else if (ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
@@ -213,8 +213,7 @@
mRemoteBugreportServiceIsActive.set(true);
mRemoteBugreportSharingAccepted.set(false);
registerRemoteBugreportReceivers();
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_STARTED), UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_STARTED);
mHandler.postDelayed(mRemoteBugreportTimeoutRunnable, REMOTE_BUGREPORT_TIMEOUT_MILLIS);
return true;
} catch (RemoteException re) {
@@ -258,13 +257,10 @@
final String bugreportHash = intent.getStringExtra(EXTRA_REMOTE_BUGREPORT_HASH);
if (mRemoteBugreportSharingAccepted.get()) {
shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
- mInjector.getNotificationManager().cancel(LOG_TAG,
- NOTIFICATION_ID);
+ cancelNotification();
} else {
mService.setDeviceOwnerRemoteBugreportUriAndHash(bugreportUriString, bugreportHash);
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
- UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED);
}
mContext.unregisterReceiver(mRemoteBugreportFinishedReceiver);
}
@@ -274,7 +270,7 @@
mInjector.systemPropertiesSet(CTL_STOP, REMOTE_BUGREPORT_SERVICE);
mRemoteBugreportSharingAccepted.set(false);
mService.setDeviceOwnerRemoteBugreportUriAndHash(null, null);
- mInjector.getNotificationManager().cancel(LOG_TAG, NOTIFICATION_ID);
+ cancelNotification();
final Bundle extras = new Bundle();
extras.putInt(DeviceAdminReceiver.EXTRA_BUGREPORT_FAILURE_REASON,
DeviceAdminReceiver.BUGREPORT_FAILURE_FAILED_COMPLETING);
@@ -289,9 +285,7 @@
if (uriAndHash != null) {
shareBugreportWithDeviceOwnerIfExists(uriAndHash.first, uriAndHash.second);
} else if (mRemoteBugreportServiceIsActive.get()) {
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED),
- UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED);
}
}
@@ -340,7 +334,16 @@
filterConsent.addAction(ACTION_BUGREPORT_SHARING_DECLINED);
filterConsent.addAction(ACTION_BUGREPORT_SHARING_ACCEPTED);
mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED), UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED);
+ }
+
+ private void notify(@RemoteBugreportNotificationType int type) {
+ mInjector.getNotificationManager()
+ .notifyAsUser(LOG_TAG, NOTIFICATION_ID, buildNotification(type), UserHandle.ALL);
+ }
+
+ private void cancelNotification() {
+ mInjector.getNotificationManager()
+ .cancelAsUser(LOG_TAG, NOTIFICATION_ID, UserHandle.ALL);
}
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index e8acb06..6ff7b26 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -16,15 +16,20 @@
package com.android.inputmethodservice;
+import static android.view.WindowInsets.Type.captionBar;
+
import static com.android.compatibility.common.util.SystemUtil.eventually;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Insets;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.uiautomator.By;
@@ -32,6 +37,7 @@
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.util.Log;
+import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
@@ -592,6 +598,20 @@
false /* orientationPortrait */);
}
+ /**
+ * This checks that when the system navigation bar is not created (e.g. emulator),
+ * then the IME caption bar is also not created.
+ */
+ @Test
+ public void testNoNavigationBar_thenImeNoCaptionBar() throws Exception {
+ boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
+ .hasNavigationBar(mInputMethodService.getDisplayId());
+ assumeFalse("Must not have a navigation bar", hasNavigationBar);
+
+ assertEquals(Insets.NONE, mInputMethodService.getWindow().getWindow().getDecorView()
+ .getRootWindowInsets().getInsetsIgnoringVisibility(captionBar()));
+ }
+
private void verifyInputViewStatus(
Runnable runnable, boolean expected, boolean inputViewStarted)
throws InterruptedException {
diff --git a/services/tests/displayservicetests/Android.bp b/services/tests/displayservicetests/Android.bp
index a421db0..8eb1b0b 100644
--- a/services/tests/displayservicetests/Android.bp
+++ b/services/tests/displayservicetests/Android.bp
@@ -27,6 +27,7 @@
"mockingservicestests-utils-mockito",
"platform-compat-test-rules",
"platform-test-annotations",
+ "service-permission.stubs.system_server",
"services.core",
"servicestests-utils",
"testables",
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 50cf169..14586ae 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -58,6 +58,7 @@
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -106,6 +107,7 @@
import com.android.server.display.DisplayManagerService.SyncRoot;
import com.android.server.input.InputManagerInternal;
import com.android.server.lights.LightsManager;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.sensors.SensorManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -254,10 +256,11 @@
@Mock LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy;
@Mock IBinder mMockDisplayToken;
@Mock SensorManagerInternal mMockSensorManagerInternal;
-
@Mock SensorManager mSensorManager;
-
@Mock DisplayDeviceConfig mMockDisplayDeviceConfig;
+ @Mock PackageManagerInternal mMockPackageManagerInternal;
+ @Mock UserManagerInternal mMockUserManagerInternal;
+
@Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
@@ -276,6 +279,10 @@
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
LocalServices.addService(
VirtualDeviceManagerInternal.class, mMockVirtualDeviceManagerInternal);
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
// TODO: b/287945043
mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
index c39bb56..9d309e9 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -1104,6 +1104,21 @@
verify(mDisplayWhiteBalanceControllerMock, times(1)).setStrongModeEnabled(true);
}
+ @Test
+ public void testPowerStateStopsOnDpcStop() {
+ // Set up
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1);
+
+ // Stop dpc
+ mHolder.dpc.stop();
+ advanceTime(1);
+
+ // Ensure dps has stopped
+ verify(mHolder.displayPowerState, times(1)).stop();
+ }
+
/**
* Creates a mock and registers it to {@link LocalServices}.
*/
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index 0544376..b9969ce 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -1106,6 +1106,21 @@
verify(mDisplayWhiteBalanceControllerMock, times(1)).setStrongModeEnabled(true);
}
+ @Test
+ public void testPowerStateStopsOnDpcStop() {
+ // Set up
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1);
+
+ // Stop dpc
+ mHolder.dpc.stop();
+ advanceTime(1);
+
+ // Ensure dps has stopped
+ verify(mHolder.displayPowerState, times(1)).stop();
+ }
+
/**
* Creates a mock and registers it to {@link LocalServices}.
*/
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.java
new file mode 100644
index 0000000..167a412
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerStateTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.mockito.Mockito.times;
+
+import android.os.Handler;
+import android.os.test.TestLooper;
+import android.view.Display;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+
+@SmallTest
+public class DisplayPowerStateTest {
+ private static final int DISPLAY_ID = 123;
+
+ private DisplayPowerState mDisplayPowerState;
+ private TestLooper mTestLooper;
+ @Mock
+ private DisplayBlanker mDisplayBlankerMock;
+ @Mock
+ private ColorFade mColorFadeMock;
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ @Before
+ public void setUp() {
+ mTestLooper = new TestLooper();
+ mDisplayPowerState = new DisplayPowerState(
+ mDisplayBlankerMock, mColorFadeMock, DISPLAY_ID, Display.STATE_ON,
+ new Handler(mTestLooper.getLooper()));
+ }
+
+ @Test
+ public void testColorFadeStopsOnDpsStop() {
+ mDisplayPowerState.stop();
+ verify(mColorFadeMock, times(1)).stop();
+ }
+}
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 0fe6e64..13c107d 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -42,8 +42,12 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -55,6 +59,7 @@
import android.os.IThermalService;
import android.os.PowerManager;
import android.os.Process;
+import android.os.RemoteException;
import android.os.test.TestLooper;
import android.view.Display;
import android.view.DisplayAddress;
@@ -65,7 +70,7 @@
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import org.junit.Before;
import org.junit.Test;
@@ -87,6 +92,7 @@
private static int sUniqueTestDisplayId = 0;
private static final int DEVICE_STATE_CLOSED = 0;
private static final int DEVICE_STATE_OPEN = 2;
+ private static final int FLAG_GO_TO_SLEEP_ON_FOLD = 0;
private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;
private static final File NON_EXISTING_FILE = new File("/non_existing_folder/should_not_exist");
@@ -101,7 +107,7 @@
@Mock LogicalDisplayMapper.Listener mListenerMock;
@Mock Context mContextMock;
- @Mock FoldSettingWrapper mFoldSettingWrapperMock;
+ @Mock FoldSettingProvider mFoldSettingProviderMock;
@Mock Resources mResourcesMock;
@Mock IPowerManager mIPowerManagerMock;
@Mock IThermalService mIThermalServiceMock;
@@ -111,7 +117,7 @@
@Captor ArgumentCaptor<LogicalDisplay> mDisplayCaptor;
@Before
- public void setUp() {
+ public void setUp() throws RemoteException {
// Share classloader to allow package private access.
System.setProperty("dexmaker.share_classloader", "true");
MockitoAnnotations.initMocks(this);
@@ -141,7 +147,9 @@
when(mContextMock.getSystemServiceName(PowerManager.class))
.thenReturn(Context.POWER_SERVICE);
- when(mFoldSettingWrapperMock.shouldStayAwakeOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+ when(mIPowerManagerMock.isInteractive()).thenReturn(true);
when(mContextMock.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
when(mContextMock.getResources()).thenReturn(mResourcesMock);
when(mResourcesMock.getBoolean(
@@ -156,9 +164,10 @@
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
- mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo,
+ mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mFoldSettingProviderMock,
+ mDisplayDeviceRepo,
mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
- mDeviceStateToLayoutMapSpy, mFoldSettingWrapperMock);
+ mDeviceStateToLayoutMapSpy);
}
@@ -574,8 +583,8 @@
}
@Test
- public void testDeviceShouldNotSleepWhenFoldSettingTrue() {
- when(mFoldSettingWrapperMock.shouldStayAwakeOnFold()).thenReturn(true);
+ public void testDeviceShouldNotSleepWhenStayAwakeSettingTrue() {
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(true);
assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
DEVICE_STATE_OPEN,
@@ -608,6 +617,26 @@
}
@Test
+ public void testDeviceShouldPutToSleepWhenSleepSettingTrue() throws RemoteException {
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(true);
+
+ finishBootAndFoldDevice();
+
+ verify(mIPowerManagerMock, atLeastOnce()).goToSleep(anyLong(), anyInt(),
+ eq(FLAG_GO_TO_SLEEP_ON_FOLD));
+ }
+
+ @Test
+ public void testDeviceShouldNotBePutToSleepWhenSleepSettingFalse() throws RemoteException {
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+
+ finishBootAndFoldDevice();
+
+ verify(mIPowerManagerMock, never()).goToSleep(anyLong(), anyInt(),
+ eq(FLAG_GO_TO_SLEEP_ON_FOLD));
+ }
+
+ @Test
public void testDeviceStateLocked() {
DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
@@ -859,6 +888,15 @@
// Helper Methods
/////////////////
+ private void finishBootAndFoldDevice() {
+ mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_OPEN, false);
+ advanceTime(1000);
+ mLogicalDisplayMapper.onBootCompleted();
+ advanceTime(1000);
+ mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_CLOSED, false);
+ advanceTime(1000);
+ }
+
private void createDefaultDisplay(Layout layout, DisplayDevice device) {
createDefaultDisplay(layout, info(device).address);
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/RampAnimatorTest.java b/services/tests/displayservicetests/src/com/android/server/display/RampAnimatorTest.java
new file mode 100644
index 0000000..2820da7
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/RampAnimatorTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import static org.junit.Assert.assertEquals;
+
+import android.util.FloatProperty;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+@SmallTest
+public class RampAnimatorTest {
+
+ private RampAnimator<TestObject> mRampAnimator;
+
+ private final TestObject mTestObject = new TestObject();
+
+ private final FloatProperty<TestObject> mTestProperty = new FloatProperty<>("mValue") {
+ @Override
+ public void setValue(TestObject object, float value) {
+ object.mValue = value;
+ }
+
+ @Override
+ public Float get(TestObject object) {
+ return object.mValue;
+ }
+ };
+
+ @Before
+ public void setUp() {
+ mRampAnimator = new RampAnimator<>(mTestObject, mTestProperty);
+ }
+
+ @Test
+ public void testInitialValueUsedInLastAnimationStep() {
+ mRampAnimator.setAnimationTarget(0.67f, 0.1f);
+
+ assertEquals(0.67f, mTestObject.mValue, 0);
+ }
+
+ private static class TestObject {
+ private float mValue;
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 9545a8a..3d7ae34 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -1862,6 +1862,13 @@
assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
SCHED_GROUP_DEFAULT);
assertBfsl(app2);
+
+ bindService(client2, app1, null, 0, mock(IBinder.class));
+ bindService(app1, client2, null, 0, mock(IBinder.class));
+ client2.mServices.setHasForegroundServices(false, 0, /* hasNoneType=*/false);
+ updateOomAdj(app1, client1, client2);
+ assertProcStates(app1, PROCESS_STATE_IMPORTANT_FOREGROUND, VISIBLE_APP_ADJ,
+ SCHED_GROUP_TOP_APP);
}
@SuppressWarnings("GuardedBy")
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java
new file mode 100644
index 0000000..1ce79a5
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/display/SmallAreaDetectionControllerTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import static android.os.Process.INVALID_UID;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContextWrapper;
+import android.content.pm.PackageManagerInternal;
+import android.provider.DeviceConfigInterface;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SmallAreaDetectionControllerTest {
+
+ @Rule
+ public MockitoRule mRule = MockitoJUnit.rule();
+
+ @Mock
+ private PackageManagerInternal mMockPackageManagerInternal;
+ @Mock
+ private UserManagerInternal mMockUserManagerInternal;
+
+ private SmallAreaDetectionController mSmallAreaDetectionController;
+
+ private static final String PKG_A = "com.a.b.c";
+ private static final String PKG_B = "com.d.e.f";
+ private static final String PKG_NOT_INSTALLED = "com.not.installed";
+ private static final float THRESHOLD_A = 0.05f;
+ private static final float THRESHOLD_B = 0.07f;
+ private static final int USER_1 = 110;
+ private static final int USER_2 = 111;
+ private static final int UID_A_1 = 11011111;
+ private static final int UID_A_2 = 11111111;
+ private static final int UID_B_1 = 11022222;
+ private static final int UID_B_2 = 11122222;
+
+ @Before
+ public void setup() {
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
+
+ when(mMockUserManagerInternal.getUserIds()).thenReturn(new int[]{USER_1, USER_2});
+ when(mMockPackageManagerInternal.getPackageUid(PKG_A, 0, USER_1)).thenReturn(UID_A_1);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_A, 0, USER_2)).thenReturn(UID_A_2);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_B, 0, USER_1)).thenReturn(UID_B_1);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_B, 0, USER_2)).thenReturn(UID_B_2);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_NOT_INSTALLED, 0, USER_1)).thenReturn(
+ INVALID_UID);
+ when(mMockPackageManagerInternal.getPackageUid(PKG_NOT_INSTALLED, 0, USER_2)).thenReturn(
+ INVALID_UID);
+
+ mSmallAreaDetectionController = spy(new SmallAreaDetectionController(
+ new ContextWrapper(ApplicationProvider.getApplicationContext()),
+ DeviceConfigInterface.REAL));
+ doNothing().when(mSmallAreaDetectionController).updateSmallAreaDetection(any(), any());
+ }
+
+ @Test
+ public void testUpdateAllowlist_validProperty() {
+ final String property = PKG_A + ":" + THRESHOLD_A + "," + PKG_B + ":" + THRESHOLD_B;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ final int[] resultUidArray = {UID_A_1, UID_B_1, UID_A_2, UID_B_2};
+ final float[] resultThresholdArray = {THRESHOLD_A, THRESHOLD_B, THRESHOLD_A, THRESHOLD_B};
+ verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray),
+ eq(resultThresholdArray));
+ }
+
+ @Test
+ public void testUpdateAllowlist_includeInvalidRow() {
+ final String property = PKG_A + "," + PKG_B + ":" + THRESHOLD_B;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ final int[] resultUidArray = {UID_B_1, UID_B_2};
+ final float[] resultThresholdArray = {THRESHOLD_B, THRESHOLD_B};
+ verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray),
+ eq(resultThresholdArray));
+ }
+
+ @Test
+ public void testUpdateAllowlist_includeNotInstalledPkg() {
+ final String property =
+ PKG_A + ":" + THRESHOLD_A + "," + PKG_NOT_INSTALLED + ":" + THRESHOLD_B;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ final int[] resultUidArray = {UID_A_1, UID_A_2};
+ final float[] resultThresholdArray = {THRESHOLD_A, THRESHOLD_A};
+ verify(mSmallAreaDetectionController).updateSmallAreaDetection(eq(resultUidArray),
+ eq(resultThresholdArray));
+ }
+
+ @Test
+ public void testUpdateAllowlist_invalidProperty() {
+ final String property = PKG_A;
+ mSmallAreaDetectionController.updateAllowlist(property);
+
+ verify(mSmallAreaDetectionController, never()).updateSmallAreaDetection(any(), any());
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java
new file mode 100644
index 0000000..3514276
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils;
+
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_SLEEP_ON_FOLD;
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_STAY_AWAKE_ON_FOLD;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.R;
+import com.android.internal.util.SettingsWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class FoldSettingProviderTest {
+
+ private static final String SETTING_VALUE_INVALID = "invalid_fold_lock_behavior";
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private SettingsWrapper mSettingsWrapper;
+ private ContentResolver mContentResolver;
+ private FoldSettingProvider mFoldSettingProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContentResolver =
+ InstrumentationRegistry.getInstrumentation().getContext().getContentResolver();
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getResources()).thenReturn(mResources);
+ setFoldLockBehaviorAvailability(true);
+
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+ }
+
+ @Test
+ public void foldSettingNotAvailable_returnDefaultSetting() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingNotAvailable_notReturnStayAwakeOnFoldTrue() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldStayAwakeOnFold = mFoldSettingProvider.shouldStayAwakeOnFold();
+
+ assertThat(shouldStayAwakeOnFold).isFalse();
+ }
+
+ @Test
+ public void foldSettingNotAvailable_notReturnSleepOnFoldTrue() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_SLEEP_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldSleepOnFold = mFoldSettingProvider.shouldSleepOnFold();
+
+ assertThat(shouldSleepOnFold).isFalse();
+ }
+
+ @Test
+ public void foldSettingAvailable_returnCorrectFoldSetting() {
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+
+ boolean shouldStayAwakeOnFold = mFoldSettingProvider.shouldStayAwakeOnFold();
+
+ assertThat(shouldStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingInvalid_returnDefaultSetting() {
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_INVALID);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingNotDefined_returnDefaultSetting() {
+ setFoldLockBehaviorSettingValue(null);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ private void setFoldLockBehaviorAvailability(boolean isFoldLockBehaviorEnabled) {
+ when(mResources.getBoolean(R.bool.config_fold_lock_behavior)).thenReturn(
+ isFoldLockBehaviorEnabled);
+ }
+
+ private void setFoldLockBehaviorSettingValue(String foldLockBehaviorSettingValue) {
+ when(mSettingsWrapper.getStringForUser(any(),
+ eq(Settings.System.FOLD_LOCK_BEHAVIOR),
+ eq(UserHandle.USER_CURRENT))).thenReturn(foldLockBehaviorSettingValue);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index 769be17..0f3daec 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -182,7 +182,8 @@
eq(TEST_PACKAGE),
eq(TEST_REQUEST_ID),
eq(sensor.getCookie()),
- anyBoolean() /* allowBackgroundAuthentication */);
+ anyBoolean() /* allowBackgroundAuthentication */,
+ anyBoolean() /* isForLegacyFingerprintManager */);
}
final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
index 0b730f1..ba77390 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
@@ -87,6 +87,8 @@
public void setUp() {
when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(eq(R.bool.config_biometricFrrNotificationEnabled)))
+ .thenReturn(true);
when(mResources.getFraction(eq(R.fraction.config_biometricNotificationFrrThreshold),
anyInt(), anyInt())).thenReturn(FRR_THRESHOLD);
@@ -109,12 +111,16 @@
0 /* modality */, mBiometricNotification);
}
-
@Test
public void authenticate_authenticationSucceeded_mapShouldBeUpdated() {
// Assert that the user doesn't exist in the map initially.
assertThat(mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1)).isNull();
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
+ .thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
+ when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
+
mAuthenticationStatsCollector.authenticate(USER_ID_1, true /* authenticated */);
AuthenticationStats authenticationStats =
@@ -130,6 +136,11 @@
// Assert that the user doesn't exist in the map initially.
assertThat(mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1)).isNull();
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
+ .thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
+ when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
+
mAuthenticationStatsCollector.authenticate(USER_ID_1, false /* authenticated */);
AuthenticationStats authenticationStats =
@@ -176,6 +187,11 @@
40 /* rejectedAttempts */, 0 /* enrollmentNotifications */,
0 /* modality */));
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
+ .thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
+ when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
+
mAuthenticationStatsCollector.authenticate(USER_ID_1, false /* authenticated */);
// Assert that no notification should be sent.
@@ -233,13 +249,13 @@
// Assert that no notification should be sent.
verify(mBiometricNotification, never()).sendFaceEnrollNotification(any());
verify(mBiometricNotification, never()).sendFpEnrollNotification(any());
- // Assert that data has been reset.
+ // Assert that data hasn't been reset.
AuthenticationStats authenticationStats = mAuthenticationStatsCollector
.getAuthenticationStatsForUser(USER_ID_1);
- assertThat(authenticationStats.getTotalAttempts()).isEqualTo(0);
- assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(0);
+ assertThat(authenticationStats.getTotalAttempts()).isEqualTo(500);
+ assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(400);
assertThat(authenticationStats.getEnrollmentNotifications()).isEqualTo(0);
- assertThat(authenticationStats.getFrr()).isWithin(0f).of(-1.0f);
+ assertThat(authenticationStats.getFrr()).isWithin(0f).of(0.8f);
}
@Test
@@ -260,13 +276,13 @@
// Assert that no notification should be sent.
verify(mBiometricNotification, never()).sendFaceEnrollNotification(any());
verify(mBiometricNotification, never()).sendFpEnrollNotification(any());
- // Assert that data has been reset.
+ // Assert that data hasn't been reset.
AuthenticationStats authenticationStats = mAuthenticationStatsCollector
.getAuthenticationStatsForUser(USER_ID_1);
- assertThat(authenticationStats.getTotalAttempts()).isEqualTo(0);
- assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(0);
+ assertThat(authenticationStats.getTotalAttempts()).isEqualTo(500);
+ assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(400);
assertThat(authenticationStats.getEnrollmentNotifications()).isEqualTo(0);
- assertThat(authenticationStats.getFrr()).isWithin(0f).of(-1.0f);
+ assertThat(authenticationStats.getFrr()).isWithin(0f).of(0.8f);
}
@Test
@@ -326,4 +342,32 @@
// Assert that notification count has been updated.
assertThat(authenticationStats.getEnrollmentNotifications()).isEqualTo(1);
}
+
+ @Test
+ public void authenticate_featureDisabled_mapMustNotBeUpdated() {
+ // Disable the feature.
+ when(mResources.getBoolean(eq(R.bool.config_biometricFrrNotificationEnabled)))
+ .thenReturn(false);
+ AuthenticationStatsCollector authenticationStatsCollector =
+ new AuthenticationStatsCollector(mContext, 0 /* modality */,
+ mBiometricNotification);
+
+ authenticationStatsCollector.setAuthenticationStatsForUser(USER_ID_1,
+ new AuthenticationStats(USER_ID_1, 500 /* totalAttempts */,
+ 400 /* rejectedAttempts */, 0 /* enrollmentNotifications */,
+ 0 /* modality */));
+
+ authenticationStatsCollector.authenticate(USER_ID_1, false /* authenticated */);
+
+ // Assert that no notification should be sent.
+ verify(mBiometricNotification, never()).sendFaceEnrollNotification(any());
+ verify(mBiometricNotification, never()).sendFpEnrollNotification(any());
+ // Assert that data hasn't been updated.
+ AuthenticationStats authenticationStats = authenticationStatsCollector
+ .getAuthenticationStatsForUser(USER_ID_1);
+ assertThat(authenticationStats.getTotalAttempts()).isEqualTo(500);
+ assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(400);
+ assertThat(authenticationStats.getEnrollmentNotifications()).isEqualTo(0);
+ assertThat(authenticationStats.getFrr()).isWithin(0f).of(0.8f);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index e79ac09..0230d77 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -598,7 +598,8 @@
anyString() /* opPackageName */,
eq(TEST_REQUEST_ID),
cookieCaptor.capture() /* cookie */,
- anyBoolean() /* allowBackgroundAuthentication */);
+ anyBoolean() /* allowBackgroundAuthentication */,
+ anyBoolean() /* isForLegacyFingerprintManager */);
// onReadyForAuthentication, mAuthSession state OK
mBiometricService.mImpl.onReadyForAuthentication(TEST_REQUEST_ID, cookieCaptor.getValue());
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
index 046b01c..9e5a047 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
@@ -36,6 +36,7 @@
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
+import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.common.AuthenticateReason;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.common.OperationContext;
@@ -109,6 +110,8 @@
private ICancellationSignal mCancellationSignal;
@Mock
private AuthSessionCoordinator mAuthSessionCoordinator;
+ @Mock
+ private BiometricManager mBiometricManager;
@Captor
private ArgumentCaptor<OperationContextExt> mOperationContextCaptor;
@Captor
@@ -119,6 +122,7 @@
@Before
public void setup() {
+ mContext.addMockSystemService(BiometricManager.class, mBiometricManager);
when(mBiometricContext.updateContext(any(), anyBoolean())).thenAnswer(
i -> i.getArgument(0));
when(mBiometricContext.getAuthSessionCoordinator()).thenReturn(mAuthSessionCoordinator);
@@ -212,11 +216,44 @@
.onError(anyInt(), anyInt(), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
}
+ @Test
+ public void testOnAuthenticatedFalseWhenListenerIsNull() throws RemoteException {
+ final FaceAuthenticationClient client = createClientWithNullListener();
+ client.start(mCallback);
+ client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */),
+ false /* authenticated */, new ArrayList<>());
+
+ verify(mCallback).onClientFinished(client, true);
+ }
+
+ @Test
+ public void testOnAuthenticatedTrueWhenListenerIsNull() throws RemoteException {
+ final FaceAuthenticationClient client = createClientWithNullListener();
+ client.start(mCallback);
+ client.onAuthenticated(new Face("friendly", 1 /* faceId */, 2 /* deviceId */),
+ true /* authenticated */, new ArrayList<>());
+
+ verify(mCallback).onClientFinished(client, true);
+ }
+
private FaceAuthenticationClient createClient() throws RemoteException {
- return createClient(2 /* version */);
+ return createClient(2 /* version */, mClientMonitorCallbackConverter,
+ false /* allowBackgroundAuthentication */);
+ }
+
+ private FaceAuthenticationClient createClientWithNullListener() throws RemoteException {
+ return createClient(2 /* version */, null /* listener */,
+ true /* allowBackgroundAuthentication */);
}
private FaceAuthenticationClient createClient(int version) throws RemoteException {
+ return createClient(version, mClientMonitorCallbackConverter,
+ false /* allowBackgroundAuthentication */);
+ }
+
+ private FaceAuthenticationClient createClient(int version,
+ ClientMonitorCallbackConverter listener,
+ boolean allowBackgroundAuthentication) throws RemoteException {
when(mHal.getInterfaceVersion()).thenReturn(version);
final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
@@ -229,11 +266,11 @@
FaceAuthenticateOptions.AUTHENTICATE_REASON_ASSISTANT_VISIBLE)
.build();
return new FaceAuthenticationClient(mContext, () -> aidl, mToken,
- 2 /* requestId */, mClientMonitorCallbackConverter, OP_ID,
+ 2 /* requestId */, listener, OP_ID,
false /* restricted */, options, 4 /* cookie */,
false /* requireConfirmation */,
mBiometricLogger, mBiometricContext, true /* isStrongBiometric */,
- mUsageStats, null /* mLockoutCache */, false /* allowBackgroundAuthentication */,
+ mUsageStats, null /* mLockoutCache */, allowBackgroundAuthentication,
null /* sensorPrivacyManager */, 0 /* biometricStrength */) {
@Override
protected ActivityTaskManager getActivityTaskManager() {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index 46af905..8a11e31 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -392,7 +392,6 @@
final ActivityManager.RunningTaskInfo topTask = new ActivityManager.RunningTaskInfo();
topTask.topActivity = new ComponentName("other", "thing");
when(mActivityTaskManager.getTasks(anyInt())).thenReturn(List.of(topTask));
- when(mHal.authenticateWithContext(anyLong(), any())).thenReturn(mCancellationSignal);
final FingerprintAuthenticationClient client = createClientWithoutBackgroundAuth();
client.start(mCallback);
@@ -406,21 +405,50 @@
.onError(anyInt(), anyInt(), eq(BIOMETRIC_ERROR_CANCELED), anyInt());
}
+ @Test
+ public void testOnAuthenticatedFalseWhenListenerIsNull() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClientWithNullListener();
+ client.start(mCallback);
+ client.onAuthenticated(new Fingerprint("friendly", 1 /* fingerId */,
+ 2 /* deviceId */), false /* authenticated */, new ArrayList<>());
+
+ verify(mCallback, never()).onClientFinished(eq(client), anyBoolean());
+ }
+
+ @Test
+ public void testOnAuthenticatedTrueWhenListenerIsNull() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClientWithNullListener();
+ client.start(mCallback);
+ client.onAuthenticated(new Fingerprint("friendly", 1 /* fingerId */,
+ 2 /* deviceId */), true /* authenticated */, new ArrayList<>());
+
+ verify(mCallback).onClientFinished(client, true);
+ }
+
private FingerprintAuthenticationClient createClient() throws RemoteException {
- return createClient(100 /* version */, true /* allowBackgroundAuthentication */);
+ return createClient(100 /* version */, true /* allowBackgroundAuthentication */,
+ mClientMonitorCallbackConverter);
}
private FingerprintAuthenticationClient createClientWithoutBackgroundAuth()
throws RemoteException {
- return createClient(100 /* version */, false /* allowBackgroundAuthentication */);
+ return createClient(100 /* version */, false /* allowBackgroundAuthentication */,
+ mClientMonitorCallbackConverter);
}
private FingerprintAuthenticationClient createClient(int version) throws RemoteException {
- return createClient(version, true /* allowBackgroundAuthentication */);
+ return createClient(version, true /* allowBackgroundAuthentication */,
+ mClientMonitorCallbackConverter);
+ }
+
+ private FingerprintAuthenticationClient createClientWithNullListener() throws RemoteException {
+ return createClient(100 /* version */, true /* allowBackgroundAuthentication */,
+ null /* listener */);
}
private FingerprintAuthenticationClient createClient(int version,
- boolean allowBackgroundAuthentication) throws RemoteException {
+ boolean allowBackgroundAuthentication, ClientMonitorCallbackConverter listener)
+ throws RemoteException {
when(mHal.getInterfaceVersion()).thenReturn(version);
final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
@@ -430,7 +458,7 @@
.setSensorId(9)
.build();
return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken,
- REQUEST_ID, mClientMonitorCallbackConverter, OP_ID,
+ REQUEST_ID, listener, OP_ID,
false /* restricted */, options, 4 /* cookie */,
false /* requireConfirmation */,
mBiometricLogger, mBiometricContext,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
index 20d5f93..78d3a9d 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
@@ -147,6 +148,24 @@
verify(mBiometricContext).unsubscribe(same(mOperationContextCaptor.getValue()));
}
+ @Test
+ public void testWhenListenerIsNull() {
+ final AidlSession aidl = new AidlSession(0, mHal, USER_ID, mHalSessionCallback);
+ final FingerprintDetectClient client = new FingerprintDetectClient(mContext, () -> aidl,
+ mToken, 6 /* requestId */, null /* listener */,
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(2)
+ .setSensorId(1)
+ .setOpPackageName("a-test")
+ .build(),
+ mBiometricLogger, mBiometricContext,
+ mUdfpsOverlayController, true /* isStrongBiometric */);
+ client.start(mCallback);
+ client.onInteractionDetected();
+
+ verify(mCallback).onClientFinished(eq(client), anyBoolean());
+ }
+
private FingerprintDetectClient createClient() throws RemoteException {
return createClient(200 /* version */);
}
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index ddd1221..d85768d 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -79,6 +79,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* Tests for the {@link MediaProjectionManagerService} class.
*
@@ -202,6 +205,29 @@
}
@Test
+ public void testCreateProjection_priorProjectionGrant() throws
+ NameNotFoundException, InterruptedException {
+ // Create a first projection.
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ FakeIMediaProjectionCallback callback1 = new FakeIMediaProjectionCallback();
+ projection.start(callback1);
+
+ // Create a second projection.
+ MediaProjectionManagerService.MediaProjection secondProjection =
+ startProjectionPreconditions();
+ FakeIMediaProjectionCallback callback2 = new FakeIMediaProjectionCallback();
+ secondProjection.start(callback2);
+
+ // Check that the first projection get stopped, but not the second projection.
+ final int timeout = 5;
+ boolean stoppedCallback1 = callback1.mLatch.await(timeout, TimeUnit.SECONDS);
+ boolean stoppedCallback2 = callback2.mLatch.await(timeout, TimeUnit.SECONDS);
+
+ assertThat(stoppedCallback1).isTrue();
+ assertThat(stoppedCallback2).isFalse();
+ }
+
+ @Test
public void testCreateProjection_attemptReuse_noPriorProjectionGrant()
throws NameNotFoundException {
// Create a first projection.
@@ -785,8 +811,10 @@
}
private static class FakeIMediaProjectionCallback extends IMediaProjectionCallback.Stub {
+ CountDownLatch mLatch = new CountDownLatch(1);
@Override
public void onStop() throws RemoteException {
+ mLatch.countDown();
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index 2273fcd..9f75cf8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -113,6 +113,42 @@
assertUserInfoEquals(data.info, read.info, /* parcelCopy= */ false);
}
+ /** Tests that device policy restrictions are written/read properly. */
+ @Test
+ public void testWriteReadDevicePolicyUserRestrictions() throws Exception {
+ final String globalRestriction = UserManager.DISALLOW_FACTORY_RESET;
+ final String localRestriction = UserManager.DISALLOW_CONFIG_DATE_TIME;
+
+ UserData data = new UserData();
+ data.info = createUser(100, FLAG_FULL, "A type");
+
+ mUserManagerService.putUserInfo(data.info);
+
+ // Set a global and user restriction so they get written out to the user file.
+ setUserRestrictions(data.info.id, globalRestriction, localRestriction, true);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(baos);
+ mUserManagerService.writeUserLP(data, out);
+ byte[] bytes = baos.toByteArray();
+
+ // Clear the restrictions to see if they are properly read in from the user file.
+ setUserRestrictions(data.info.id, globalRestriction, localRestriction, false);
+
+ mUserManagerService.readUserLP(data.info.id, new ByteArrayInputStream(bytes));
+ assertTrue(mUserManagerService.hasUserRestrictionOnAnyUser(globalRestriction));
+ assertTrue(mUserManagerService.hasUserRestrictionOnAnyUser(localRestriction));
+ }
+
+ /** Sets a global and local restriction and verifies they were set properly **/
+ private void setUserRestrictions(int id, String global, String local, boolean enabled) {
+ mUserManagerService.setUserRestrictionInner(UserHandle.USER_ALL, global, enabled);
+ assertEquals(mUserManagerService.hasUserRestrictionOnAnyUser(global), enabled);
+
+ mUserManagerService.setUserRestrictionInner(id, local, enabled);
+ assertEquals(mUserManagerService.hasUserRestrictionOnAnyUser(local), enabled);
+ }
+
@Test
public void testParcelUnparcelUserInfo() throws Exception {
UserInfo info = createUser();
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
index 1ba1462..a2dc5d8 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
@@ -37,7 +37,6 @@
import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.BatteryStatsHistoryIterator;
-import com.android.internal.os.Clock;
import org.junit.Before;
import org.junit.Test;
@@ -64,8 +63,9 @@
private final Parcel mHistoryBuffer = Parcel.obtain();
private File mSystemDir;
private File mHistoryDir;
- private final Clock mClock = new MockClock();
+ private final MockClock mClock = new MockClock();
private BatteryStatsHistory mHistory;
+ private BatteryStats.HistoryPrinter mHistoryPrinter;
@Mock
private BatteryStatsHistory.TraceDelegate mTracer;
@Mock
@@ -89,6 +89,8 @@
when(mStepDetailsCalculator.getHistoryStepDetails())
.thenReturn(new BatteryStats.HistoryStepDetails());
+
+ mHistoryPrinter = new BatteryStats.HistoryPrinter();
}
@Test
@@ -366,11 +368,95 @@
assertThat(checkin).contains("XC,10321,400,500,600");
}
+ @Test
+ public void largeTagPool() {
+ // Keep the preserved part of history short - we only need to capture the very tail of
+ // history.
+ mHistory = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 1, 6000,
+ mStepDetailsCalculator, mClock, mTracer);
+
+ mHistory.forceRecordAllHistory();
+
+ mClock.realtime = 2_000_000;
+ mClock.uptime = 1_000_000;
+ // More than 32k strings
+ final int tagCount = 0x7FFF + 20;
+ for (int tag = 0; tag < tagCount;) {
+ mClock.realtime += 10;
+ mClock.uptime += 10;
+ mHistory.recordEvent(mClock.realtime, mClock.uptime, HistoryItem.EVENT_ALARM_START,
+ "a" + (tag++), 42);
+
+ mHistory.setBatteryState(true, BatteryManager.BATTERY_STATUS_CHARGING, tag % 50, 0);
+ mClock.realtime += 10;
+ mClock.uptime += 10;
+ mHistory.recordWakelockStartEvent(mClock.realtime, mClock.uptime, "w" + tag, 42);
+ mClock.realtime += 10;
+ mClock.uptime += 10;
+ mHistory.recordWakelockStopEvent(mClock.realtime, mClock.uptime, "w" + tag, 42);
+ tag++;
+
+ mHistory.recordWakeupEvent(mClock.realtime, mClock.uptime, "wr" + (tag++));
+ }
+
+ int eventTagsPooled = 0;
+ int eventTagsUnpooled = 0;
+ int wakelockTagsPooled = 0;
+ int wakelockTagsUnpooled = 0;
+ int wakeReasonTagsPooled = 0;
+ int wakeReasonTagsUnpooled = 0;
+ for (BatteryStatsHistoryIterator iterator = mHistory.iterate(); iterator.hasNext(); ) {
+ HistoryItem item = iterator.next();
+ if (item.cmd != HistoryItem.CMD_UPDATE) {
+ continue;
+ }
+ String checkinDump = toString(item, true);
+ if (item.eventCode == HistoryItem.EVENT_ALARM_START) {
+ if (item.eventTag.poolIdx != BatteryStats.HistoryTag.HISTORY_TAG_POOL_OVERFLOW) {
+ eventTagsPooled++;
+ assertThat(checkinDump).contains("+Eal=" + item.eventTag.poolIdx);
+ } else {
+ eventTagsUnpooled++;
+ assertThat(checkinDump).contains("+Eal=42:\"" + item.eventTag.string + "\"");
+ }
+ }
+
+ if (item.wakelockTag != null) {
+ if (item.wakelockTag.poolIdx != BatteryStats.HistoryTag.HISTORY_TAG_POOL_OVERFLOW) {
+ wakelockTagsPooled++;
+ assertThat(checkinDump).contains("w=" + item.wakelockTag.poolIdx);
+ } else {
+ wakelockTagsUnpooled++;
+ assertThat(checkinDump).contains("w=42:\"" + item.wakelockTag.string + "\"");
+ }
+ }
+
+ if (item.wakeReasonTag != null) {
+ if (item.wakeReasonTag.poolIdx
+ != BatteryStats.HistoryTag.HISTORY_TAG_POOL_OVERFLOW) {
+ wakeReasonTagsPooled++;
+ assertThat(checkinDump).contains("wr=" + item.wakeReasonTag.poolIdx);
+ } else {
+ wakeReasonTagsUnpooled++;
+ assertThat(checkinDump).contains("wr=0:\"" + item.wakeReasonTag.string + "\"");
+ }
+ }
+ }
+
+ // Self-check - ensure that we have all cases represented in the test
+ assertThat(eventTagsPooled).isGreaterThan(0);
+ assertThat(eventTagsUnpooled).isGreaterThan(0);
+ assertThat(wakelockTagsPooled).isGreaterThan(0);
+ assertThat(wakelockTagsUnpooled).isGreaterThan(0);
+ assertThat(wakeReasonTagsPooled).isGreaterThan(0);
+ assertThat(wakeReasonTagsUnpooled).isGreaterThan(0);
+ }
+
private String toString(BatteryStats.HistoryItem item, boolean checkin) {
BatteryStats.HistoryPrinter printer = new BatteryStats.HistoryPrinter();
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
- printer.printNextItem(pw, item, 0, checkin, /* verbose */ true);
+ mHistoryPrinter.printNextItem(pw, item, 0, checkin, /* verbose */ false);
pw.flush();
return writer.toString();
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java b/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java
index 93464cd..d9bc74d 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java
@@ -35,7 +35,7 @@
private final List<StateChangeListener> mConfigurationInternalChangeListeners =
new ArrayList<>();
- private ConfigurationInternal mConfigurationInternal;
+ private ConfigurationInternal mCurrentUserConfigurationInternal;
@Override
public void addConfigurationInternalChangeListener(StateChangeListener listener) {
@@ -49,21 +49,23 @@
@Override
public ConfigurationInternal getCurrentUserConfigurationInternal() {
- return mConfigurationInternal;
+ return mCurrentUserConfigurationInternal;
}
@Override
public boolean updateConfiguration(
- @UserIdInt int userID, @NonNull TimeConfiguration requestedChanges,
+ @UserIdInt int userId, @NonNull TimeConfiguration requestedChanges,
boolean bypassUserPolicyChecks) {
- assertNotNull(mConfigurationInternal);
+ assertNotNull(mCurrentUserConfigurationInternal);
assertNotNull(requestedChanges);
+ ConfigurationInternal toUpdate = getConfigurationInternal(userId);
+
// Simulate the real strategy's behavior: the new configuration will be updated to be the
// old configuration merged with the new if the user has the capability to up the settings.
// Then, if the configuration changed, the change listener is invoked.
TimeCapabilitiesAndConfig capabilitiesAndConfig =
- mConfigurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
+ toUpdate.createCapabilitiesAndConfig(bypassUserPolicyChecks);
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
TimeConfiguration newConfiguration =
@@ -73,28 +75,36 @@
}
if (!newConfiguration.equals(capabilitiesAndConfig.getConfiguration())) {
- mConfigurationInternal = mConfigurationInternal.merge(newConfiguration);
+ mCurrentUserConfigurationInternal = toUpdate.merge(newConfiguration);
// Note: Unlike the real strategy, the listeners are invoked synchronously.
- simulateConfigurationChangeForTests();
+ notifyConfigurationChange();
}
return true;
}
- void initializeConfiguration(ConfigurationInternal configurationInternal) {
- mConfigurationInternal = configurationInternal;
+
+ void initializeCurrentUserConfiguration(ConfigurationInternal configurationInternal) {
+ mCurrentUserConfigurationInternal = configurationInternal;
}
- void simulateConfigurationChangeForTests() {
- for (StateChangeListener listener : mConfigurationInternalChangeListeners) {
- listener.onChange();
- }
+ void simulateCurrentUserConfigurationInternalChange(
+ ConfigurationInternal configurationInternal) {
+ mCurrentUserConfigurationInternal = configurationInternal;
+ // Note: Unlike the real strategy, the listeners are invoked synchronously.
+ notifyConfigurationChange();
}
@Override
public ConfigurationInternal getConfigurationInternal(int userId) {
assertEquals("Multi-user testing not supported currently",
- userId, mConfigurationInternal.getUserId());
- return mConfigurationInternal;
+ userId, mCurrentUserConfigurationInternal.getUserId());
+ return mCurrentUserConfigurationInternal;
+ }
+
+ private void notifyConfigurationChange() {
+ for (StateChangeListener listener : mConfigurationInternalChangeListeners) {
+ listener.onChange();
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java
index 87aa272..a7a9c0c 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java
@@ -18,6 +18,8 @@
import android.annotation.UserIdInt;
import android.app.time.ExternalTimeSuggestion;
+import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
import android.app.time.TimeState;
import android.app.time.UnixEpochTime;
import android.app.timedetector.ManualTimeSuggestion;
@@ -31,10 +33,20 @@
* in tests.
*/
public class FakeTimeDetectorStrategy implements TimeDetectorStrategy {
+ private final FakeServiceConfigAccessor mFakeServiceConfigAccessor;
+
// State
private TimeState mTimeState;
private NetworkTimeSuggestion mLatestNetworkTimeSuggestion;
+ FakeTimeDetectorStrategy() {
+ mFakeServiceConfigAccessor = new FakeServiceConfigAccessor();
+ }
+
+ void initializeConfiguration(ConfigurationInternal configuration) {
+ mFakeServiceConfigAccessor.initializeCurrentUserConfiguration(configuration);
+ }
+
@Override
public TimeState getTimeState() {
return mTimeState;
@@ -51,6 +63,26 @@
}
@Override
+ public void addChangeListener(StateChangeListener listener) {
+ mFakeServiceConfigAccessor.addConfigurationInternalChangeListener(listener);
+ }
+
+ @Override
+ public TimeCapabilitiesAndConfig getCapabilitiesAndConfig(int userId,
+ boolean bypassUserPolicyChecks) {
+ ConfigurationInternal configurationInternal =
+ mFakeServiceConfigAccessor.getConfigurationInternal(userId);
+ return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
+ }
+
+ @Override
+ public boolean updateConfiguration(int userId, TimeConfiguration configuration,
+ boolean bypassUserPolicyChecks) {
+ return mFakeServiceConfigAccessor.updateConfiguration(
+ userId, configuration, bypassUserPolicyChecks);
+ }
+
+ @Override
public void suggestTelephonyTime(TelephonyTimeSuggestion suggestion) {
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorInternalImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorInternalImplTest.java
index a0845a6..de5a37b 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorInternalImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorInternalImplTest.java
@@ -89,7 +89,7 @@
public void testGetCapabilitiesAndConfigForDpm() throws Exception {
final boolean autoDetectionEnabled = true;
ConfigurationInternal testConfig = createConfigurationInternal(autoDetectionEnabled);
- mFakeServiceConfigAccessorSpy.initializeConfiguration(testConfig);
+ mFakeServiceConfigAccessorSpy.initializeCurrentUserConfiguration(testConfig);
TimeCapabilitiesAndConfig actualCapabilitiesAndConfig =
mTimeDetectorInternal.getCapabilitiesAndConfigForDpm();
@@ -108,7 +108,8 @@
final boolean autoDetectionEnabled = false;
ConfigurationInternal initialConfigurationInternal =
createConfigurationInternal(autoDetectionEnabled);
- mFakeServiceConfigAccessorSpy.initializeConfiguration(initialConfigurationInternal);
+ mFakeServiceConfigAccessorSpy.initializeCurrentUserConfiguration(
+ initialConfigurationInternal);
TimeConfiguration timeConfiguration = new TimeConfiguration.Builder()
.setAutoDetectionEnabled(true)
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index daa6823..6b2d4b0 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -83,7 +83,6 @@
private HandlerThread mHandlerThread;
private TestHandler mTestHandler;
private TestCallerIdentityInjector mTestCallerIdentityInjector;
- private FakeServiceConfigAccessor mFakeServiceConfigAccessorSpy;
private FakeTimeDetectorStrategy mFakeTimeDetectorStrategySpy;
private NtpTrustedTime mMockNtpTrustedTime;
@@ -101,13 +100,12 @@
mTestCallerIdentityInjector = new TestCallerIdentityInjector();
mTestCallerIdentityInjector.initializeCallingUserId(ARBITRARY_USER_ID);
- mFakeServiceConfigAccessorSpy = spy(new FakeServiceConfigAccessor());
mFakeTimeDetectorStrategySpy = spy(new FakeTimeDetectorStrategy());
mMockNtpTrustedTime = mock(NtpTrustedTime.class);
mTimeDetectorService = new TimeDetectorService(
mMockContext, mTestHandler, mTestCallerIdentityInjector,
- mFakeServiceConfigAccessorSpy, mFakeTimeDetectorStrategySpy, mMockNtpTrustedTime);
+ mFakeTimeDetectorStrategySpy, mMockNtpTrustedTime);
}
@After
@@ -132,14 +130,14 @@
ConfigurationInternal configuration =
createConfigurationInternal(true /* autoDetectionEnabled*/);
- mFakeServiceConfigAccessorSpy.initializeConfiguration(configuration);
+ mFakeTimeDetectorStrategySpy.initializeConfiguration(configuration);
TimeCapabilitiesAndConfig actualCapabilitiesAndConfig =
mTimeDetectorService.getCapabilitiesAndConfig();
verify(mMockContext).enforceCallingPermission(
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
int expectedUserId = mTestCallerIdentityInjector.getCallingUserId();
- verify(mFakeServiceConfigAccessorSpy).getConfigurationInternal(expectedUserId);
+ verify(mFakeTimeDetectorStrategySpy).getCapabilitiesAndConfig(expectedUserId, false);
boolean bypassUserPolicyChecks = false;
TimeCapabilitiesAndConfig expectedCapabilitiesAndConfig =
@@ -174,7 +172,7 @@
public void testListenerRegistrationAndCallbacks() throws Exception {
ConfigurationInternal initialConfiguration =
createConfigurationInternal(false /* autoDetectionEnabled */);
- mFakeServiceConfigAccessorSpy.initializeConfiguration(initialConfiguration);
+ mFakeTimeDetectorStrategySpy.initializeConfiguration(initialConfiguration);
IBinder mockListenerBinder = mock(IBinder.class);
ITimeDetectorListener mockListener = mock(ITimeDetectorListener.class);
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 4df21e0..dd58135 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -29,14 +29,22 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.annotation.UserIdInt;
import android.app.time.ExternalTimeSuggestion;
+import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
import android.app.time.TimeState;
import android.app.time.UnixEpochTime;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.TelephonyTimeSuggestion;
import android.os.TimestampedValue;
+import android.util.IndentingPrintWriter;
import com.android.server.SystemClockTime.TimeConfidence;
import com.android.server.timedetector.TimeDetectorStrategy.Origin;
@@ -47,14 +55,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.PrintWriter;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
@@ -120,13 +126,108 @@
.build();
private FakeEnvironment mFakeEnvironment;
+ private FakeServiceConfigAccessor mFakeServiceConfigAccessorSpy;
+ private TimeDetectorStrategyImpl mTimeDetectorStrategy;
@Before
public void setUp() {
mFakeEnvironment = new FakeEnvironment();
- mFakeEnvironment.initializeConfig(CONFIG_AUTO_DISABLED);
mFakeEnvironment.initializeFakeClocks(
ARBITRARY_CLOCK_INITIALIZATION_INFO, TIME_CONFIDENCE_LOW);
+
+ mFakeServiceConfigAccessorSpy = spy(new FakeServiceConfigAccessor());
+ mFakeServiceConfigAccessorSpy.initializeCurrentUserConfiguration(CONFIG_AUTO_DISABLED);
+
+ mTimeDetectorStrategy = new TimeDetectorStrategyImpl(
+ mFakeEnvironment, mFakeServiceConfigAccessorSpy);
+ }
+
+ @Test
+ public void testChangeListenerBehavior() throws Exception {
+ TestStateChangeListener stateChangeListener = new TestStateChangeListener();
+ mTimeDetectorStrategy.addChangeListener(stateChangeListener);
+
+ boolean bypassUserPolicyChecks = false;
+
+ // Report a config change, but not one that actually changes anything.
+ {
+ mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+ CONFIG_AUTO_DISABLED);
+ assertStateChangeNotificationsSent(stateChangeListener, 0);
+ assertEquals(CONFIG_AUTO_DISABLED,
+ mTimeDetectorStrategy.getCachedCapabilitiesAndConfigForTests());
+ }
+
+ // Report a config change that actually changes something.
+ {
+ mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+ CONFIG_AUTO_ENABLED);
+ assertStateChangeNotificationsSent(stateChangeListener, 1);
+ assertEquals(CONFIG_AUTO_ENABLED,
+ mTimeDetectorStrategy.getCachedCapabilitiesAndConfigForTests());
+ }
+
+ // Perform a (current user) update via the strategy.
+ {
+ TimeConfiguration requestedChanges =
+ new TimeConfiguration.Builder().setAutoDetectionEnabled(false).build();
+ mTimeDetectorStrategy.updateConfiguration(
+ ARBITRARY_USER_ID, requestedChanges, bypassUserPolicyChecks);
+ assertStateChangeNotificationsSent(stateChangeListener, 1);
+ }
+ }
+
+ // Current user behavior: the strategy caches and returns the latest configuration.
+ @Test
+ public void testReadAndWriteConfiguration() throws Exception {
+ ConfigurationInternal currentUserConfig = CONFIG_AUTO_ENABLED;
+ mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+ currentUserConfig);
+
+ final boolean bypassUserPolicyChecks = false;
+
+ ConfigurationInternal cachedConfigurationInternal =
+ mTimeDetectorStrategy.getCachedCapabilitiesAndConfigForTests();
+ assertEquals(currentUserConfig, cachedConfigurationInternal);
+
+ // Confirm getCapabilitiesAndConfig() does not call through to the ServiceConfigAccessor.
+ {
+ reset(mFakeServiceConfigAccessorSpy);
+ TimeCapabilitiesAndConfig actualCapabilitiesAndConfig =
+ mTimeDetectorStrategy.getCapabilitiesAndConfig(
+ currentUserConfig.getUserId(), bypassUserPolicyChecks);
+ verify(mFakeServiceConfigAccessorSpy, never()).getConfigurationInternal(
+ currentUserConfig.getUserId());
+
+ TimeCapabilitiesAndConfig expectedCapabilitiesAndConfig =
+ currentUserConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
+ assertEquals(expectedCapabilitiesAndConfig.getCapabilities(),
+ actualCapabilitiesAndConfig.getCapabilities());
+ assertEquals(expectedCapabilitiesAndConfig.getConfiguration(),
+ actualCapabilitiesAndConfig.getConfiguration());
+ }
+
+ // Confirm updateConfiguration() calls through to the ServiceConfigAccessor and updates
+ // the cached copy.
+ {
+ boolean newAutoDetectionEnabled =
+ !cachedConfigurationInternal.getAutoDetectionEnabledBehavior();
+ TimeConfiguration requestedChanges = new TimeConfiguration.Builder()
+ .setAutoDetectionEnabled(newAutoDetectionEnabled)
+ .build();
+ ConfigurationInternal expectedConfigAfterChange =
+ new ConfigurationInternal.Builder(cachedConfigurationInternal)
+ .setAutoDetectionEnabledSetting(newAutoDetectionEnabled)
+ .build();
+
+ reset(mFakeServiceConfigAccessorSpy);
+ mTimeDetectorStrategy.updateConfiguration(
+ currentUserConfig.getUserId(), requestedChanges, bypassUserPolicyChecks);
+ verify(mFakeServiceConfigAccessorSpy, times(1)).updateConfiguration(
+ currentUserConfig.getUserId(), requestedChanges, bypassUserPolicyChecks);
+ assertEquals(expectedConfigAfterChange,
+ mTimeDetectorStrategy.getCachedCapabilitiesAndConfigForTests());
+ }
}
@Test
@@ -1939,20 +2040,14 @@
private final List<Runnable> mAsyncRunnables = new ArrayList<>();
- private ConfigurationInternal mConfigurationInternal;
private boolean mWakeLockAcquired;
private long mElapsedRealtimeMillis;
private long mSystemClockMillis;
private int mSystemClockConfidence = TIME_CONFIDENCE_LOW;
- private StateChangeListener mConfigurationInternalChangeListener;
// Tracking operations.
private boolean mSystemClockWasSet;
- void initializeConfig(ConfigurationInternal configurationInternal) {
- mConfigurationInternal = configurationInternal;
- }
-
public void initializeFakeClocks(
TimestampedValue<Instant> timeInfo, @TimeConfidence int timeConfidence) {
pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis());
@@ -1960,16 +2055,6 @@
}
@Override
- public void setConfigurationInternalChangeListener(StateChangeListener listener) {
- mConfigurationInternalChangeListener = Objects.requireNonNull(listener);
- }
-
- @Override
- public ConfigurationInternal getCurrentUserConfigurationInternal() {
- return mConfigurationInternal;
- }
-
- @Override
public void acquireWakeLock() {
if (mWakeLockAcquired) {
fail("Wake lock already acquired");
@@ -2019,7 +2104,7 @@
}
@Override
- public void dumpDebugLog(PrintWriter printWriter) {
+ public void dumpDebugLog(IndentingPrintWriter pw) {
// No-op for tests
}
@@ -2037,11 +2122,6 @@
mAsyncRunnables.clear();
}
- void simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
- mConfigurationInternal = configurationInternal;
- mConfigurationInternalChangeListener.onChange();
- }
-
void pokeElapsedRealtimeMillis(long elapsedRealtimeMillis) {
mElapsedRealtimeMillis = elapsedRealtimeMillis;
}
@@ -2095,13 +2175,6 @@
*/
private class Script {
- private final TimeDetectorStrategyImpl mTimeDetectorStrategy;
-
- Script() {
- mFakeEnvironment = new FakeEnvironment();
- mTimeDetectorStrategy = new TimeDetectorStrategyImpl(mFakeEnvironment);
- }
-
Script pokeFakeClocks(TimestampedValue<Instant> initialClockTime,
@TimeConfidence int timeConfidence) {
mFakeEnvironment.pokeElapsedRealtimeMillis(initialClockTime.getReferenceTimeMillis());
@@ -2122,7 +2195,8 @@
* Simulates the user / user's configuration changing.
*/
Script simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
- mFakeEnvironment.simulateConfigurationInternalChange(configurationInternal);
+ mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+ configurationInternal);
return this;
}
@@ -2167,14 +2241,15 @@
Script simulateAutoTimeDetectionToggle() {
ConfigurationInternal configurationInternal =
- mFakeEnvironment.getCurrentUserConfigurationInternal();
+ mFakeServiceConfigAccessorSpy.getCurrentUserConfigurationInternal();
boolean autoDetectionEnabledSetting =
!configurationInternal.getAutoDetectionEnabledSetting();
ConfigurationInternal newConfigurationInternal =
new ConfigurationInternal.Builder(configurationInternal)
.setAutoDetectionEnabledSetting(autoDetectionEnabledSetting)
.build();
- mFakeEnvironment.simulateConfigurationInternalChange(newConfigurationInternal);
+ mFakeServiceConfigAccessorSpy.simulateCurrentUserConfigurationInternalChange(
+ newConfigurationInternal);
return this;
}
@@ -2389,4 +2464,12 @@
return LocalDateTime.of(year, monthInYear, day, hourOfDay, minute, second)
.toInstant(ZoneOffset.UTC);
}
+
+ private void assertStateChangeNotificationsSent(
+ TestStateChangeListener stateChangeListener, int expectedCount) {
+ // The fake environment needs to be told to run posted work.
+ mFakeEnvironment.runAsyncRunnables();
+
+ stateChangeListener.assertNotificationsReceivedAndReset(expectedCount);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index f158ce1..9d2b34c 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -84,6 +84,7 @@
import android.view.InputDevice;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.FrameworkStatsLog;
@@ -813,6 +814,7 @@
eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString());
}
+ @FlakyTest
@Test
public void vibrate_withOngoingRepeatingVibration_ignoresEffect() throws Exception {
mockVibrators(1);
@@ -899,6 +901,7 @@
cancelVibrate(service); // Clean up repeating effect.
}
+ @FlakyTest
@Test
public void vibrate_withNewSameImportanceVibrationButOngoingIsRepeating_ignoreNewVibration()
throws Exception {
@@ -952,6 +955,7 @@
cancelVibrate(service); // Clean up repeating effect.
}
+ @FlakyTest
@Test
public void vibrate_withNewUnknownUsageVibrationAndNotRepeating_ignoreNewVibration()
throws Exception {
@@ -1687,6 +1691,7 @@
cancelVibrate(service); // Clean up long effect.
}
+ @FlakyTest
@Test
public void onExternalVibration_withNewSameImportanceButRepeating_cancelsOngoingVibration()
throws Exception {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 4290f4b..f5866406 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -242,26 +242,27 @@
displayInfo.copyFrom(mDisplayInfo);
displayInfo.type = Display.TYPE_VIRTUAL;
DisplayContent virtualDisplay = createNewDisplay(displayInfo);
+ final KeyguardController keyguardController = mSupervisor.getKeyguardController();
// Make sure we're starting out with 2 unlocked displays
assertEquals(2, mRootWindowContainer.getChildCount());
mRootWindowContainer.forAllDisplays(displayContent -> {
assertFalse(displayContent.isKeyguardLocked());
- assertFalse(displayContent.isAodShowing());
+ assertFalse(keyguardController.isAodShowing(displayContent.mDisplayId));
});
// Check that setLockScreenShown locks both displays
mAtm.setLockScreenShown(true, true);
mRootWindowContainer.forAllDisplays(displayContent -> {
assertTrue(displayContent.isKeyguardLocked());
- assertTrue(displayContent.isAodShowing());
+ assertTrue(keyguardController.isAodShowing(displayContent.mDisplayId));
});
// Check setLockScreenShown unlocking both displays
mAtm.setLockScreenShown(false, false);
mRootWindowContainer.forAllDisplays(displayContent -> {
assertFalse(displayContent.isKeyguardLocked());
- assertFalse(displayContent.isAodShowing());
+ assertFalse(keyguardController.isAodShowing(displayContent.mDisplayId));
});
}
@@ -275,25 +276,26 @@
displayInfo.displayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
displayInfo.flags = Display.FLAG_OWN_DISPLAY_GROUP | Display.FLAG_ALWAYS_UNLOCKED;
DisplayContent newDisplay = createNewDisplay(displayInfo);
+ final KeyguardController keyguardController = mSupervisor.getKeyguardController();
// Make sure we're starting out with 2 unlocked displays
assertEquals(2, mRootWindowContainer.getChildCount());
mRootWindowContainer.forAllDisplays(displayContent -> {
assertFalse(displayContent.isKeyguardLocked());
- assertFalse(displayContent.isAodShowing());
+ assertFalse(keyguardController.isAodShowing(displayContent.mDisplayId));
});
// setLockScreenShown should only lock the default display, not the virtual one
mAtm.setLockScreenShown(true, true);
assertTrue(mDefaultDisplay.isKeyguardLocked());
- assertTrue(mDefaultDisplay.isAodShowing());
+ assertTrue(keyguardController.isAodShowing(mDefaultDisplay.mDisplayId));
DisplayContent virtualDisplay = mRootWindowContainer.getDisplayContent(
newDisplay.getDisplayId());
assertNotEquals(Display.DEFAULT_DISPLAY, virtualDisplay.getDisplayId());
assertFalse(virtualDisplay.isKeyguardLocked());
- assertFalse(virtualDisplay.isAodShowing());
+ assertFalse(keyguardController.isAodShowing(virtualDisplay.mDisplayId));
}
/*
diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
index bbec091..e1b11f6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
@@ -16,6 +16,11 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -76,6 +81,7 @@
@RunWith(WindowTestRunner.class)
public class ContentRecorderTests extends WindowTestsBase {
private static IBinder sTaskWindowContainerToken;
+ private DisplayContent mVirtualDisplayContent;
private Task mTask;
private final ContentRecordingSession mDisplaySession =
ContentRecordingSession.createDisplaySession(DEFAULT_DISPLAY);
@@ -106,11 +112,11 @@
displayInfo.logicalWidth = sSurfaceSize.x;
displayInfo.logicalHeight = sSurfaceSize.y;
displayInfo.state = STATE_ON;
- final DisplayContent virtualDisplayContent = createNewDisplay(displayInfo);
- final int displayId = virtualDisplayContent.getDisplayId();
- mContentRecorder = new ContentRecorder(virtualDisplayContent,
+ mVirtualDisplayContent = createNewDisplay(displayInfo);
+ final int displayId = mVirtualDisplayContent.getDisplayId();
+ mContentRecorder = new ContentRecorder(mVirtualDisplayContent,
mMediaProjectionManagerWrapper);
- spyOn(virtualDisplayContent);
+ spyOn(mVirtualDisplayContent);
// GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
// record.
@@ -118,7 +124,7 @@
mDisplaySession.setDisplayToRecord(mDefaultDisplay.mDisplayId);
// GIVEN there is a window token associated with a task to record.
- sTaskWindowContainerToken = setUpTaskWindowContainerToken(virtualDisplayContent);
+ sTaskWindowContainerToken = setUpTaskWindowContainerToken(mVirtualDisplayContent);
mTaskSession = ContentRecordingSession.createTaskSession(sTaskWindowContainerToken);
mTaskSession.setVirtualDisplayId(displayId);
@@ -251,7 +257,11 @@
public void testOnConfigurationChanged_resizesSurface() {
mContentRecorder.setContentRecordingSession(mDisplaySession);
mContentRecorder.updateRecording();
- mContentRecorder.onConfigurationChanged(ORIENTATION_PORTRAIT);
+ // Ensure a different orientation when we check if something has changed.
+ @Configuration.Orientation final int lastOrientation =
+ mDisplayContent.getConfiguration().orientation == ORIENTATION_PORTRAIT
+ ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
+ mContentRecorder.onConfigurationChanged(lastOrientation);
verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(),
anyFloat());
@@ -260,12 +270,77 @@
}
@Test
+ public void testOnConfigurationChanged_resizesVirtualDisplay() {
+ final int newWidth = 55;
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
+ mContentRecorder.updateRecording();
+
+ // The user rotates the device, so the host app resizes the virtual display for the capture.
+ resizeDisplay(mDisplayContent, newWidth, sSurfaceSize.y);
+ resizeDisplay(mVirtualDisplayContent, newWidth, sSurfaceSize.y);
+ mContentRecorder.onConfigurationChanged(mDisplayContent.getConfiguration().orientation);
+
+ verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(),
+ anyFloat());
+ verify(mTransaction, atLeast(2)).setMatrix(eq(mRecordedSurface), anyFloat(), anyFloat(),
+ anyFloat(), anyFloat());
+ }
+
+ @Test
+ public void testOnConfigurationChanged_rotateVirtualDisplay() {
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
+ mContentRecorder.updateRecording();
+
+ // Change a value that we shouldn't rely upon; it has the wrong type.
+ mVirtualDisplayContent.setOverrideOrientation(SCREEN_ORIENTATION_FULL_SENSOR);
+ mContentRecorder.onConfigurationChanged(
+ mVirtualDisplayContent.getConfiguration().orientation);
+
+ // No resize is issued, only the initial transformations when we started recording.
+ verify(mTransaction).setPosition(eq(mRecordedSurface), anyFloat(),
+ anyFloat());
+ verify(mTransaction).setMatrix(eq(mRecordedSurface), anyFloat(), anyFloat(),
+ anyFloat(), anyFloat());
+ }
+
+ /**
+ * Test that resizing the output surface results in resizing the mirrored content to fit.
+ */
+ @Test
+ public void testOnConfigurationChanged_resizeSurface() {
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
+ mContentRecorder.updateRecording();
+
+ // Resize the output surface.
+ final Point newSurfaceSize = new Point(Math.round(sSurfaceSize.x / 2f),
+ Math.round(sSurfaceSize.y * 2));
+ doReturn(newSurfaceSize).when(mWm.mDisplayManagerInternal).getDisplaySurfaceDefaultSize(
+ anyInt());
+ mContentRecorder.onConfigurationChanged(
+ mVirtualDisplayContent.getConfiguration().orientation);
+
+ // No resize is issued, only the initial transformations when we started recording.
+ verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(),
+ anyFloat());
+ verify(mTransaction, atLeast(2)).setMatrix(eq(mRecordedSurface), anyFloat(), anyFloat(),
+ anyFloat(), anyFloat());
+
+ }
+
+ @Test
public void testOnTaskOrientationConfigurationChanged_resizesSurface() {
mContentRecorder.setContentRecordingSession(mTaskSession);
mContentRecorder.updateRecording();
Configuration config = mTask.getConfiguration();
- config.orientation = ORIENTATION_PORTRAIT;
+ // Ensure a different orientation when we compare.
+ @Configuration.Orientation final int orientation =
+ config.orientation == ORIENTATION_PORTRAIT ? ORIENTATION_LANDSCAPE
+ : ORIENTATION_PORTRAIT;
+ final Rect lastBounds = config.windowConfiguration.getBounds();
+ config.orientation = orientation;
+ config.windowConfiguration.setBounds(
+ new Rect(0, 0, lastBounds.height(), lastBounds.width()));
mTask.onConfigurationChanged(config);
verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(),
@@ -278,13 +353,15 @@
public void testOnTaskBoundsConfigurationChanged_notifiesCallback() {
mTask.getRootTask().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
+ final int minWidth = 222;
+ final int minHeight = 777;
final int recordedWidth = 333;
final int recordedHeight = 999;
final ActivityInfo info = new ActivityInfo();
info.windowLayout = new ActivityInfo.WindowLayout(-1 /* width */,
-1 /* widthFraction */, -1 /* height */, -1 /* heightFraction */,
- Gravity.NO_GRAVITY, recordedWidth, recordedHeight);
+ Gravity.NO_GRAVITY, minWidth, minHeight);
mTask.setMinDimensions(info);
// WHEN a recording is ongoing.
@@ -310,6 +387,39 @@
}
@Test
+ public void testTaskWindowingModeChanged_pip_stopsRecording() {
+ // WHEN a recording is ongoing.
+ mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ mContentRecorder.setContentRecordingSession(mTaskSession);
+ mContentRecorder.updateRecording();
+ assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
+
+ // WHEN a configuration change arrives, and the task is now pinned.
+ mTask.setWindowingMode(WINDOWING_MODE_PINNED);
+ Configuration configuration = mTask.getConfiguration();
+ mTask.onConfigurationChanged(configuration);
+
+ // THEN recording is paused.
+ assertThat(mContentRecorder.isCurrentlyRecording()).isFalse();
+ }
+
+ @Test
+ public void testTaskWindowingModeChanged_fullscreen_startsRecording() {
+ // WHEN a recording is ongoing.
+ mTask.setWindowingMode(WINDOWING_MODE_PINNED);
+ mContentRecorder.setContentRecordingSession(mTaskSession);
+ mContentRecorder.updateRecording();
+ assertThat(mContentRecorder.isCurrentlyRecording()).isFalse();
+
+ // WHEN the task is now fullscreen.
+ mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ mContentRecorder.updateRecording();
+
+ // THEN recording is started.
+ assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
+ }
+
+ @Test
public void testStartRecording_notifiesCallback_taskSession() {
// WHEN a recording is ongoing.
mContentRecorder.setContentRecordingSession(mTaskSession);
@@ -334,6 +444,45 @@
}
@Test
+ public void testStartRecording_taskInPIP_recordingNotStarted() {
+ // GIVEN a task is in PIP.
+ mContentRecorder.setContentRecordingSession(mTaskSession);
+ mTask.setWindowingMode(WINDOWING_MODE_PINNED);
+
+ // WHEN a recording tries to start.
+ mContentRecorder.updateRecording();
+
+ // THEN recording does not start.
+ assertThat(mContentRecorder.isCurrentlyRecording()).isFalse();
+ }
+
+ @Test
+ public void testStartRecording_taskInSplit_recordingStarted() {
+ // GIVEN a task is in PIP.
+ mContentRecorder.setContentRecordingSession(mTaskSession);
+ mTask.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+
+ // WHEN a recording tries to start.
+ mContentRecorder.updateRecording();
+
+ // THEN recording does not start.
+ assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
+ }
+
+ @Test
+ public void testStartRecording_taskInFullscreen_recordingStarted() {
+ // GIVEN a task is in PIP.
+ mContentRecorder.setContentRecordingSession(mTaskSession);
+ mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+ // WHEN a recording tries to start.
+ mContentRecorder.updateRecording();
+
+ // THEN recording does not start.
+ assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
+ }
+
+ @Test
public void testOnVisibleRequestedChanged_notifiesCallback() {
// WHEN a recording is ongoing.
mContentRecorder.setContentRecordingSession(mTaskSession);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index dd90e04..bf86563 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR;
import static android.view.DisplayCutout.NO_CUTOUT;
import static android.view.InsetsSource.ID_IME;
import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
@@ -427,11 +428,11 @@
@SetupWindows(addWindows = { W_NAVIGATION_BAR, W_INPUT_METHOD })
@Test
public void testImeMinimalSourceFrame() {
+ Assume.assumeFalse("Behavior no longer needed with ENABLE_HIDE_IME_CAPTION_BAR",
+ ENABLE_HIDE_IME_CAPTION_BAR);
+
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
- final DisplayInfo displayInfo = new DisplayInfo();
- displayInfo.logicalWidth = 1000;
- displayInfo.logicalHeight = 2000;
- displayInfo.rotation = ROTATION_0;
+ final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
WindowManager.LayoutParams attrs = mNavBarWindow.mAttrs;
displayPolicy.addWindowLw(mNavBarWindow, attrs);
@@ -466,10 +467,6 @@
@Test
public void testImeInsetsGivenContentFrame() {
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
- final DisplayInfo displayInfo = new DisplayInfo();
- displayInfo.logicalWidth = 1000;
- displayInfo.logicalHeight = 2000;
- displayInfo.rotation = ROTATION_0;
mDisplayContent.setInputMethodWindowLocked(mImeWindow);
mImeWindow.getControllableInsetProvider().setServerVisible(true);
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 994dcf1..ffa1ed9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -23,8 +23,6 @@
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
@@ -108,7 +106,7 @@
@Test
public void testControlsForDispatch_forceStatusBarVisible() {
- addStatusBar().mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
+ addStatusBar().mAttrs.forciblyShownTypes |= statusBars();
addNavigationBar();
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -120,8 +118,8 @@
@Test
public void testControlsForDispatch_statusBarForceShowNavigation() {
- addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.privateFlags |=
- PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
+ addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.forciblyShownTypes |=
+ navigationBars();
addStatusBar();
addNavigationBar();
@@ -135,7 +133,7 @@
@Test
public void testControlsForDispatch_statusBarForceShowNavigation_butFocusedAnyways() {
WindowState notifShade = addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade");
- notifShade.mAttrs.privateFlags |= PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
+ notifShade.mAttrs.forciblyShownTypes |= navigationBars();
addNavigationBar();
mDisplayContent.getInsetsPolicy().updateBarControlTarget(notifShade);
@@ -329,6 +327,7 @@
addNavigationBar().getControllableInsetProvider().getSource();
statusBarSource.setVisible(false);
navBarSource.setVisible(false);
+ mAppWindow.setRequestedVisibleTypes(0, navigationBars() | statusBars());
mAppWindow.mAboveInsetsState.addSource(navBarSource);
mAppWindow.mAboveInsetsState.addSource(statusBarSource);
final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
@@ -389,6 +388,50 @@
assertFalse(policy.isTransient(navigationBars()));
}
+ @Test
+ public void testFakeControlTarget_overrideVisibilityReceivedByWindows() {
+ final WindowState statusBar = addStatusBar();
+ final InsetsSourceProvider statusBarProvider = statusBar.getControllableInsetProvider();
+ statusBar.mSession.mCanForceShowingInsets = true;
+ statusBar.setHasSurface(true);
+ statusBarProvider.setServerVisible(true);
+
+ final InsetsSource statusBarSource = statusBarProvider.getSource();
+ final int statusBarId = statusBarSource.getId();
+ assertTrue(statusBarSource.isVisible());
+
+ final WindowState app1 = addWindow(TYPE_APPLICATION, "app1");
+ app1.mAboveInsetsState.addSource(statusBarSource);
+ assertTrue(app1.getInsetsState().peekSource(statusBarId).isVisible());
+
+ final WindowState app2 = addWindow(TYPE_APPLICATION, "app2");
+ app2.mAboveInsetsState.addSource(statusBarSource);
+ assertTrue(app2.getInsetsState().peekSource(statusBarId).isVisible());
+
+ app2.setRequestedVisibleTypes(0, navigationBars() | statusBars());
+ mDisplayContent.getInsetsPolicy().updateBarControlTarget(app2);
+ waitUntilWindowAnimatorIdle();
+
+ // app2 is the real control target now. It can override the visibility of all sources that
+ // it controls.
+ assertFalse(statusBarSource.isVisible());
+ assertFalse(app1.getInsetsState().peekSource(statusBarId).isVisible());
+ assertFalse(app2.getInsetsState().peekSource(statusBarId).isVisible());
+
+ statusBar.mAttrs.forciblyShownTypes = statusBars();
+ mDisplayContent.getDisplayPolicy().applyPostLayoutPolicyLw(
+ statusBar, statusBar.mAttrs, null, null);
+ mDisplayContent.getInsetsPolicy().updateBarControlTarget(app2);
+ waitUntilWindowAnimatorIdle();
+
+ // app2 is the fake control target now. It can only override the visibility of sources
+ // received by windows, but not the raw source.
+ assertTrue(statusBarSource.isVisible());
+ assertFalse(app1.getInsetsState().peekSource(statusBarId).isVisible());
+ assertFalse(app2.getInsetsState().peekSource(statusBarId).isVisible());
+
+ }
+
private WindowState addNavigationBar() {
final Binder owner = new Binder();
final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 114796d..2085d61 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -367,9 +367,11 @@
doReturn(rotatedState).when(app.mToken).getFixedRotationTransformInsetsState();
assertTrue(rotatedState.isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars()));
- provider.getSource().setVisible(false);
+ app.setRequestedVisibleTypes(0, statusBars());
+ mDisplayContent.getInsetsPolicy().updateBarControlTarget(app);
mDisplayContent.getInsetsPolicy().showTransient(statusBars(),
true /* isGestureOnSystemBar */);
+ waitUntilWindowAnimatorIdle();
assertTrue(mDisplayContent.getInsetsPolicy().isTransient(statusBars()));
assertFalse(app.getInsetsState().isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars()));
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java
index 06033c7..3fcec96 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java
@@ -184,7 +184,7 @@
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT);
firstPersister.setLetterboxPositionForVerticalReachability(false,
LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
- waitForCompletion(mPersisterQueue);
+ waitForCompletion(firstPersisterQueue);
final int newPositionForHorizontalReachability =
firstPersister.getLetterboxPositionForHorizontalReachability(false);
final int newPositionForVerticalReachability =
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 2ad9fa0..381b27b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -811,6 +811,28 @@
/* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_PORTRAIT);
}
+ @Test
+ public void testOverrideOrientationIfNeeded_userAspectRatioApplied_unspecifiedOverridden() {
+ spyOn(mController);
+ doReturn(true).when(mController).shouldApplyUserMinAspectRatioOverride();
+
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_PORTRAIT);
+
+ // unchanged if orientation is specified
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_LANDSCAPE), SCREEN_ORIENTATION_LANDSCAPE);
+ }
+
+ @Test
+ public void testOverrideOrientationIfNeeded_userAspectRatioNotApplied_returnsUnchanged() {
+ spyOn(mController);
+ doReturn(false).when(mController).shouldApplyUserMinAspectRatioOverride();
+
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
+ }
+
// shouldApplyUser...Override
@Test
public void testShouldApplyUserFullscreenOverride_trueProperty_returnsFalse() throws Exception {
@@ -862,6 +884,39 @@
}
@Test
+ public void testShouldEnableUserAspectRatioSettings_falseProperty_returnsFalse()
+ throws Exception {
+ prepareActivityThatShouldApplyUserMinAspectRatioOverride();
+ mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, /* value */ false);
+
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertFalse(mController.shouldEnableUserAspectRatioSettings());
+ }
+
+ @Test
+ public void testShouldEnableUserAspectRatioSettings_trueProperty_returnsTrue()
+ throws Exception {
+ prepareActivityThatShouldApplyUserMinAspectRatioOverride();
+ mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, /* value */ true);
+
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertTrue(mController.shouldEnableUserAspectRatioSettings());
+ }
+
+ @Test
+ public void testShouldEnableUserAspectRatioSettings_noIgnoreOrientaion_returnsFalse()
+ throws Exception {
+ prepareActivityForShouldApplyUserMinAspectRatioOverride(/* orientationRequest */ false);
+ mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, /* value */ true);
+
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertFalse(mController.shouldEnableUserAspectRatioSettings());
+ }
+
+ @Test
public void testShouldApplyUserMinAspectRatioOverride_falseProperty_returnsFalse()
throws Exception {
prepareActivityThatShouldApplyUserMinAspectRatioOverride();
@@ -898,13 +953,26 @@
assertTrue(mController.shouldApplyUserMinAspectRatioOverride());
}
- private void prepareActivityThatShouldApplyUserMinAspectRatioOverride() {
+ @Test
+ public void testShouldApplyUserMinAspectRatioOverride_noIgnoreOrientationreturnsFalse() {
+ prepareActivityForShouldApplyUserMinAspectRatioOverride(/* orientationRequest */ false);
+
+ assertFalse(mController.shouldApplyUserMinAspectRatioOverride());
+ }
+
+ private void prepareActivityForShouldApplyUserMinAspectRatioOverride(
+ boolean orientationRequest) {
spyOn(mController);
- doReturn(true).when(mLetterboxConfiguration).isUserAppAspectRatioSettingsEnabled();
+ doReturn(orientationRequest).when(
+ mLetterboxConfiguration).isUserAppAspectRatioSettingsEnabled();
mDisplayContent.setIgnoreOrientationRequest(true);
doReturn(USER_MIN_ASPECT_RATIO_3_2).when(mController).getUserMinAspectRatioOverrideCode();
}
+ private void prepareActivityThatShouldApplyUserMinAspectRatioOverride() {
+ prepareActivityForShouldApplyUserMinAspectRatioOverride(/* orientationRequest */ true);
+ }
+
private void prepareActivityThatShouldApplyUserFullscreenOverride() {
spyOn(mController);
doReturn(true).when(mLetterboxConfiguration).isUserAppAspectRatioFullscreenEnabled();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index d5afe3b..03e0401 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -2404,8 +2404,9 @@
.setUid(android.os.Process.myUid())
.build();
activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
- activity.mWmService.mLetterboxConfiguration
- .setUserAppAspectRatioSettingsOverrideEnabled(enabled);
+ spyOn(activity.mWmService.mLetterboxConfiguration);
+ doReturn(enabled).when(activity.mWmService.mLetterboxConfiguration)
+ .isUserAppAspectRatioSettingsEnabled();
// Set user aspect ratio override
final IPackageManager pm = mAtm.getPackageManager();
try {
@@ -4244,6 +4245,7 @@
// Set up a display in landscape with a fixed-orientation PORTRAIT app
setUpDisplaySizeWithApp(2800, 1400);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mWm.mLetterboxConfiguration.setIsAutomaticReachabilityInBookModeEnabled(false);
mWm.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(0.5f);
prepareUnresizable(mActivity, 1.75f, SCREEN_ORIENTATION_PORTRAIT);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index f332b69..09b56f4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -571,26 +571,28 @@
final Task task = rootTask.getBottomMostTask();
final ActivityRecord root = task.getTopNonFinishingActivity();
spyOn(mWm.mLetterboxConfiguration);
-
- // When device config flag is disabled the button is not enabled
- doReturn(false).when(mWm.mLetterboxConfiguration)
- .isUserAppAspectRatioSettingsEnabled();
- doReturn(false).when(mWm.mLetterboxConfiguration)
- .isTranslucentLetterboxingEnabled();
- assertFalse(task.getTaskInfo().topActivityEligibleForUserAspectRatioButton);
-
- // The flag is enabled
- doReturn(true).when(mWm.mLetterboxConfiguration)
- .isUserAppAspectRatioSettingsEnabled();
spyOn(root);
- doReturn(task).when(root).getOrganizedTask();
- // When the flag is enabled and the top activity is not in size compat mode.
+ spyOn(root.mLetterboxUiController);
+
+ doReturn(true).when(root.mLetterboxUiController)
+ .shouldEnableUserAspectRatioSettings();
doReturn(false).when(root).inSizeCompatMode();
+ doReturn(task).when(root).getOrganizedTask();
+
+ // The button should be eligible to be displayed
assertTrue(task.getTaskInfo().topActivityEligibleForUserAspectRatioButton);
+ // When shouldApplyUserMinAspectRatioOverride is disable the button is not enabled
+ doReturn(false).when(root.mLetterboxUiController)
+ .shouldEnableUserAspectRatioSettings();
+ assertFalse(task.getTaskInfo().topActivityEligibleForUserAspectRatioButton);
+ doReturn(true).when(root.mLetterboxUiController)
+ .shouldEnableUserAspectRatioSettings();
+
// When in size compat mode the button is not enabled
doReturn(true).when(root).inSizeCompatMode();
assertFalse(task.getTaskInfo().topActivityEligibleForUserAspectRatioButton);
+ doReturn(false).when(root).inSizeCompatMode();
}
/**
diff --git a/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java b/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java
index 9015563..2411498 100644
--- a/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java
+++ b/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java
@@ -63,6 +63,12 @@
public void createSession(String engine,
ITextToSpeechSessionCallback sessionCallback) {
synchronized (mLock) {
+ if (engine == null) {
+ runSessionCallbackMethod(
+ () -> sessionCallback.onError("Engine cannot be null"));
+ return;
+ }
+
TextToSpeechManagerPerUserService perUserService = getServiceForUserLocked(
UserHandle.getCallingUserId());
if (perUserService != null) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 361b1c0..7005e4d 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -22,6 +22,7 @@
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.os.Build;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -1557,6 +1558,13 @@
}
}
+ void deleteDataFor(String pkg) {
+ // reuse the existing prune method to delete data for the specified package.
+ // we'll use the current timestamp so that all events before now get pruned.
+ prunePackagesDataOnUpgrade(
+ new HashMap<>(Collections.singletonMap(pkg, SystemClock.elapsedRealtime())));
+ }
+
IntervalStats readIntervalStatsForFile(int interval, long fileName) {
synchronized (mLock) {
final IntervalStats stats = new IntervalStats();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index cf236dd..d89a626 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -2043,6 +2043,12 @@
mAppStandby.clearLastUsedTimestampsForTest(packageName, userId);
}
+ void deletePackageData(@NonNull String packageName, @UserIdInt int userId) {
+ synchronized (mLock) {
+ mUserState.get(userId).deleteDataFor(packageName);
+ }
+ }
+
private final class BinderService extends IUsageStatsManager.Stub {
private boolean hasPermission(String callingPackage) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsShellCommand.java b/services/usage/java/com/android/server/usage/UsageStatsShellCommand.java
index 772b22a..4cb31f9 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsShellCommand.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsShellCommand.java
@@ -38,6 +38,8 @@
switch (cmd) {
case "clear-last-used-timestamps":
return runClearLastUsedTimestamps();
+ case "delete-package-data":
+ return deletePackageData();
default:
return handleDefaultCommands(cmd);
}
@@ -51,14 +53,38 @@
pw.println(" Print this help text.");
pw.println();
pw.println("clear-last-used-timestamps PACKAGE_NAME [-u | --user USER_ID]");
- pw.println(" Clears any existing usage data for the given package.");
+ pw.println(" Clears the last used timestamps for the given package.");
+ pw.println();
+ pw.println("delete-package-data PACKAGE_NAME [-u | --user USER_ID]");
+ pw.println(" Deletes all the usage stats for the given package.");
pw.println();
}
@SuppressLint("AndroidFrameworkRequiresPermission")
private int runClearLastUsedTimestamps() {
final String packageName = getNextArgRequired();
+ final int userId = getUserId();
+ if (userId == -1) {
+ return -1;
+ }
+ mService.clearLastUsedTimestamps(packageName, userId);
+ return 0;
+ }
+
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ private int deletePackageData() {
+ final String packageName = getNextArgRequired();
+ final int userId = getUserId();
+ if (userId == -1) {
+ return -1;
+ }
+
+ mService.deletePackageData(packageName, userId);
+ return 0;
+ }
+
+ private int getUserId() {
int userId = UserHandle.USER_CURRENT;
String opt;
while ((opt = getNextOption()) != null) {
@@ -72,8 +98,6 @@
if (userId == UserHandle.USER_CURRENT) {
userId = ActivityManager.getCurrentUser();
}
-
- mService.clearLastUsedTimestamps(packageName, userId);
- return 0;
+ return userId;
}
}
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 9203208..a6d2206 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -974,6 +974,10 @@
mDatabase.dumpMappings(ipw);
}
+ void deleteDataFor(String pkg) {
+ mDatabase.deleteDataFor(pkg);
+ }
+
void dumpFile(IndentingPrintWriter ipw, String[] args) {
if (args == null || args.length == 0) {
// dump all files for every interval for specified user
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 3d78a1d..0a70a5f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -27,9 +27,9 @@
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__SERVICE_CRASH;
-import android.app.AppOpsManager;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
import android.content.ComponentName;
@@ -50,6 +50,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SharedMemory;
+import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.service.voice.HotwordDetectionService;
import android.service.voice.HotwordDetectionServiceFailure;
@@ -114,6 +115,9 @@
private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour
private static final int MAX_ISOLATED_PROCESS_NUMBER = 10;
+ private static final boolean SYSPROP_VISUAL_QUERY_SERVICE_ENABLED =
+ SystemProperties.getBoolean("ro.hotword.visual_query_service_enabled", false);
+
/**
* Indicates the {@link HotwordDetectionService} is created.
*/
@@ -680,7 +684,8 @@
mIntent = intent;
mDetectionServiceType = detectionServiceType;
int flags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0;
- if (mVisualQueryDetectionComponentName != null
+ if (SYSPROP_VISUAL_QUERY_SERVICE_ENABLED
+ && mVisualQueryDetectionComponentName != null
&& mHotwordDetectionComponentName != null) {
flags |= Context.BIND_SHARED_ISOLATED_PROCESS;
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 471acc1..6ba77da 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -57,6 +57,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SharedMemory;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.service.voice.HotwordDetector;
import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
@@ -96,6 +97,8 @@
/** The delay time for retrying to request DirectActions. */
private static final long REQUEST_DIRECT_ACTIONS_RETRY_TIME_MS = 200;
+ private static final boolean SYSPROP_VISUAL_QUERY_SERVICE_ENABLED =
+ SystemProperties.getBoolean("ro.hotword.visual_query_service_enabled", false);
final boolean mValid;
@@ -715,7 +718,7 @@
} else {
verifyDetectorForVisualQueryDetectionLocked(sharedMemory);
}
- if (!verifyProcessSharingLocked()) {
+ if (SYSPROP_VISUAL_QUERY_SERVICE_ENABLED && !verifyProcessSharingLocked()) {
Slog.w(TAG, "Sandboxed detection service not in shared isolated process");
throw new IllegalStateException("VisualQueryDetectionService or HotworDetectionService "
+ "not in a shared isolated process. Please make sure to set "
@@ -914,6 +917,7 @@
if (hotwordInfo == null || visualQueryInfo == null) {
return true;
}
+ // Enforce shared isolated option is used when VisualQueryDetectionservice is enabled
return (hotwordInfo.flags & ServiceInfo.FLAG_ALLOW_SHARED_ISOLATED_PROCESS) != 0
&& (visualQueryInfo.flags & ServiceInfo.FLAG_ALLOW_SHARED_ISOLATED_PROCESS) != 0;
}
diff --git a/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationPerUserService.java b/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationPerUserService.java
index 3870dfd..4f99f14 100644
--- a/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationPerUserService.java
+++ b/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationPerUserService.java
@@ -95,21 +95,29 @@
String newTaskId = cinematicEffectRequest.getTaskId();
// Previous request is still being processed.
if (mCinematicEffectListenerWrapper != null) {
+ CinematicEffectResponse cinematicEffectResponse;
if (mCinematicEffectListenerWrapper.mTaskId.equals(newTaskId)) {
- invokeCinematicListenerAndCleanup(
- new CinematicEffectResponse.Builder(
- CinematicEffectResponse.CINEMATIC_EFFECT_STATUS_PENDING, newTaskId)
- .build()
- );
+ cinematicEffectResponse = new CinematicEffectResponse.Builder(
+ CinematicEffectResponse.CINEMATIC_EFFECT_STATUS_PENDING, newTaskId)
+ .build();
} else {
- invokeCinematicListenerAndCleanup(
- new CinematicEffectResponse.Builder(
- CinematicEffectResponse.CINEMATIC_EFFECT_STATUS_TOO_MANY_REQUESTS,
- newTaskId).build()
- );
+ cinematicEffectResponse = new CinematicEffectResponse.Builder(
+ CinematicEffectResponse.CINEMATIC_EFFECT_STATUS_TOO_MANY_REQUESTS,
+ newTaskId)
+ .build();
}
- return;
+ try {
+ cinematicEffectListener.onCinematicEffectGenerated(cinematicEffectResponse);
+ return;
+ } catch (RemoteException e) {
+ if (isDebug()) {
+ Slog.w(TAG, "RemoteException invoking cinematic effect listener for task["
+ + mCinematicEffectListenerWrapper.mTaskId + "]");
+ }
+ return;
+ }
}
+
RemoteWallpaperEffectsGenerationService remoteService = ensureRemoteServiceLocked();
if (remoteService != null) {
remoteService.executeOnResolvedService(
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 60d640c..fbb2eb9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -10182,7 +10182,7 @@
sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
sDefaults.putInt(KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 0);
sDefaults.putBoolean(KEY_INCLUDE_LTE_FOR_NR_ADVANCED_THRESHOLD_BANDWIDTH_BOOL, false);
- sDefaults.putBoolean(KEY_RATCHET_NR_ADVANCED_BANDWIDTH_IF_RRC_IDLE_BOOL, true);
+ sDefaults.putBoolean(KEY_RATCHET_NR_ADVANCED_BANDWIDTH_IF_RRC_IDLE_BOOL, false);
sDefaults.putIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
new int[]{CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA});
sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
index d41c019..bc41829 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
@@ -23,9 +23,11 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Resources;
import android.net.wifi.sharedconnectivity.service.ISharedConnectivityCallback;
@@ -35,6 +37,7 @@
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
@@ -67,7 +70,7 @@
@SystemApi
public class SharedConnectivityManager {
private static final String TAG = SharedConnectivityManager.class.getSimpleName();
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static final class SharedConnectivityCallbackProxy extends
ISharedConnectivityCallback.Stub {
@@ -172,6 +175,7 @@
private final String mServicePackageName;
private final String mIntentAction;
private ServiceConnection mServiceConnection;
+ private UserManager mUserManager;
/**
* Creates a new instance of {@link SharedConnectivityManager}.
@@ -217,12 +221,14 @@
mContext = context;
mServicePackageName = servicePackageName;
mIntentAction = serviceIntentAction;
+ mUserManager = context.getSystemService(UserManager.class);
}
private void bind() {
mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) Log.i(TAG, "onServiceConnected");
mService = ISharedConnectivityService.Stub.asInterface(service);
synchronized (mProxyDataLock) {
if (!mCallbackProxyCache.isEmpty()) {
@@ -253,9 +259,45 @@
}
};
- mContext.bindService(
+ boolean result = mContext.bindService(
new Intent().setPackage(mServicePackageName).setAction(mIntentAction),
mServiceConnection, Context.BIND_AUTO_CREATE);
+ if (!result) {
+ if (DEBUG) Log.i(TAG, "bindService failed");
+ mServiceConnection = null;
+ if (mUserManager != null && !mUserManager.isUserUnlocked()) { // In direct boot mode
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
+ mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+ } else {
+ synchronized (mProxyDataLock) {
+ if (!mCallbackProxyCache.isEmpty()) {
+ mCallbackProxyCache.keySet().forEach(
+ callback -> callback.onRegisterCallbackFailed(
+ new IllegalStateException(
+ "Failed to bind after user unlock")));
+ mCallbackProxyCache.clear();
+ }
+ }
+ }
+ }
+ }
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ context.unregisterReceiver(mBroadcastReceiver);
+ bind();
+ }
+ };
+
+ /**
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ public BroadcastReceiver getBroadcastReceiver() {
+ return mBroadcastReceiver;
}
private void registerCallbackInternal(SharedConnectivityClientCallback callback,
@@ -357,6 +399,13 @@
return false;
}
+ // Try to unregister the broadcast receiver to guard against memory leaks.
+ try {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ } catch (IllegalArgumentException e) {
+ // This is fine, it means the receiver was never registered or was already unregistered.
+ }
+
if (mService == null) {
boolean shouldUnbind;
synchronized (mProxyDataLock) {