diff options
230 files changed, 4704 insertions, 1567 deletions
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 07fbde546cbc..4188a7ef35c1 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -16,6 +16,7 @@ package android.app; +import static android.Manifest.permission.CONTROL_KEYGUARD; import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; @@ -371,9 +372,8 @@ public class ActivityOptions extends ComponentOptions { private static final String KEY_LAUNCH_INTO_PIP_PARAMS = "android.activity.launchIntoPipParams"; - /** See {@link #setDismissKeyguardIfInsecure()}. */ - private static final String KEY_DISMISS_KEYGUARD_IF_INSECURE = - "android.activity.dismissKeyguardIfInsecure"; + /** See {@link #setDismissKeyguard()}. */ + private static final String KEY_DISMISS_KEYGUARD = "android.activity.dismissKeyguard"; private static final String KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE = "android.activity.ignorePendingIntentCreatorForegroundState"; @@ -475,7 +475,7 @@ public class ActivityOptions extends ComponentOptions { private boolean mLaunchedFromBubble; private boolean mTransientLaunch; private PictureInPictureParams mLaunchIntoPipParams; - private boolean mDismissKeyguardIfInsecure; + private boolean mDismissKeyguard; private boolean mIgnorePendingIntentCreatorForegroundState; /** @@ -1282,7 +1282,7 @@ public class ActivityOptions extends ComponentOptions { mLaunchIntoPipParams = opts.getParcelable(KEY_LAUNCH_INTO_PIP_PARAMS); mIsEligibleForLegacyPermissionPrompt = opts.getBoolean(KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE); - mDismissKeyguardIfInsecure = opts.getBoolean(KEY_DISMISS_KEYGUARD_IF_INSECURE); + mDismissKeyguard = opts.getBoolean(KEY_DISMISS_KEYGUARD); mIgnorePendingIntentCreatorForegroundState = opts.getBoolean( KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE); } @@ -1903,24 +1903,24 @@ public class ActivityOptions extends ComponentOptions { } /** - * Sets whether the insecure keyguard should go away when this activity launches. In case the - * keyguard is secure, this option will be ignored. + * Sets whether the keyguard should go away when this activity launches. * * @see Activity#setShowWhenLocked(boolean) * @see android.R.attr#showWhenLocked * @hide */ - public void setDismissKeyguardIfInsecure() { - mDismissKeyguardIfInsecure = true; + @RequiresPermission(CONTROL_KEYGUARD) + public void setDismissKeyguard() { + mDismissKeyguard = true; } /** - * @see #setDismissKeyguardIfInsecure() + * @see #setDismissKeyguard() * @return whether the insecure keyguard should go away when the activity launches. * @hide */ - public boolean getDismissKeyguardIfInsecure() { - return mDismissKeyguardIfInsecure; + public boolean getDismissKeyguard() { + return mDismissKeyguard; } /** @@ -2204,8 +2204,8 @@ public class ActivityOptions extends ComponentOptions { b.putBoolean(KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE, mIsEligibleForLegacyPermissionPrompt); } - if (mDismissKeyguardIfInsecure) { - b.putBoolean(KEY_DISMISS_KEYGUARD_IF_INSECURE, mDismissKeyguardIfInsecure); + if (mDismissKeyguard) { + b.putBoolean(KEY_DISMISS_KEYGUARD, mDismissKeyguard); } if (mIgnorePendingIntentCreatorForegroundState) { b.putBoolean(KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE, diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java index 691690c09e0e..5b1973ad2dd4 100644 --- a/core/java/android/hardware/camera2/CameraCaptureSession.java +++ b/core/java/android/hardware/camera2/CameraCaptureSession.java @@ -1234,6 +1234,42 @@ public abstract class CameraCaptureSession implements AutoCloseable { } /** + * This method is called when the camera device has started reading out the output + * image for the request, at the beginning of the sensor image readout. + * + * <p>For a capture request, this callback is invoked right after + * {@link #onCaptureStarted}. Unlike {@link #onCaptureStarted}, instead of passing + * a timestamp of start of exposure, this callback passes a timestamp of start of + * camera data readout. This is useful because for a camera running at fixed frame + * rate, the start of readout is at fixed interval, which is not necessarily true for + * the start of exposure, particularly when autoexposure is changing exposure duration + * between frames.</p> + * + * <p>This timestamp may not match {@link CaptureResult#SENSOR_TIMESTAMP the result + * timestamp field}. It will, however, match the timestamp of buffers sent to the + * output surfaces with {@link OutputConfiguration#TIMESTAMP_BASE_READOUT_SENSOR} + * timestamp base.</p> + * + * <p>This callback will be called only if {@link + * CameraCharacteristics#SENSOR_READOUT_TIMESTAMP} is + * {@link CameraMetadata#SENSOR_READOUT_TIMESTAMP_HARDWARE}, and it's called + * right after {@link #onCaptureStarted}.</p> + * + * @param session the session returned by {@link CameraDevice#createCaptureSession} + * @param request the request for the readout that just began + * @param timestamp the timestamp at start of readout for a regular request, or + * the timestamp at the input image's start of readout for a + * reprocess request, in nanoseconds. + * @param frameNumber the frame number for this capture + * + * @hide + */ + public void onReadoutStarted(@NonNull CameraCaptureSession session, + @NonNull CaptureRequest request, long timestamp, long frameNumber) { + // default empty implementation + } + + /** * This method is called when some results from an image capture are * available. * diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 98a8cbd8a73c..861a8502c44d 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1326,6 +1326,10 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * {@link android.hardware.camera2.CameraManager#turnOnTorchWithStrengthLevel }. * If this value is equal to 1, flashlight brightness control is not supported. * The value for this key will be null for devices with no flash unit.</p> + * <p>The maximum value is guaranteed to be safe to use for an indefinite duration in + * terms of device flashlight lifespan, but may be too bright for comfort for many + * use cases. Use the default torch brightness value to avoid problems with an + * over-bright flashlight.</p> * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> */ @PublicKey @@ -4415,6 +4419,40 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri new Key<android.graphics.Rect[]>("android.sensor.opticalBlackRegions", android.graphics.Rect[].class); /** + * <p>Whether or not the camera device supports readout timestamp and + * onReadoutStarted callback.</p> + * <p>If this tag is HARDWARE, the camera device calls onReadoutStarted in addition to the + * onCaptureStarted callback for each capture. The timestamp passed into the callback + * is the start of camera image readout rather than the start of the exposure. In + * addition, the application can configure an + * {@link android.hardware.camera2.params.OutputConfiguration } with + * TIMESTAMP_BASE_READOUT_SENSOR timestamp base, in which case, the timestamp of the + * output surface matches the timestamp from the corresponding onReadoutStarted callback.</p> + * <p>The readout timestamp is beneficial for video recording, because the encoder favors + * uniform timestamps, and the readout timestamps better reflect the cadence camera sensors + * output data.</p> + * <p>If this tag is HARDWARE, the camera device produces the start-of-exposure and + * start-of-readout together. As a result, the onReadoutStarted is called right after + * onCaptureStarted. The difference in start-of-readout and start-of-exposure is the sensor + * exposure time, plus certain constant offset. The offset is usually due to camera sensor + * level crop, and it remains constant for a given camera sensor mode.</p> + * <p><b>Possible values:</b></p> + * <ul> + * <li>{@link #SENSOR_READOUT_TIMESTAMP_NOT_SUPPORTED NOT_SUPPORTED}</li> + * <li>{@link #SENSOR_READOUT_TIMESTAMP_HARDWARE HARDWARE}</li> + * </ul> + * + * <p>This key is available on all devices.</p> + * @see #SENSOR_READOUT_TIMESTAMP_NOT_SUPPORTED + * @see #SENSOR_READOUT_TIMESTAMP_HARDWARE + * @hide + */ + @PublicKey + @NonNull + public static final Key<Integer> SENSOR_READOUT_TIMESTAMP = + new Key<Integer>("android.sensor.readoutTimestamp", int.class); + + /** * <p>List of lens shading modes for {@link CaptureRequest#SHADING_MODE android.shading.mode} that are supported by this camera device.</p> * <p>This list contains lens shading modes that can be set for the camera device. * Camera devices that support the MANUAL_POST_PROCESSING capability will always diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index eb8c73aced39..c67a560b5885 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -1658,6 +1658,28 @@ public abstract class CameraMetadata<TKey> { public static final int SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN = 24; // + // Enumeration values for CameraCharacteristics#SENSOR_READOUT_TIMESTAMP + // + + /** + * <p>This camera device doesn't support readout timestamp and onReadoutStarted + * callback.</p> + * @see CameraCharacteristics#SENSOR_READOUT_TIMESTAMP + * @hide + */ + public static final int SENSOR_READOUT_TIMESTAMP_NOT_SUPPORTED = 0; + + /** + * <p>This camera device supports the onReadoutStarted callback as well as outputting + * readout timestamp for streams with TIMESTAMP_BASE_READOUT_SENSOR timestamp base. The + * readout timestamp is generated by the camera hardware and it has the same accuracy + * and timing characteristics of the start-of-exposure time.</p> + * @see CameraCharacteristics#SENSOR_READOUT_TIMESTAMP + * @hide + */ + public static final int SENSOR_READOUT_TIMESTAMP_HARDWARE = 1; + + // // Enumeration values for CameraCharacteristics#LED_AVAILABLE_LEDS // diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index 9a9163c724ff..b9eba9c1d541 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -657,6 +657,21 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } @Override + public void onReadoutStarted(CameraDevice camera, + CaptureRequest request, long timestamp, long frameNumber) { + if ((callback != null) && (executor != null)) { + final long ident = Binder.clearCallingIdentity(); + try { + executor.execute(() -> callback.onReadoutStarted( + CameraCaptureSessionImpl.this, request, timestamp, + frameNumber)); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + @Override public void onCapturePartial(CameraDevice camera, CaptureRequest request, android.hardware.camera2.CaptureResult result) { if ((callback != null) && (executor != null)) { diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 3cb0c93d8409..a6c79b3a289f 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -2025,12 +2025,16 @@ public class CameraDeviceImpl extends CameraDevice resultExtras.getLastCompletedReprocessFrameNumber(); final long lastCompletedZslFrameNumber = resultExtras.getLastCompletedZslFrameNumber(); + final boolean hasReadoutTimestamp = resultExtras.hasReadoutTimestamp(); + final long readoutTimestamp = resultExtras.getReadoutTimestamp(); if (DEBUG) { Log.d(TAG, "Capture started for id " + requestId + " frame number " + frameNumber + ": completedRegularFrameNumber " + lastCompletedRegularFrameNumber + ", completedReprocessFrameNUmber " + lastCompletedReprocessFrameNumber - + ", completedZslFrameNumber " + lastCompletedZslFrameNumber); + + ", completedZslFrameNumber " + lastCompletedZslFrameNumber + + ", hasReadoutTimestamp " + hasReadoutTimestamp + + (hasReadoutTimestamp ? ", readoutTimestamp " + readoutTimestamp : "")) ; } final CaptureCallbackHolder holder; @@ -2082,14 +2086,26 @@ public class CameraDeviceImpl extends CameraDevice CameraDeviceImpl.this, holder.getRequest(i), timestamp - (subsequenceId - i) * - NANO_PER_SECOND/fpsRange.getUpper(), + NANO_PER_SECOND / fpsRange.getUpper(), frameNumber - (subsequenceId - i)); + if (hasReadoutTimestamp) { + holder.getCallback().onReadoutStarted( + CameraDeviceImpl.this, + holder.getRequest(i), + readoutTimestamp - (subsequenceId - i) * + NANO_PER_SECOND / fpsRange.getUpper(), + frameNumber - (subsequenceId - i)); + } } } else { holder.getCallback().onCaptureStarted( - CameraDeviceImpl.this, - holder.getRequest(resultExtras.getSubsequenceId()), + CameraDeviceImpl.this, request, timestamp, frameNumber); + if (hasReadoutTimestamp) { + holder.getCallback().onReadoutStarted( + CameraDeviceImpl.this, request, + readoutTimestamp, frameNumber); + } } } } diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java index 4d0ba63d7759..41822e77f953 100644 --- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java @@ -1693,8 +1693,10 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { ((i != idx) || notifyCurrentIndex)) { TotalCaptureResult result = previewMap.valueAt(i).second; Long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP); - mCaptureResultHandler.onCaptureCompleted(timestamp, - initializeFilteredResults(result)); + if (mCaptureResultHandler != null) { + mCaptureResultHandler.onCaptureCompleted(timestamp, + initializeFilteredResults(result)); + } Log.w(TAG, "Preview frame drop with timestamp: " + previewMap.keyAt(i)); final long ident = Binder.clearCallingIdentity(); @@ -1739,6 +1741,20 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { // abruptly. Log.w(TAG, "Output surface likely abandoned, dropping buffer!"); img.close(); + } catch (RuntimeException e) { + // NOTE: This is intended to catch RuntimeException from ImageReader.detachImage + // ImageReader.detachImage is not supposed to throw RuntimeExceptions but the + // bug went unchecked for a few years and now its behavior cannot be changed + // without breaking backwards compatibility. + + if (!e.getClass().equals(RuntimeException.class)) { + // re-throw any exceptions that aren't base RuntimeException since they are + // coming from elsewhere, and we shouldn't silently drop those. + throw e; + } + + Log.w(TAG, "Output surface likely abandoned, dropping buffer!"); + img.close(); } } } @@ -1773,9 +1789,23 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } try { reader.detachImage(img); - } catch (Exception e) { - Log.e(TAG, - "Failed to detach image!"); + } catch (IllegalStateException e) { + Log.e(TAG, "Failed to detach image!"); + img.close(); + return; + } catch (RuntimeException e) { + // NOTE: This is intended to catch RuntimeException from ImageReader.detachImage + // ImageReader.detachImage is not supposed to throw RuntimeExceptions but the + // bug went unchecked for a few years and now its behavior cannot be changed + // without breaking backwards compatibility. + + if (!e.getClass().equals(RuntimeException.class)) { + // re-throw any exceptions that aren't base RuntimeException since they are + // coming from elsewhere, and we shouldn't silently drop those. + throw e; + } + + Log.e(TAG, "Failed to detach image!"); img.close(); return; } diff --git a/core/java/android/hardware/camera2/impl/CaptureCallback.java b/core/java/android/hardware/camera2/impl/CaptureCallback.java index 6defe63b1766..b064e6a1f975 100644 --- a/core/java/android/hardware/camera2/impl/CaptureCallback.java +++ b/core/java/android/hardware/camera2/impl/CaptureCallback.java @@ -66,6 +66,13 @@ public abstract class CaptureCallback { CaptureRequest request, long timestamp, long frameNumber); /** + * This method is called when the camera device has started reading out the output + * image for the request, at the beginning of the sensor image readout. + */ + public abstract void onReadoutStarted(CameraDevice camera, + CaptureRequest request, long timestamp, long frameNumber); + + /** * This method is called when some results from an image capture are * available. * diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java index 5d9da73fd5c0..8bf94986a490 100644 --- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java +++ b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java @@ -33,6 +33,8 @@ public class CaptureResultExtras implements Parcelable { private long lastCompletedRegularFrameNumber; private long lastCompletedReprocessFrameNumber; private long lastCompletedZslFrameNumber; + private boolean hasReadoutTimestamp; + private long readoutTimestamp; public static final @android.annotation.NonNull Parcelable.Creator<CaptureResultExtras> CREATOR = new Parcelable.Creator<CaptureResultExtras>() { @@ -56,7 +58,8 @@ public class CaptureResultExtras implements Parcelable { int partialResultCount, int errorStreamId, String errorPhysicalCameraId, long lastCompletedRegularFrameNumber, long lastCompletedReprocessFrameNumber, - long lastCompletedZslFrameNumber) { + long lastCompletedZslFrameNumber, boolean hasReadoutTimestamp, + long readoutTimestamp) { this.requestId = requestId; this.subsequenceId = subsequenceId; this.afTriggerId = afTriggerId; @@ -68,6 +71,8 @@ public class CaptureResultExtras implements Parcelable { this.lastCompletedRegularFrameNumber = lastCompletedRegularFrameNumber; this.lastCompletedReprocessFrameNumber = lastCompletedReprocessFrameNumber; this.lastCompletedZslFrameNumber = lastCompletedZslFrameNumber; + this.hasReadoutTimestamp = hasReadoutTimestamp; + this.readoutTimestamp = readoutTimestamp; } @Override @@ -93,6 +98,10 @@ public class CaptureResultExtras implements Parcelable { dest.writeLong(lastCompletedRegularFrameNumber); dest.writeLong(lastCompletedReprocessFrameNumber); dest.writeLong(lastCompletedZslFrameNumber); + dest.writeBoolean(hasReadoutTimestamp); + if (hasReadoutTimestamp) { + dest.writeLong(readoutTimestamp); + } } public void readFromParcel(Parcel in) { @@ -110,6 +119,10 @@ public class CaptureResultExtras implements Parcelable { lastCompletedRegularFrameNumber = in.readLong(); lastCompletedReprocessFrameNumber = in.readLong(); lastCompletedZslFrameNumber = in.readLong(); + hasReadoutTimestamp = in.readBoolean(); + if (hasReadoutTimestamp) { + readoutTimestamp = in.readLong(); + } } public String getErrorPhysicalCameraId() { @@ -155,4 +168,12 @@ public class CaptureResultExtras implements Parcelable { public long getLastCompletedZslFrameNumber() { return lastCompletedZslFrameNumber; } + + public boolean hasReadoutTimestamp() { + return hasReadoutTimestamp; + } + + public long getReadoutTimestamp() { + return readoutTimestamp; + } } diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableArray.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableArray.java index 6cf5d60acec8..598170dfcb25 100644 --- a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableArray.java +++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableArray.java @@ -26,6 +26,10 @@ import static android.hardware.camera2.marshal.MarshalHelpers.getPrimitiveTypeCl import java.lang.reflect.Array; import java.nio.ByteBuffer; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; import java.util.ArrayList; /** @@ -45,46 +49,49 @@ public class MarshalQueryableArray<T> implements MarshalQueryable<T> { private static final boolean DEBUG = false; private static interface PrimitiveArrayFiller { - public void fillPosition(Object arr, int index, ByteBuffer buffer); + public void fillArray(Object arr, int size, ByteBuffer buffer); static PrimitiveArrayFiller getPrimitiveArrayFiller(Class<?> componentType) { if (componentType == int.class) { return new PrimitiveArrayFiller() { @Override - public void fillPosition(Object arr, int index, ByteBuffer buffer) { - int i = buffer.getInt(); - Array.setInt(arr, index, i); + public void fillArray(Object arr, int size, ByteBuffer buffer) { + IntBuffer ib = buffer.asIntBuffer().get(int[].class.cast(arr), 0, size); + // Update buffer position since the IntBuffer has independent position. + buffer.position(buffer.position() + ib.position() * Integer.BYTES); } }; } else if (componentType == float.class) { return new PrimitiveArrayFiller() { @Override - public void fillPosition(Object arr, int index, ByteBuffer buffer) { - float i = buffer.getFloat(); - Array.setFloat(arr, index, i); + public void fillArray(Object arr, int size, ByteBuffer buffer) { + FloatBuffer fb = + buffer.asFloatBuffer().get(float[].class.cast(arr), 0, size); + buffer.position(buffer.position() + fb.position() * Float.BYTES); } }; } else if (componentType == long.class) { return new PrimitiveArrayFiller() { @Override - public void fillPosition(Object arr, int index, ByteBuffer buffer) { - long i = buffer.getLong(); - Array.setLong(arr, index, i); + public void fillArray(Object arr, int size, ByteBuffer buffer) { + LongBuffer lb = + buffer.asLongBuffer().get(long[].class.cast(arr), 0, size); + buffer.position(buffer.position() + lb.position() * Long.BYTES); } }; } else if (componentType == double.class) { return new PrimitiveArrayFiller() { @Override - public void fillPosition(Object arr, int index, ByteBuffer buffer) { - double i = buffer.getDouble(); - Array.setDouble(arr, index, i); + public void fillArray(Object arr, int size, ByteBuffer buffer) { + DoubleBuffer db = + buffer.asDoubleBuffer().get(double[].class.cast(arr), 0, size); + buffer.position(buffer.position() + db.position() * Double.BYTES); } }; } else if (componentType == byte.class) { return new PrimitiveArrayFiller() { @Override - public void fillPosition(Object arr, int index, ByteBuffer buffer) { - byte i = buffer.get(); - Array.setByte(arr, index, i); + public void fillArray(Object arr, int size, ByteBuffer buffer) { + buffer.get(byte[].class.cast(arr), 0, size); } }; } @@ -93,13 +100,6 @@ public class MarshalQueryableArray<T> implements MarshalQueryable<T> { } }; - static void unmarshalPrimitiveArray(Object arr, int size, ByteBuffer buffer, - PrimitiveArrayFiller filler) { - for (int i = 0; i < size; i++) { - filler.fillPosition(arr, i, buffer); - } - } - private class MarshalerArray extends Marshaler<T> { private final Class<T> mClass; private final Marshaler<?> mComponentMarshaler; @@ -150,8 +150,8 @@ public class MarshalQueryableArray<T> implements MarshalQueryable<T> { array = Array.newInstance(mComponentClass, arraySize); if (isUnwrappedPrimitiveClass(mComponentClass) && mComponentClass == getPrimitiveTypeClass(mNativeType)) { - unmarshalPrimitiveArray(array, arraySize, buffer, - PrimitiveArrayFiller.getPrimitiveArrayFiller(mComponentClass)); + PrimitiveArrayFiller.getPrimitiveArrayFiller(mComponentClass).fillArray(array, + arraySize, buffer); } else { for (int i = 0; i < arraySize; ++i) { Object elem = mComponentMarshaler.unmarshal(buffer); diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index 4a2517763aae..9e8703779863 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -245,6 +245,26 @@ public final class OutputConfiguration implements Parcelable { */ public static final int TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED = 4; + /** + * Timestamp is the start of readout in the same time domain as TIMESTAMP_BASE_SENSOR. + * + * <p>The start of the camera sensor readout after exposure. For a rolling shutter camera + * sensor, the timestamp is typically equal to the start of exposure time + + * exposure time + certain fixed offset. The fixed offset could be due to camera sensor + * level crop. The benefit of using readout time is that when camera runs in a fixed + * frame rate, the timestamp intervals between frames are constant.</p> + * + * <p>This timestamp is in the same time domain as in TIMESTAMP_BASE_SENSOR, with the exception + * that one is start of exposure, and the other is start of readout.</p> + * + * <p>This timestamp base is supported only if {@link + * CameraCharacteristics#SENSOR_READOUT_TIMESTAMP} is + * {@link CameraMetadata#SENSOR_READOUT_TIMESTAMP_HARDWARE}.</p> + * + * @hide + */ + public static final int TIMESTAMP_BASE_READOUT_SENSOR = 5; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"TIMESTAMP_BASE_"}, value = @@ -252,7 +272,8 @@ public final class OutputConfiguration implements Parcelable { TIMESTAMP_BASE_SENSOR, TIMESTAMP_BASE_MONOTONIC, TIMESTAMP_BASE_REALTIME, - TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED}) + TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED, + TIMESTAMP_BASE_READOUT_SENSOR}) public @interface TimestampBase {}; /** @hide */ @@ -974,7 +995,7 @@ public final class OutputConfiguration implements Parcelable { public void setTimestampBase(@TimestampBase int timestampBase) { // Verify that the value is in range if (timestampBase < TIMESTAMP_BASE_DEFAULT || - timestampBase > TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED) { + timestampBase > TIMESTAMP_BASE_READOUT_SENSOR) { throw new IllegalArgumentException("Not a valid timestamp base value " + timestampBase); } diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java index 31f3b6aef251..7092e43596ec 100644 --- a/core/java/android/hardware/face/FaceManager.java +++ b/core/java/android/hardware/face/FaceManager.java @@ -1363,19 +1363,31 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan // Consolidate positional feedback to reduce noise during authentication. case FACE_ACQUIRED_NOT_DETECTED: + return context.getString(R.string.face_acquired_not_detected); case FACE_ACQUIRED_TOO_CLOSE: + return context.getString(R.string.face_acquired_too_close); case FACE_ACQUIRED_TOO_FAR: + return context.getString(R.string.face_acquired_too_far); case FACE_ACQUIRED_TOO_HIGH: + // TODO(b/181269243) Change back once error codes are fixed. + return context.getString(R.string.face_acquired_too_low); case FACE_ACQUIRED_TOO_LOW: + // TODO(b/181269243) Change back once error codes are fixed. + return context.getString(R.string.face_acquired_too_high); case FACE_ACQUIRED_TOO_RIGHT: + // TODO(b/181269243) Change back once error codes are fixed. + return context.getString(R.string.face_acquired_too_left); case FACE_ACQUIRED_TOO_LEFT: + // TODO(b/181269243) Change back once error codes are fixed. + return context.getString(R.string.face_acquired_too_right); case FACE_ACQUIRED_POOR_GAZE: + return context.getString(R.string.face_acquired_poor_gaze); case FACE_ACQUIRED_PAN_TOO_EXTREME: + return context.getString(R.string.face_acquired_pan_too_extreme); case FACE_ACQUIRED_TILT_TOO_EXTREME: + return context.getString(R.string.face_acquired_tilt_too_extreme); case FACE_ACQUIRED_ROLL_TOO_EXTREME: - return context.getString(R.string.face_acquired_poor_gaze); - - // Provide more detailed feedback for other soft errors. + return context.getString(R.string.face_acquired_roll_too_extreme); case FACE_ACQUIRED_INSUFFICIENT: return context.getString(R.string.face_acquired_insufficient); case FACE_ACQUIRED_TOO_BRIGHT: @@ -1394,6 +1406,10 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan return context.getString(R.string.face_acquired_obscured); case FACE_ACQUIRED_SENSOR_DIRTY: return context.getString(R.string.face_acquired_sensor_dirty); + case FACE_ACQUIRED_DARK_GLASSES_DETECTED: + return context.getString(R.string.face_acquired_dark_glasses_detected); + case FACE_ACQUIRED_MOUTH_COVERING_DETECTED: + return context.getString(R.string.face_acquired_mouth_covering_detected); // Find and return the appropriate vendor-specific message. case FACE_ACQUIRED_VENDOR: { @@ -1459,11 +1475,13 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan case FACE_ACQUIRED_ROLL_TOO_EXTREME: return context.getString(R.string.face_acquired_roll_too_extreme); case FACE_ACQUIRED_FACE_OBSCURED: - case FACE_ACQUIRED_DARK_GLASSES_DETECTED: - case FACE_ACQUIRED_MOUTH_COVERING_DETECTED: return context.getString(R.string.face_acquired_obscured); case FACE_ACQUIRED_SENSOR_DIRTY: return context.getString(R.string.face_acquired_sensor_dirty); + case FACE_ACQUIRED_DARK_GLASSES_DETECTED: + return context.getString(R.string.face_acquired_dark_glasses_detected); + case FACE_ACQUIRED_MOUTH_COVERING_DETECTED: + return context.getString(R.string.face_acquired_mouth_covering_detected); case FACE_ACQUIRED_VENDOR: { String[] msgArray = context.getResources().getStringArray( R.array.face_acquired_vendor); diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index 149db319a82e..e373c50e2e34 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -116,6 +116,7 @@ message KeyguardControllerProto { repeated KeyguardOccludedProto keyguard_occluded_states = 2 [deprecated=true]; optional bool aod_showing = 3; repeated KeyguardPerDisplayProto keyguard_per_display = 4; + optional bool keyguard_going_away = 5; } message KeyguardOccludedProto { @@ -132,6 +133,7 @@ message KeyguardPerDisplayProto { optional bool keyguard_showing = 2; optional bool aod_showing = 3; optional bool keyguard_occluded = 4; + optional bool keyguard_going_away = 5; } /* represents PhoneWindowManager */ diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 4e3703aac99a..3d021f752d4d 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -2274,11 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ترجمه شد."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"پیام از <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> به <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ترجمه شد."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"فعالیت در پسزمینه"</string> - <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> - <skip /> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"برنامهای شارژ باتری را خالی میکند"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"یکی از برنامهها همچنان فعال است"</string> - <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> - <skip /> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> در پسزمینه درحال اجرا است. برای مدیریت مصرف باتری ضربه بزنید."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ممکن است بر عمر باتری تأثیر بگذارد. برای مرور برنامههای فعال، ضربه بزنید."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"بررسی برنامههای فعال"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"نمیتوان از <xliff:g id="DEVICE">%1$s</xliff:g> شما به دوربین تلفن دسترسی داشت"</string> diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index fe296c704095..5fd9dc0ca798 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -30,4 +30,5 @@ lockscreen, setting this to true should come with customized drawables. --> <bool name="use_lock_pattern_drawable">false</bool> <bool name="resolver_landscape_phone">true</bool> + <bool name="system_server_plays_face_haptics">true</bool> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index db6be5c42de5..df6d563387f4 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1786,45 +1786,57 @@ <string name="fingerprint_recalibrate_notification_content">Visit a repair provider.</string> <!-- Message shown during face acquisition when the face cannot be recognized [CHAR LIMIT=50] --> - <string name="face_acquired_insufficient">Couldn\u2019t capture accurate face data. Try again.</string> + <string name="face_acquired_insufficient">Can\u2019t create your face model. Try again.</string> <!-- Message shown during face acquisition when the image is too bright [CHAR LIMIT=50] --> <string name="face_acquired_too_bright">Too bright. Try gentler lighting.</string> <!-- Message shown during face acquisition when the image is too dark [CHAR LIMIT=50] --> - <string name="face_acquired_too_dark">Too dark. Try brighter lighting.</string> + <string name="face_acquired_too_dark">Try brighter lighting</string> <!-- Message shown during face acquisition when the user is too close to sensor [CHAR LIMIT=50] --> - <string name="face_acquired_too_close">Move phone farther away.</string> + <string name="face_acquired_too_close">Move phone farther away</string> <!-- Message shown during face acquisition when the user is too far from sensor [CHAR LIMIT=50] --> - <string name="face_acquired_too_far">Move phone closer.</string> + <string name="face_acquired_too_far">Move phone closer</string> <!-- Message shown during face acquisition when the user is too high relatively to sensor [CHAR LIMIT=50] --> - <string name="face_acquired_too_high">Move phone higher.</string> + <string name="face_acquired_too_high">Move phone higher</string> <!-- Message shown during face acquisition when the user is too low relatively to sensor [CHAR LIMIT=50] --> - <string name="face_acquired_too_low">Move phone lower.</string> + <string name="face_acquired_too_low">Move phone lower</string> <!-- Message shown during face acquisition when only the right part of the user's face was detected [CHAR LIMIT=50] --> - <string name="face_acquired_too_right">Move phone to the left.</string> + <string name="face_acquired_too_right">Move phone to your left</string> <!-- Message shown during face acquisition when only the left part of the user's face was detected [CHAR LIMIT=50] --> - <string name="face_acquired_too_left">Move phone to the right.</string> + <string name="face_acquired_too_left">Move phone to your right</string> <!-- Message shown during face acquisition when the user is not front facing the sensor [CHAR LIMIT=50] --> <string name="face_acquired_poor_gaze">Please look more directly at your device.</string> - <!-- Message shown during face acquisition when the user is not detected [CHAR LIMIT=50] --> - <string name="face_acquired_not_detected">Position your face directly in front of the phone.</string> + <!-- Message shown during face acquisition when the user is not detected [CHAR LIMIT=75] --> + <string name="face_acquired_not_detected">Can\u2019t see your face. Hold your phone at eye level.</string> <!-- Message shown during face acquisition when the device is not steady [CHAR LIMIT=50] --> <string name="face_acquired_too_much_motion">Too much motion. Hold phone steady.</string> <!-- Message shown during face acquisition when the sensor needs to be recalibrated [CHAR LIMIT=50] --> <string name="face_acquired_recalibrate">Please re-enroll your face.</string> <!-- Message shown during face enrollment when a different person's face is detected [CHAR LIMIT=50] --> - <string name="face_acquired_too_different">No longer able to recognize face. Try again.</string> + <string name="face_acquired_too_different">Can\u2019t recognize face. Try again.</string> <!-- Message shown during face enrollment when the face is too similar to a previous acquisition [CHAR LIMIT=50] --> - <string name="face_acquired_too_similar">Too similar, please change your pose.</string> + <string name="face_acquired_too_similar">Change the position of your head slightly</string> <!-- Message shown during acqusition when the user's face is turned too far left or right [CHAR LIMIT=50] --> - <string name="face_acquired_pan_too_extreme">Turn your head a little less.</string> + <string name="face_acquired_pan_too_extreme">Look more directly at your phone</string> <!-- Message shown during acqusition when the user's face is tilted too high or too low [CHAR LIMIT=50] --> - <string name="face_acquired_tilt_too_extreme">Tilt your head a little less.</string> + <string name="face_acquired_tilt_too_extreme">Look more directly at your phone</string> <!-- Message shown during acquisiton when the user's face is tilted too far left or right [CHAR LIMIT=50] --> - <string name="face_acquired_roll_too_extreme">Turn your head a little less.</string> + <string name="face_acquired_roll_too_extreme">Look more directly at your phone</string> <!-- Message shown during acquisition when the user's face is obscured [CHAR LIMIT=50] --> <string name="face_acquired_obscured">Remove anything hiding your face.</string> <!-- Message shown during acquisition when the sensor is dirty [CHAR LIMIT=100] --> <string name="face_acquired_sensor_dirty">Clean the top of your screen, including the black bar</string> + <!-- Message shown during acquisition when dark glasses were detected [CHAR LIMIT=75] --> + <string name="face_acquired_dark_glasses_detected">Your face must be fully visible</string> + <!-- Message shown during acquisition when a mouth covering was detected [CHAR LIMIT=75] --> + <string name="face_acquired_mouth_covering_detected">Your face must be fully visible</string> + + <!-- Message shown during face acquisition when the sensor needs to be recalibrated [CHAR LIMIT=75] --> + <string name="face_acquired_recalibrate_alt">Can\u2019t create your face model. Try again.</string> + <!-- Message shown during acquisition when dark glasses were detected [CHAR LIMIT=100] --> + <string name="face_acquired_dark_glasses_detected_alt">Dark glasses detected. Your face must be fully visible.</string> + <!-- Message shown during acquisition when a mouth covering was detected [CHAR LIMIT=100] --> + <string name="face_acquired_mouth_covering_detected_alt">Face covering detected. Your face must be fully visible.</string> + <!-- Array containing custom messages shown during face acquisition from vendor. Vendor is expected to add and translate these strings --> <string-array name="face_acquired_vendor"> </string-array> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 1f71bf9f95dd..3617407e10c5 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2647,6 +2647,11 @@ <java-symbol type="string" name="face_acquired_roll_too_extreme" /> <java-symbol type="string" name="face_acquired_obscured" /> <java-symbol type="string" name="face_acquired_sensor_dirty" /> + <java-symbol type="string" name="face_acquired_dark_glasses_detected" /> + <java-symbol type="string" name="face_acquired_mouth_covering_detected" /> + <java-symbol type="string" name="face_acquired_recalibrate_alt" /> + <java-symbol type="string" name="face_acquired_dark_glasses_detected_alt" /> + <java-symbol type="string" name="face_acquired_mouth_covering_detected_alt" /> <java-symbol type="array" name="face_acquired_vendor" /> <java-symbol type="string" name="face_name_template" /> <java-symbol type="string" name="face_app_setting_name" /> @@ -4822,4 +4827,6 @@ <java-symbol type="id" name="language_picker_header" /> <java-symbol type="dimen" name="status_bar_height_default" /> + + <java-symbol type="bool" name="system_server_plays_face_haptics" /> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index c94455d9151a..bae23575297f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -211,24 +211,24 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange /** Applies new configuration, returns {@code false} if there's no effect to the layout. */ public boolean updateConfiguration(Configuration configuration) { - // Always update configuration after orientation changed to make sure to render divider bar - // with proper resources that matching screen orientation. - final int orientation = configuration.orientation; - if (mOrientation != orientation) { - mContext = mContext.createConfigurationContext(configuration); - mSplitWindowManager.setConfiguration(configuration); - mOrientation = orientation; - } - // Update the split bounds when necessary. Besides root bounds changed, split bounds need to // be updated when the rotation changed to cover the case that users rotated the screen 180 // degrees. + // Make sure to render the divider bar with proper resources that matching the screen + // orientation. final int rotation = configuration.windowConfiguration.getRotation(); final Rect rootBounds = configuration.windowConfiguration.getBounds(); - if (mRotation == rotation && mRootBounds.equals(rootBounds)) { + final int orientation = configuration.orientation; + + if (mOrientation == orientation + && mRotation == rotation + && mRootBounds.equals(rootBounds)) { return false; } + mContext = mContext.createConfigurationContext(configuration); + mSplitWindowManager.setConfiguration(configuration); + mOrientation = orientation; mTempRect.set(mRootBounds); mRootBounds.set(rootBounds); mRotation = rotation; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index dad261ad9580..4b1e5f8c0d7c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -542,24 +542,44 @@ public class PipController implements PipTransitionController.PipTransitionCallb mMenuController.attachPipMenuView(); // Calculate the snap fraction of the current stack along the old movement bounds final PipSnapAlgorithm pipSnapAlgorithm = mPipBoundsAlgorithm.getSnapAlgorithm(); - final Rect postChangeStackBounds = new Rect(mPipBoundsState.getBounds()); - final float snapFraction = pipSnapAlgorithm.getSnapFraction(postChangeStackBounds, - mPipBoundsAlgorithm.getMovementBounds(postChangeStackBounds), + final Rect postChangeBounds = new Rect(mPipBoundsState.getBounds()); + final float snapFraction = pipSnapAlgorithm.getSnapFraction(postChangeBounds, + mPipBoundsAlgorithm.getMovementBounds(postChangeBounds), mPipBoundsState.getStashedState()); + // Scale PiP on density dpi change, so it appears to be the same size physically. + final boolean densityDpiChanged = mPipBoundsState.getDisplayLayout().densityDpi() != 0 + && (mPipBoundsState.getDisplayLayout().densityDpi() != layout.densityDpi()); + if (densityDpiChanged) { + final float scale = (float) layout.densityDpi() + / mPipBoundsState.getDisplayLayout().densityDpi(); + postChangeBounds.set(0, 0, + (int) (postChangeBounds.width() * scale), + (int) (postChangeBounds.height() * scale)); + } + updateDisplayLayout.run(); - // Calculate the stack bounds in the new orientation based on same fraction along the + // Calculate the PiP bounds in the new orientation based on same fraction along the // rotated movement bounds. final Rect postChangeMovementBounds = mPipBoundsAlgorithm.getMovementBounds( - postChangeStackBounds, false /* adjustForIme */); - pipSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, + postChangeBounds, false /* adjustForIme */); + pipSnapAlgorithm.applySnapFraction(postChangeBounds, postChangeMovementBounds, snapFraction, mPipBoundsState.getStashedState(), mPipBoundsState.getStashOffset(), mPipBoundsState.getDisplayBounds(), mPipBoundsState.getDisplayLayout().stableInsets()); - mTouchHandler.getMotionHelper().movePip(postChangeStackBounds); + if (densityDpiChanged) { + // Using PipMotionHelper#movePip directly here may cause race condition since + // the app content in PiP mode may or may not be updated for the new density dpi. + final int duration = mContext.getResources().getInteger( + R.integer.config_pipEnterAnimationDuration); + mPipTaskOrganizer.scheduleAnimateResizePip( + postChangeBounds, duration, null /* updateBoundsCallback */); + } else { + mTouchHandler.getMotionHelper().movePip(postChangeBounds); + } } else { updateDisplayLayout.run(); } diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index 190e1cc083bd..fba4249260ef 100644 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -142,6 +142,14 @@ public class GpsNetInitiatedHandler { public int textEncoding; } + /** Callbacks for Emergency call events. */ + public interface EmergencyCallCallback { + /** Callback invoked when an emergency call starts */ + void onEmergencyCallStart(int subId); + /** Callback invoked when an emergency call ends */ + void onEmergencyCallEnd(); + } + private class EmergencyCallListener extends TelephonyCallback implements TelephonyCallback.OutgoingEmergencyCallListener, TelephonyCallback.CallStateListener { @@ -152,6 +160,7 @@ public class GpsNetInitiatedHandler { int subscriptionId) { mIsInEmergencyCall = true; if (DEBUG) Log.d(TAG, "onOutgoingEmergencyCall(): inEmergency = " + getInEmergency()); + mEmergencyCallCallback.onEmergencyCallStart(subscriptionId); } @Override @@ -163,6 +172,7 @@ public class GpsNetInitiatedHandler { if (mIsInEmergencyCall) { mCallEndElapsedRealtimeMillis = SystemClock.elapsedRealtime(); mIsInEmergencyCall = false; + mEmergencyCallCallback.onEmergencyCallEnd(); } } } @@ -180,8 +190,11 @@ public class GpsNetInitiatedHandler { */ private Notification.Builder mNiNotificationBuilder; + private final EmergencyCallCallback mEmergencyCallCallback; + public GpsNetInitiatedHandler(Context context, INetInitiatedListener netInitiatedListener, + EmergencyCallCallback emergencyCallCallback, boolean isSuplEsEnabled) { mContext = context; @@ -190,6 +203,7 @@ public class GpsNetInitiatedHandler { } else { mNetInitiatedListener = netInitiatedListener; } + mEmergencyCallCallback = emergencyCallCallback; setSuplEsEnabled(isSuplEsEnabled); mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE); diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index f9c6121c2eae..b4d28d798333 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"Estableciendo conexión…"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"Conectado<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"Vinculando…"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"Emparejando…"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sin audio de teléfono)"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Conectado (sin audio multimedia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> (sin acceso a mensajes)"</string> @@ -570,7 +570,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 usuario nuevo, este 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 usuario nuevo, debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de usuarios."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"¿Configurar usuario ahora?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"Asegúrate de que la persona está disponible en este momento para usar el dispositivo y configurar su espacio."</string> <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"¿Quieres configurar un perfil ahora?"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 29376f30c1fb..37a6db28ee0b 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -589,7 +589,7 @@ <string name="add_user_failed" msgid="4809887794313944872">"Uue kasutaja loomine ebaõnnestus"</string> <string name="add_guest_failed" msgid="8074548434469843443">"Uue külalise loomine ei õnnestunud"</string> <string name="user_nickname" msgid="262624187455825083">"Hüüdnimi"</string> - <string name="user_add_user" msgid="7876449291500212468">"Kasutaja lisamine"</string> + <string name="user_add_user" msgid="7876449291500212468">"Lisa kasutaja"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Lisa külaline"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Eemalda külaline"</string> <string name="guest_reset_guest" msgid="6110013010356013758">"Lähtesta külastajaseanss"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 02b78c16aabc..325fdbba7c25 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -570,7 +570,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">"आप और ज़्यादा उपयोगकर्ता बनाकर इस डिवाइस को दूसरे लोगों के साथ शेयर कर सकते हैं. हर उपयोगकर्ता के पास अपनी जगह होती है, जिसमें वह मनपसंद तरीके से ऐप्लिकेशन, वॉलपेपर और दूसरी चीज़ों में बदलाव कर सकते हैं. उपयोगकर्ता वाई-फ़ाई जैसी डिवाइस सेटिंग में भी बदलाव कर सकते हैं, जिसका असर हर किसी पर पड़ेगा.\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_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> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 2196c75ddde6..c50b18079f52 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -594,7 +594,7 @@ <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> - <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"להסיר את האורח/ת?"</string> + <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"להסיר את האורח?"</string> <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"איפוס"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"הסרה"</string> <string name="guest_resetting" msgid="7822120170191509566">"מתבצע איפוס של הגלישה כאורח…"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 8af2627c8e9c..73830c51d3f2 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ажыратылууда…"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"Туташууда…"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"Туташып турат<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"Жупташтырылууда…"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"Туташууда…"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Туташып турат (телефониясыз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Туташып турат (медиасыз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"Туташып турат (SMS/MMS жазышуусуз)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -150,7 +150,7 @@ <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ЖУПТАШТЫРУУ"</string> <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_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүнө туташуу мүмкүн болгон жок."</string> <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN-код же сырсөз туура эмес болгондуктан, \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" түзмөгүнө туташуу мүмкүн болгон жок."</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> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 4006665cb12e..5c3578cea23d 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"डिस्कनेक्ट करत आहे..."</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"कनेक्ट करत आहे..."</string> <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>कनेक्ट केले"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"जोडत आहे…"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"पेअर करत आहे…"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"कनेक्ट केले (फोन नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"कनेक्ट केले (मीडिया नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"कनेक्ट केले (मेसेज अॅक्सेस नाही)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -151,7 +151,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> सह जोडू शकलो नाही."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"अयोग्य पिन किंवा पासकीमुळे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> सह पेअर करू शकलो नाही."</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-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 98bac84ac706..c0aafc490564 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"အဆက်အသွယ်ဖြတ်တောက်သည်"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"ချိတ်ဆက်နေသည်"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ချိတ်ဆက်ပြီးပြီ"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"တွဲချိတ်ပါ"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"တွဲချိတ်နေသည်…"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ချိတ်ဆက်ပြီးပြီ (ဖုန်းမရှိပါ)"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ချိတ်ဆက်ပြီးပြီ (မီဒီယာ မရှိပါ)"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> ချိတ်ဆက်ပြီးပြီ (မက်ဆေ့ဂျ် သုံး၍မရပါ)"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 13bdd7e90dbc..4f64d104a809 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Kobler fra…"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"Kobler til…"</string> <string name="bluetooth_connected" msgid="8065345572198502293">"Koblet til <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"Sammenkobles …"</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"Kobler til …"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Koblet til (ingen telefon) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Koblet til (ingen medier) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"Koblet til (ingen meldingstilgang) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -570,7 +570,7 @@ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Begrenset profil"</string> <string name="user_add_user_title" msgid="5457079143694924885">"Vil du legge til en ny bruker?"</string> <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kan dele denne enheten med andre folk ved å opprette flere brukere. Hver bruker har sin egen plass de kan tilpasse med apper, bakgrunner og annet. Brukere kan også justere enhetsinnstillinger, for eksempel Wi-Fi, som påvirker alle.\n\nNår du legger til en ny bruker, må vedkommende angi innstillinger for plassen sin.\n\nAlle brukere kan oppdatere apper for alle andre brukere. Innstillinger og tjenester for tilgjengelighet overføres kanskje ikke til den nye brukeren."</string> - <string name="user_add_user_message_short" msgid="3295959985795716166">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område.\n\nAlle brukere kan oppdatere apper for alle andre brukere."</string> + <string name="user_add_user_message_short" msgid="3295959985795716166">"Når du legger til en ny bruker, må hen konfigurere sitt eget område.\n\nAlle brukere kan oppdatere apper for alle andre brukere."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"Konfigurere brukeren nå?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"Sørg for at brukeren er tilgjengelig for å konfigurere området sitt på enheten"</string> <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Vil du konfigurere profilen nå?"</string> @@ -590,7 +590,7 @@ <string name="add_guest_failed" msgid="8074548434469843443">"Kunne ikke opprette en ny gjest"</string> <string name="user_nickname" msgid="262624187455825083">"Kallenavn"</string> <string name="user_add_user" msgid="7876449291500212468">"Legg til bruker"</string> - <string name="guest_new_guest" msgid="3482026122932643557">"Legg til en gjest"</string> + <string name="guest_new_guest" msgid="3482026122932643557">"Legg til gjest"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gjesten"</string> <string name="guest_reset_guest" msgid="6110013010356013758">"Tilbakestill gjest"</string> <string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"Vil du tilbakestille gjesten?"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 187e1794de93..c25966c2d429 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -95,7 +95,7 @@ <string name="bluetooth_disconnecting" msgid="7638892134401574338">"డిస్కనెక్ట్ చేస్తోంది..."</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"కనెక్ట్ చేస్తోంది..."</string> <string name="bluetooth_connected" msgid="8065345572198502293">"కనెక్ట్ చేయబడిన<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> - <string name="bluetooth_pairing" msgid="4269046942588193600">"జత చేస్తోంది..."</string> + <string name="bluetooth_pairing" msgid="4269046942588193600">"పెయిరింగ్..."</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"కనెక్ట్ చేయబడింది (ఫోన్ కాదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"కనెక్ట్ చేయబడింది (మీడియా కాదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"కనెక్ట్ చేయబడింది (సందేశ యాక్సెస్ లేదు)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string> @@ -594,7 +594,7 @@ <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> - <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"అతిథిని తీసివేయాలా?"</string> + <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"గెస్ట్ను తీసివేయాలా?"</string> <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"రీసెట్ చేయండి"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"తీసివేయండి"</string> <string name="guest_resetting" msgid="7822120170191509566">"గెస్ట్ సెషన్ను రీసెట్ చేస్తోంది…"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java index 8b34cf3d624f..44a37f4ccaca 100644 --- a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java @@ -25,6 +25,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.util.MathUtils; import android.view.Display; +import android.view.DisplayInfo; import android.view.IWindowManager; import android.view.WindowManagerGlobal; @@ -87,14 +88,14 @@ public class DisplayDensityUtils { } final Resources res = context.getResources(); - final DisplayMetrics metrics = new DisplayMetrics(); - context.getDisplayNoVerify().getRealMetrics(metrics); + DisplayInfo info = new DisplayInfo(); + context.getDisplayNoVerify().getDisplayInfo(info); - final int currentDensity = metrics.densityDpi; + final int currentDensity = info.logicalDensityDpi; int currentDensityIndex = -1; // Compute number of "larger" and "smaller" scales for this display. - final int minDimensionPx = Math.min(metrics.widthPixels, metrics.heightPixels); + final int minDimensionPx = Math.min(info.logicalWidth, info.logicalHeight); final int maxDensity = DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP; final float maxScaleDimen = context.getResources().getFraction( R.fraction.display_density_max_scale, 1, 1); diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING index 3bd6d51eecc6..edb5ee30524f 100644 --- a/packages/SystemUI/TEST_MAPPING +++ b/packages/SystemUI/TEST_MAPPING @@ -91,7 +91,7 @@ // // If you don't use @Staging or @Postsubmit, your new test will immediately // block presubmit, which is probably not what you want! - "platinum-postsubmit": [ + "sysui-platinum-postsubmit": [ { "name": "PlatformScenarioTests", "options": [ @@ -110,7 +110,7 @@ ] } ], - "staged-platinum-postsubmit": [ + "sysui-staged-platinum-postsubmit": [ { "name": "PlatformScenarioTests", "options": [ diff --git a/packages/SystemUI/animation/res/values/ids.xml b/packages/SystemUI/animation/res/values/ids.xml index 03ca462beb76..f7150ab548dd 100644 --- a/packages/SystemUI/animation/res/values/ids.xml +++ b/packages/SystemUI/animation/res/values/ids.xml @@ -21,6 +21,7 @@ <!-- ViewBoundsAnimator --> <item type="id" name="tag_animator"/> + <item type="id" name="tag_alpha_animator"/> <item type="id" name="tag_layout_listener"/> <item type="id" name="tag_override_bottom"/> <item type="id" name="tag_override_left"/> 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 bb6eb78aac65..323db8526470 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -494,9 +494,10 @@ class ActivityLaunchAnimator( } private fun applyStateToWindow(window: RemoteAnimationTarget, state: LaunchAnimator.State) { - if (transactionApplierView.viewRootImpl == null) { - // If the view root we synchronize with was detached, don't apply any transaction - // (as [SyncRtSurfaceTransactionApplier.scheduleApply] would otherwise throw). + if (transactionApplierView.viewRootImpl == null || !window.leash.isValid) { + // Don't apply any transaction if the view root we synchronize with was detached or + // if the SurfaceControl associated with [window] is not valid, as + // [SyncRtSurfaceTransactionApplier.scheduleApply] would otherwise throw. return } @@ -557,9 +558,10 @@ class ActivityLaunchAnimator( state: LaunchAnimator.State, linearProgress: Float ) { - if (transactionApplierView.viewRootImpl == null) { - // If the view root we synchronize with was detached, don't apply any transaction - // (as [SyncRtSurfaceTransactionApplier.scheduleApply] would otherwise throw). + if (transactionApplierView.viewRootImpl == null || !navigationBar.leash.isValid) { + // Don't apply any transaction if the view root we synchronize with was detached or + // if the SurfaceControl associated with [navigationBar] is not valid, as + // [SyncRtSurfaceTransactionApplier.scheduleApply] would otherwise throw. return } diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt index 093589f8c636..4c3cd3c2b441 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt @@ -39,6 +39,7 @@ class ViewHierarchyAnimator { private val DEFAULT_INTERPOLATOR = Interpolators.STANDARD private val DEFAULT_ADDITION_INTERPOLATOR = Interpolators.STANDARD_DECELERATE private val DEFAULT_REMOVAL_INTERPOLATOR = Interpolators.STANDARD_ACCELERATE + private val DEFAULT_FADE_IN_INTERPOLATOR = Interpolators.ALPHA_IN /** The properties used to animate the view bounds. */ private val PROPERTIES = mapOf( @@ -162,6 +163,10 @@ class ViewHierarchyAnimator { * animate an already visible view, see [animate] and [animateNextUpdate]. * * Then animator unregisters itself once the first addition animation is complete. + * + * @param includeFadeIn true if the animator should also fade in the view and child views. + * @param fadeInInterpolator the interpolator to use when fading in the view. Unused if + * [includeFadeIn] is false. */ @JvmOverloads fun animateAddition( @@ -169,7 +174,9 @@ class ViewHierarchyAnimator { origin: Hotspot = Hotspot.CENTER, interpolator: Interpolator = DEFAULT_ADDITION_INTERPOLATOR, duration: Long = DEFAULT_DURATION, - includeMargins: Boolean = false + includeMargins: Boolean = false, + includeFadeIn: Boolean = false, + fadeInInterpolator: Interpolator = DEFAULT_FADE_IN_INTERPOLATOR ): Boolean { if (isVisible( rootView.visibility, @@ -186,6 +193,42 @@ class ViewHierarchyAnimator { origin, interpolator, duration, ignorePreviousValues = !includeMargins ) addListener(rootView, listener, recursive = true) + + if (!includeFadeIn) { + return true + } + + if (rootView is ViewGroup) { + // First, fade in the container view + val containerDuration = duration / 6 + createAndStartFadeInAnimator( + rootView, containerDuration, startDelay = 0, interpolator = fadeInInterpolator + ) + + // Then, fade in the child views + val childDuration = duration / 3 + for (i in 0 until rootView.childCount) { + val view = rootView.getChildAt(i) + createAndStartFadeInAnimator( + view, + childDuration, + // Wait until the container fades in before fading in the children + startDelay = containerDuration, + interpolator = fadeInInterpolator + ) + } + // For now, we don't recursively fade in additional sub views (e.g. grandchild + // views) since it hasn't been necessary, but we could add that functionality. + } else { + // Fade in the view during the first half of the addition + createAndStartFadeInAnimator( + rootView, + duration / 2, + startDelay = 0, + interpolator = fadeInInterpolator + ) + } + return true } @@ -834,6 +877,27 @@ class ViewHierarchyAnimator { view.setTag(R.id.tag_animator, animator) animator.start() } + + private fun createAndStartFadeInAnimator( + view: View, + duration: Long, + startDelay: Long, + interpolator: Interpolator + ) { + val animator = ObjectAnimator.ofFloat(view, "alpha", 1f) + animator.startDelay = startDelay + animator.duration = duration + animator.interpolator = interpolator + animator.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + view.setTag(R.id.tag_alpha_animator, null /* tag */) + } + }) + + (view.getTag(R.id.tag_alpha_animator) as? ObjectAnimator)?.cancel() + view.setTag(R.id.tag_alpha_animator, animator) + animator.start() + } } /** An enum used to determine the origin of addition animations. */ diff --git a/packages/SystemUI/res-keyguard/values/config.xml b/packages/SystemUI/res-keyguard/values/config.xml index a25ab5109fa8..b1d33758f1b3 100644 --- a/packages/SystemUI/res-keyguard/values/config.xml +++ b/packages/SystemUI/res-keyguard/values/config.xml @@ -28,6 +28,11 @@ <!-- Will display the bouncer on one side of the display, and the current user icon and user switcher on the other side --> <bool name="config_enableBouncerUserSwitcher">false</bool> + <!-- Whether to show the face scanning animation on devices with face auth supported. + The face scanning animation renders in a SW layer in ScreenDecorations. + Enabling this will also render the camera protection in the SW layer + (instead of HW, if relevant)."=--> + <bool name="config_enableFaceScanningAnimation">true</bool> <!-- Time to be considered a consecutive fingerprint failure in ms --> <integer name="fp_consecutive_failure_time_ms">3500</integer> </resources> diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 64aa8ee84423..1be2d997719d 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -220,8 +220,8 @@ <!-- Face hint message when finger was not recognized. [CHAR LIMIT=20] --> <string name="kg_face_not_recognized">Not recognized</string> - <!-- Error message indicating that the camera privacy sensor has been turned on [CHAR LIMIT=NONE] --> - <string name="kg_face_sensor_privacy_enabled">To use Face Unlock, turn on <b>Camera access</b> in Settings > Privacy</string> + <!-- Error message indicating that the camera privacy sensor has been turned on [CHAR LIMIT=53] --> + <string name="kg_face_sensor_privacy_enabled">To use Face Unlock, turn on camera access in Settings</string> <!-- Instructions telling the user remaining times when enter SIM PIN view. --> <plurals name="kg_password_default_pin_message"> diff --git a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml index 3a08a7111d9a..41123c84ded1 100644 --- a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml +++ b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml @@ -16,19 +16,13 @@ * limitations under the License. */ --> -<ripple +<shape xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - android:color="?android:attr/textColorPrimary"> - <item> - <shape - android:shape="rectangle"> - <solid android:color="?androidprv:attr/colorSurface"/> - <size - android:width="@dimen/keyguard_affordance_width" - android:height="@dimen/keyguard_affordance_height"/> - <corners android:radius="@dimen/keyguard_affordance_fixed_radius"/> - </shape> - </item> -</ripple> - + android:shape="rectangle"> + <solid android:color="?androidprv:attr/colorSurface"/> + <size + android:width="@dimen/keyguard_affordance_width" + android:height="@dimen/keyguard_affordance_height"/> + <corners android:radius="@dimen/keyguard_affordance_fixed_radius"/> +</shape> diff --git a/packages/SystemUI/res/layout/auth_biometric_view.xml b/packages/SystemUI/res/layout/auth_biometric_view.xml deleted file mode 100644 index ee4da25f2284..000000000000 --- a/packages/SystemUI/res/layout/auth_biometric_view.xml +++ /dev/null @@ -1,26 +0,0 @@ -<!-- - ~ Copyright (C) 2022 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. - --> - -<com.android.systemui.biometrics.AuthBiometricView - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/contents" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <include layout="@layout/auth_biometric_contents"/> - -</com.android.systemui.biometrics.AuthBiometricView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/media_ttt_chip.xml b/packages/SystemUI/res/layout/media_ttt_chip.xml index a502d33a0be1..4d24140abbf4 100644 --- a/packages/SystemUI/res/layout/media_ttt_chip.xml +++ b/packages/SystemUI/res/layout/media_ttt_chip.xml @@ -13,71 +13,85 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> -<LinearLayout +<!-- Wrap in a frame layout so that we can update the margins on the inner layout. (Since this view + is the root view of a window, we cannot change the root view's margins.) --> +<!-- Alphas start as 0 because the view will be animated in. --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:id="@+id/media_ttt_sender_chip" - android:orientation="horizontal" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:padding="@dimen/media_ttt_chip_outer_padding" - android:background="@drawable/media_ttt_chip_background" - android:layout_marginTop="50dp" - android:clipToPadding="false" - android:gravity="center_vertical" - > + android:layout_height="wrap_content"> - <com.android.internal.widget.CachingIconView - android:id="@+id/app_icon" - android:layout_width="@dimen/media_ttt_app_icon_size" - android:layout_height="@dimen/media_ttt_app_icon_size" - android:layout_marginEnd="12dp" - /> - - <TextView - android:id="@+id/text" + <LinearLayout + android:id="@+id/media_ttt_sender_chip_inner" + android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="@dimen/media_ttt_text_size" - android:textColor="?android:attr/textColorPrimary" - /> + android:padding="@dimen/media_ttt_chip_outer_padding" + android:background="@drawable/media_ttt_chip_background" + android:layout_marginTop="20dp" + android:clipToPadding="false" + android:gravity="center_vertical" + android:alpha="0.0" + > - <!-- At most one of [loading, failure_icon, undo] will be visible at a time. --> + <com.android.internal.widget.CachingIconView + android:id="@+id/app_icon" + android:layout_width="@dimen/media_ttt_app_icon_size" + android:layout_height="@dimen/media_ttt_app_icon_size" + android:layout_marginEnd="12dp" + android:alpha="0.0" + /> - <ProgressBar - android:id="@+id/loading" - android:indeterminate="true" - android:layout_width="@dimen/media_ttt_status_icon_size" - android:layout_height="@dimen/media_ttt_status_icon_size" - android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" - android:indeterminateTint="?androidprv:attr/colorAccentPrimaryVariant" - style="?android:attr/progressBarStyleSmall" - /> + <TextView + android:id="@+id/text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="@dimen/media_ttt_text_size" + android:textColor="?android:attr/textColorPrimary" + android:alpha="0.0" + /> - <ImageView - android:id="@+id/failure_icon" - android:layout_width="@dimen/media_ttt_status_icon_size" - android:layout_height="@dimen/media_ttt_status_icon_size" - android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" - android:src="@drawable/ic_warning" - android:tint="@color/GM2_red_500" - /> + <!-- At most one of [loading, failure_icon, undo] will be visible at a time. --> + <ProgressBar + android:id="@+id/loading" + android:indeterminate="true" + android:layout_width="@dimen/media_ttt_status_icon_size" + android:layout_height="@dimen/media_ttt_status_icon_size" + android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" + android:indeterminateTint="?androidprv:attr/colorAccentPrimaryVariant" + style="?android:attr/progressBarStyleSmall" + android:alpha="0.0" + /> - <TextView - android:id="@+id/undo" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/media_transfer_undo" - android:textColor="?androidprv:attr/textColorOnAccent" - android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" - android:textSize="@dimen/media_ttt_text_size" - android:paddingStart="@dimen/media_ttt_chip_outer_padding" - android:paddingEnd="@dimen/media_ttt_chip_outer_padding" - android:paddingTop="@dimen/media_ttt_undo_button_vertical_padding" - android:paddingBottom="@dimen/media_ttt_undo_button_vertical_padding" - android:layout_marginTop="@dimen/media_ttt_undo_button_vertical_negative_margin" - android:layout_marginBottom="@dimen/media_ttt_undo_button_vertical_negative_margin" - android:background="@drawable/media_ttt_undo_background" - /> + <ImageView + android:id="@+id/failure_icon" + android:layout_width="@dimen/media_ttt_status_icon_size" + android:layout_height="@dimen/media_ttt_status_icon_size" + android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" + android:src="@drawable/ic_warning" + android:tint="@color/GM2_red_500" + android:alpha="0.0" + /> + + <TextView + android:id="@+id/undo" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/media_transfer_undo" + android:textColor="?androidprv:attr/textColorOnAccent" + android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" + android:textSize="@dimen/media_ttt_text_size" + android:paddingStart="@dimen/media_ttt_chip_outer_padding" + android:paddingEnd="@dimen/media_ttt_chip_outer_padding" + android:paddingTop="@dimen/media_ttt_undo_button_vertical_padding" + android:paddingBottom="@dimen/media_ttt_undo_button_vertical_padding" + android:layout_marginTop="@dimen/media_ttt_undo_button_vertical_negative_margin" + android:layout_marginBottom="@dimen/media_ttt_undo_button_vertical_negative_margin" + android:background="@drawable/media_ttt_undo_background" + android:alpha="0.0" + /> -</LinearLayout> + </LinearLayout> +</FrameLayout> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 0cb773531459..f101b7c25d9f 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestig"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestig om te voltooi"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ontsluit met gesig. Druk die ontsluitikoon om voort te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontsluit met gesig. Druk om voort te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesig is herken. Druk om voort te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesig is herken. Druk die ontsluitikoon om voort te gaan."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Gestaaf"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gebruik PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gebruik patroon"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swiep op om oop te maak"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Druk die onsluitikoon om oop te maak"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ontsluit met gesig. Druk die ontsluitikoon om oop te maak."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ontsluit met gesig. Druk om oop te maak."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Gesig is herken. Druk om oop te maak."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gesig is herken. Druk die ontsluitikoon om oop te maak."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swiep op om weer te probeer"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontsluit om NFC te gebruik"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Hierdie toestel behoort aan jou organisasie"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 4cd2a3d40829..5838dbf9521f 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ተረጋግጧል"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ለማጠናቀቅ አረጋግጥን መታ ያድርጉ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"በመልክ ተከፍቷል። ለመቀጠል የመክፈቻ አዶውን ይጫኑ።"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"በመልክ ተከፍቷል። ለመቀጠል ይጫኑ።"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"መልክ ተለይቶ ታውቋል። ለመቀጠል ይጫኑ።"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"መልክ ተለይቶ ታውቋል። ለመቀጠል የመክፈቻ አዶውን ይጫኑ።"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"የተረጋገጠ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ፒን ይጠቀሙ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ሥርዓተ ጥለትን ተጠቀም"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ለመክፈት በጣት ወደ ላይ ጠረግ ያድርጉ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ለመክፈት የመክፈቻ አዶውን ይጫኑ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"በመልክ ተከፍቷል። ለመክፈት የመክፈቻ አዶውን ይጫኑ።"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"በመልክ ተከፍቷል። ለመክፈት ይጫኑ።"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"መልክ ተለይቶ ታውቋል። ለመክፈት ይጫኑ።"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"መልክ ተለይቶ ታውቋል። ለመክፈት የመክፈቻ አዶውን ይጫኑ።"</string> <string name="keyguard_retry" msgid="886802522584053523">"እንደገና ለመሞከር ወደ ላይ ይጥረጉ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCን ለመጠቀም ይክፈቱ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ይህ መሣሪያ የድርጅትዎ ነው"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 60bf24742a1d..d711d592933b 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تمّ التأكيد."</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"يمكنك النقر على \"تأكيد\" لإكمال المهمة."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"فُتح القفل عندما تمّ التعرّف على وجهك. للمتابعة، اضغط على رمز فتح القفل."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط للمتابعة."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"تم التعرّف على الوجه. اضغط للمتابعة."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"تم التعرّف على الوجه. للمتابعة، اضغط على رمز فتح القفل."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"مصادقة"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"استخدام رقم تعريف شخصي"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"استخدام نقش"</string> @@ -320,6 +323,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"يمكنك الفتح بالتمرير سريعًا لأعلى."</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"اضغط على رمز فتح القفل لفتح قفل الشاشة."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"فُتح القفل عندما تمّ التعرّف على وجهك. اضغط على رمز فتح القفل لفتحه."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط لفتح الجهاز."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"تم التعرّف على الوجه. اضغط لفتح الجهاز."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"تم التعرّف على الوجه. اضغط على رمز فتح القفل لفتح الجهاز."</string> <string name="keyguard_retry" msgid="886802522584053523">"مرِّر سريعًا للأعلى لإعادة المحاولة."</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"افتح قفل الشاشة لاستخدام تقنية NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"هذا الجهاز يخص مؤسستك."</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index b9ba840f00c5..68728a731182 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"নিশ্চিত কৰিলে"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূৰ্ণ কৰিবলৈ নিশ্চিত কৰক-ত টিপক"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"পিন ব্যৱহাৰ কৰক"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"আৰ্হি ব্যৱহাৰ কৰক"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"খুলিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"খুলিবলৈ আনলক কৰক চিহ্নটোত টিপক"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। খুলিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। খুলিবলৈ টিপক।"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। খুলিবলৈ টিপক।"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। খুলিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string> <string name="keyguard_retry" msgid="886802522584053523">"পুনৰ চেষ্টা কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index c0735cc6dec3..e4ab386f3ba0 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Təsdiqləndi"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamaq üçün \"Təsdiq edin\" seçiminə toxunun"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Üzlə kilidi açılıb. \"Kilidi aç\" ikonasına basıb davam edin."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Üz ilə kiliddən çıxarılıb. Davam etmək üçün basın."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Üz tanınıb. Davam etmək üçün basın."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb davam edin."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Doğrulandı"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN istifadə edin"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Model istifadə edin"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Açmaq üçün yuxarı sürüşdürün"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"\"Kilidi aç\" ikonasına basıb açın"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Üzlə kilidi açılıb. \"Kilidi aç\" ikonasına basıb açın."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Üz ilə kiliddən çıxarılıb. Açmaq üçün basın."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Üz tanınıb. Açmaq üçün basın."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb açın."</string> <string name="keyguard_retry" msgid="886802522584053523">"Yenidən cəhd etmək üçün yuxarı sürüşdürün"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC istifadə etmək üçün kiliddən çıxarın"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz təşkilatınıza məxsusdur"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 585b8798798d..ac7b219faa1d 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da biste završili"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Otključano je licem. Pritisnite ikonu otključavanja za nastavak"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano je licem. Pritisnite da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu otključavanja za nastavak."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Identitet je potvrđen"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristite PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristite šablon"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite nagore da biste otvorili"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pritisnite ikonu otključavanja za otvaranje"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Otključano je licem. Pritisnite ikonu otključavanja za otvaranje"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Otključano je licem. Pritisnite da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Lice je prepoznato. Pritisnite da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice prepoznato. Pritisnite ikonu otključavanja za otvaranje."</string> <string name="keyguard_retry" msgid="886802522584053523">"Prevucite nagore da biste probali ponovo"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste koristili NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada organizaciji"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 08379979bf09..7f006f46724f 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Пацверджана"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Націсніце \"Пацвердзіць\", каб завяршыць"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Твар распазнаны. Для працягу націсніце значок разблакіроўкі."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблакіравана распазнаваннем твару. Націсніце для працягу."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Твар распазнаны. Націсніце для працягу."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Твар распазнаны. Для працягу націсніце значок разблакіроўкі."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Распазнана"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Увесці PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Выкарыстаць узор разблакіроўкі"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Каб адкрыць, прагарніце ўверх"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Каб адкрыць, націсніце значок разблакіроўкі"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Твар распазнаны. Для адкрыцця націсніце значок разблакіроўкі"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Разблакіравана распазнаваннем твару. Націсніце, каб адкрыць."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Твар распазнаны. Націсніце, каб адкрыць."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Твар распазнаны. Для адкрыцця націсніце значок разблакіроўкі."</string> <string name="keyguard_retry" msgid="886802522584053523">"Прагартайце ўверх, каб паўтарыць спробу"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Разблакіруйце, каб выкарыстоўваць NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Гэта прылада належыць вашай арганізацыі"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index c9d1e81e7c29..901572db25c7 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потвърдено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Докоснете „Потвърждаване“ за завършване"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Отключено с лице. Натиснете иконата за отключване, за да продължите."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Отключено с лице. Натиснете, за да продължите."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето бе разпознато. Натиснете, за да продължите."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето бе разпознато. Продължете чрез иконата за отключване."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Удостоверено"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Използване на ПИН"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Използване на фигура"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Прекарайте пръст нагоре, за да отключите"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Натиснете иконата за отключване, за да отворите"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Отключено с лице. Натиснете иконата за отключване, за да отворите."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Отключено с лице. Натиснете за отваряне."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лицето бе разпознато. Натиснете за отваряне."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицето бе разпознато. Отворете чрез иконата за отключване."</string> <string name="keyguard_retry" msgid="886802522584053523">"Плъзнете бързо нагоре, за да опитате отново"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отключете, за да използвате NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Това устройство принадлежи на организацията ви"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index e5920fcdd734..180d80ba18b7 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"কনফার্ম করা হয়েছে"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূর্ণ করতে \'কনফার্ম করুন\' বোতামে ট্যাপ করুন"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ফেসের সাহায্যে আনলক করা হয়েছে। চালিয়ে যাওয়ার জন্য আনলক আইকনে প্রেস করুন।"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"প্রমাণীকৃত"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"পিন ব্যবহার করুন"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"প্যাটার্ন ব্যবহার করুন"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"খোলার জন্য উপরে সোয়াইপ করুন"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"খোলার জন্য আনলক আইকন প্রেস করুন"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ফেসের সাহায্যে আনলক করা হয়েছে। খোলার জন্য আনলক আইকন প্রেস করুন।"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"আবার চেষ্টা করতে উপরের দিকে সোয়াইপ করুন"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যবহার করতে আনলক করুন"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইসটি আপনার প্রতিষ্ঠানের"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 3d84113d1900..b1edfd992715 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da završite"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Otključano licem. Pritisnite ikonu za otklj. da nastavite."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano licem. Pritisnite da nastavite."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice prepoznato. Pritisnite da nastavite."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu za otklj. da nastavite."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentificirano"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristi PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristi uzorak"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite da otvorite"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pritisnite ikonu za otključavanje da otvorite."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Otključano licem. Pritisnite ikonu za otklj. da otvorite."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Otključano licem. Pritisnite da otvorite."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Lice prepoznato. Pritisnite da otvorite."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice prepoznato. Pritisnite ikonu za otklj. da otvorite."</string> <string name="keyguard_retry" msgid="886802522584053523">"Prevucite prema gore da pokušate ponovo"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da koristite NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 88228753a1f6..20e5a5af5bd9 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirma per completar"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"S\'ha desbloquejat amb la cara. Prem la icona per continuar."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticat"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilitza el PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utilitza el patró"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Llisca cap amunt per obrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Prem la icona de desbloqueig per obrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"S\'ha desbloquejat amb la cara. Prem la icona per obrir."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Llisca cap a dalt per tornar-ho a provar"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueja per utilitzar l\'NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Aquest dispositiu pertany a la teva organització"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 820749f71d42..14749b5fd8a6 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrzeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ověření dokončíte klepnutím na Potvrdit"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odemknuto obličejem. Klepněte na ikonu odemknutí."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odemknuto obličejem. Pokračujte stisknutím."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obličej rozpoznán. Pokračujte stisknutím."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Ověřeno"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Použít kód PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Použít gesto"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Otevřete přejetím prstem nahoru"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Otevřete klepnutím na ikonu odemknutí"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Odemknuto obličejem. Klepněte na ikonu odemknutí."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odemknuto obličejem. Stisknutím otevřete."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Obličej rozpoznán. Stisknutím otevřete."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string> <string name="keyguard_retry" msgid="886802522584053523">"Přejetím nahoru to zkusíte znovu"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC vyžaduje odemknutou obrazovku"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zařízení patří vaší organizaci"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 135b480a3015..8e5095b70fb3 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekræftet"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tryk på Bekræft for at udføre"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Låst op vha. ansigt. Tryk på oplåsningsikonet for at fortsætte."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst op ved hjælp af ansigt. Tryk for at fortsætte."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansigt genkendt. Tryk for at fortsætte."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansigt genkendt. Tryk på oplåsningsikonet for at fortsætte."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Godkendt"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Brug pinkode"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Brug mønster"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Stryg opad for at åbne"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tryk på oplåsningsikonet for at åbne"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Låst op vha. ansigt. Tryk på oplåsningsikonet for at åbne."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Låst op ved hjælp af ansigt. Tryk for at åbne."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ansigt genkendt. Tryk for at åbne."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansigt genkendt. Tryk på oplåsningsikonet for at åbne."</string> <string name="keyguard_retry" msgid="886802522584053523">"Stryg opad for at prøve igen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås op for at bruge NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enhed tilhører din organisation"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 50061fb75849..e0a3eacc028b 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bestätigt"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Zum Abschließen auf \"Bestätigen\" tippen"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Gerät mit dem Gesicht entsperrt. Tippe auf das Symbol „Entsperren“, um fortzufahren."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifiziert"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN verwenden"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Muster verwenden"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Zum Öffnen nach oben wischen"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tippe zum Öffnen auf das Symbol „Entsperren“"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Gerät mit dem Gesicht entsperrt. Tippe zum Öffnen auf das Symbol „Entsperren“."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Zum Wiederholen nach oben wischen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Zur Verwendung von NFC entsperren"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dieses Gerät gehört deiner Organisation"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index d82a28cad763..bb29f6f937ce 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Επιβεβαιώθηκε"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Πατήστε Επιβεβαίωση για ολοκλήρωση"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ξεκλ. με αναγν. προσώπου. Πατ. το εικον. ξεκλ. για συνέχεια."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ξεκλείδωμα με αναγνώριση προσώπου. Πατήστε για συνέχεια."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Το πρόσωπο αναγνωρίστηκε. Πατήστε για συνέχεια."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Το πρόσωπο αναγνωρ. Πατήστε το εικον. ξεκλειδ. για συνέχεια."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Ολοκληρώθηκε ο έλεγχος ταυτότητας"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Χρήση PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Χρήση μοτίβου"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Σύρετε προς τα επάνω για άνοιγμα"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Πατήστε το εικονίδιο ξεκλειδώματος για άνοιγμα"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ξεκλ. με αναγν. προσώπου. Πατ. το εικον. ξεκλ. για άνοιγμα."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ξεκλείδωμα με αναγνώριση προσώπου. Πατήστε για άνοιγμα."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Το πρόσωπο αναγνωρίστηκε. Πατήστε για άνοιγμα."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Το πρόσωπο αναγνωρ. Πατήστ. το εικον. ξεκλειδ. για άνοιγμα."</string> <string name="keyguard_retry" msgid="886802522584053523">"Σύρετε προς τα πάνω για να δοκιμάσετε ξανά"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ξεκλείδωμα για χρήση του NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Αυτή η συσκευή ανήκει στον οργανισμό σας."</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 2ca4d809fe58..790bf3f424e0 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index d7a4dece9140..ce764590458a 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 2ca4d809fe58..790bf3f424e0 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 2ca4d809fe58..790bf3f424e0 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognised. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index be94028c3381..30240d45290f 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Unlocked by face. Press the unlock icon to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognized. Press to continue."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognized. Press the unlock icon to continue."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authenticated"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Use PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Use pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe up to open"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Press the unlock icon to open"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Unlocked by face. Press the unlock icon to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Unlocked by face. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Face recognized. Press to open."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognized. Press the unlock icon to open."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organization"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index ec3c79a562db..f2c7236c64e0 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Presiona Confirmar para completar"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueo con rostro. Presiona ícono desbl. para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueo con rostro. Presiona para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rostro reconocido. Presiona para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rostro reconocido. Presiona el desbloqueo para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar patrón"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Presiona el ícono de desbloquear para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueo con rostro. Presiona ícono desbloq. para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueo con rostro. Presiona para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rostro reconocido. Presiona para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rostro reconocido. Presiona el desbloqueo para abrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volver a intentarlo"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea el dispositivo para usar NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 98394056eefc..f394e0086b75 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar la acción"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado con datos faciales. Pulsa el icono desbloquear para continuar."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Se ha autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar patrón"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pulsa el icono desbloquear para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueado con datos faciales. Pulsa el icono desbloquear para abrir."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volverlo a intentar"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea para usar el NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 42842fca72e6..8a47781656ad 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kinnitatud"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lõpuleviimiseks puudutage nuppu Kinnita"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Avati näoga. Jätkamiseks vajutage avamise ikooni."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenditud"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Kasuta PIN-koodi"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Kasuta mustrit"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Pühkige avamiseks üles"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Avamiseks vajutage avamise ikooni"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Avati näoga. Avamiseks vajutage avamise ikooni."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Uuesti proovimiseks pühkige üles"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC kasutamiseks avage."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"See seade kuulub teie organisatsioonile"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 53c3698697d7..d832aac2f21e 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Berretsita"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Amaitzeko, sakatu \"Berretsi\""</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Aurpegiaren bidez desblokeatu da. Aurrera egiteko, sakatu desblokeatzeko ikonoa."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikatuta"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Erabili PINa"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Erabili eredua"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Pasatu hatza gora irekitzeko"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Irekitzeko, sakatu desblokeatzeko ikonoa"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Aurpegiaren bidez desblokeatu da. Irekitzeko, sakatu desblokeatzeko ikonoa."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Berriro saiatzeko, pasatu hatza gora"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desblokea ezazu NFC erabiltzeko"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Gailu hau zure erakundearena da"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 38b1f9fcb8c4..93b0b66ea173 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تأیید شد"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"برای تکمیل، روی تأیید ضربه بزنید"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"قفلْ با چهره باز شد. برای ادامه، نماد قفلگشایی را فشار دهید."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"قفلْ با چهره باز شد. برای ادامه، فشار دهید."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چهره شناسایی شد. برای ادامه، فشار دهید."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چهره شناسایی شد. برای ادامه، نماد قفلگشایی را فشار دهید."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"راستیآزماییشده"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"استفاده از پین"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"استفاده از الگو"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"برای باز کردن، انگشتتان را تند بهبالا بکشید"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"برای باز کردن، نماد قفلگشایی را فشار دهید"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"قفلْ با چهره باز شد. برای باز کردن، نماد قفلگشایی را فشار دهید."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"قفلْ با چهره باز شد. برای باز کردن، فشار دهید."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"چهره شناسایی شد. برای باز کردن، فشار دهید."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"چهره شناسایی شد. برای باز کردن، نماد قفلگشایی را فشار دهید."</string> <string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند بهبالا بکشید"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"برای استفاده از NFC، قفل را باز کنید"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"این دستگاه به سازمان شما تعلق دارد"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index c10bfcb7e362..b9b00711eda0 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Vahvistettu"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Valitse lopuksi Vahvista"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Avattu kasvojen avulla. Jatka lukituksen avauskuvakkeella."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Avattu kasvojen avulla. Jatka painamalla."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Kasvot tunnistettu. Jatka painamalla."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Todennettu"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Käytä PIN-koodia"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Käytä kuviota"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Avaa pyyhkäisemällä ylös"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Jatka painamalla lukituksen avauskuvaketta."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Avattu kasvojen avulla. Jatka lukituksen avauskuvakkeella."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Avattu kasvojen avulla. Avaa painamalla."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Kasvot tunnistettu. Avaa painamalla."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string> <string name="keyguard_retry" msgid="886802522584053523">"Yritä uudelleen pyyhkäisemällä ylös"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Avaa lukitus, jotta voit käyttää NFC:tä"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Organisaatiosi omistaa tämän laitteen"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 75e48690c1c2..071b445d9741 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Touchez Confirmer pour terminer"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Déverrouillé avec le visage. Appuyez Déverrouiller pour cont."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifié"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un NIP"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utiliser un schéma"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Balayez l\'écran vers le haut pour ouvrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Appuyez sur l\'icône Déverrouiller pour ouvrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Déverrouillé avec le visage. Appuyez Déverrouiller pour ouvrir"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour utiliser la CCP"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 8854de269557..c042f4ae1841 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Appuyez sur \"Confirmer\" pour terminer"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Déverrouillé par visage. Appuyez sur icône déverrouillage pour continuer."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Déverrouillé par visage. Appuyez pour continuer."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour continuer."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifié"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un code PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utiliser un schéma"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Balayer vers le haut pour ouvrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Appuyez sur l\'icône de déverrouillage pour ouvrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Déverrouillé par visage. Appuyez sur icône déverrouillage pour ouvrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Déverrouillé par visage. Appuyez pour ouvrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Visage reconnu. Appuyez pour ouvrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour ouvrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour pouvoir utiliser NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index d56e2bad2cc7..5b47e522321f 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar o proceso"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Usouse o desbloqueo facial. Preme a icona de desbloquear."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Usouse o desbloqueo facial. Preme para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Recoñeceuse a cara. Preme para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Recoñeceuse a cara. Preme a icona de desbloquear."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrón"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Pasa o dedo cara arriba para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Preme a icona de desbloquear para abrir a porta"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Usouse o desbloqueo facial. Preme a icona de desbloquear."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Usouse o desbloqueo facial. Preme para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Recoñeceuse a cara. Preme para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Recoñeceuse a cara. Preme a icona de desbloquear para abrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Pasa o dedo cara arriba para tentalo de novo"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea o dispositivo para utilizar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence á túa organización."</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 9981769b1ab4..aee9c0d4d6d8 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"પુષ્ટિ કરી"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"પરીક્ષણ પૂર્ણ કરવા કન્ફર્મ કરોને ટૅપ કરો"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ચહેરા દ્વારા અનલૉક કર્યું. આગળ વધવા \'અનલૉક કરો\' આઇકન દબાવો."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"પ્રમાણિત"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"પિનનો ઉપયોગ કરો"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"પૅટર્નનો ઉપયોગ કરો"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ખોલવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ખોલવા માટે \'અનલૉક કરો\' આઇકન દબાવો"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ચહેરા દ્વારા અનલૉક કર્યું. ખોલવા \'અનલૉક કરો\' આઇકન દબાવો."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"ફરી પ્રયાસ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCનો ઉપયોગ કરવા માટે અનલૉક કરો"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"આ ડિવાઇસ તમારી સંસ્થાની માલિકીનું છે"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 416e0c400ce0..8f90f6292d7e 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि हो गई"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"\'पुष्टि करें\' पर टैप करके पूरा करें"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"चेहरे से अनलॉक किया. जारी रखने के लिए, अनलॉक आइकॉन को दबाएं."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"पुष्टि हो गई"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"पिन इस्तेमाल करें"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"पैटर्न इस्तेमाल करें"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"खोलने के लिए ऊपर स्वाइप करें"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"डिवाइस अनलॉक करने के लिए, अनलॉक आइकॉन को दबाएं"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"चेहरे से अनलॉक किया. डिवाइस अनलॉक करने के लिए, अनलॉक आइकॉन को दबाएं."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"फिर से कोशिश करने के लिए ऊपर की ओर स्वाइप करें"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"एनएफ़सी इस्तेमाल करने के लिए स्क्रीन को अनलॉक करें"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 66613d408711..e0cd63939378 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi za dovršetak"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Otključano pomoću lica. Pritisnite ikonu otključavanja da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano pomoću lica. Pritisnite da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste nastavili."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentičnost provjerena"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristite PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristite uzorak"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Prijeđite prstom prema gore da biste otvorili"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pritisnite ikonu otključavanja da biste otvorili"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Otključano pomoću lica. Pritisnite ikonu otključavanja da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Otključano pomoću lica. Pritisnite da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Lice je prepoznato. Pritisnite da biste otvorili."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste otvorili."</string> <string name="keyguard_retry" msgid="886802522584053523">"Prijeđite prstom prema gore za ponovni pokušaj"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste upotrijebili NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 89693de7b5ff..bc8f8ef9d01c 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Megerősítve"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Koppintson a Megerősítés lehetőségre"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Zárolás arccal feloldva. Folytatás: Feloldásra koppintás."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Zárolás arccal feloldva. Koppintson a folytatáshoz."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Arc felismerve. Koppintson a folytatáshoz."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Arc felismerve. A folytatáshoz koppintson a Feloldásra."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Hitelesítve"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-kód használata"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Minta használata"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Csúsztasson felfelé a megnyitáshoz"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Az eszköz használatához nyomja meg a feloldás ikonját"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Zárolás arccal feloldva. Eszköz használata: Feloldás ikon."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Zárolás arccal feloldva. Koppintson az eszköz használatához."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Arc felismerve. Koppintson az eszköz használatához."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Arc felismerve. Eszköz használata: Feloldás ikon."</string> <string name="keyguard_retry" msgid="886802522584053523">"Az újrapróbálkozáshoz csúsztassa felfelé az ujját"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Az NFC használatához oldja fel a képernyőzárat"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ez az eszköz az Ön szervezetének tulajdonában van"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index e21f8e0f044f..8a6949a6b5df 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Հաստատվեց"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ավարտելու համար հպեք «Հաստատել»"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ապակողպվել է դեմքով։ Սեղմեք ապակողպման պատկերակը։"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ապակողպվել է դեմքով։ Սեղմեք շարունակելու համար։"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Դեմքը ճանաչվեց։ Սեղմեք շարունակելու համար։"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Դեմքը ճանաչվեց։ Սեղմեք ապակողպման պատկերակը։"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Նույնականացված է"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Օգտագործել PIN կոդ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Օգտագործել նախշ"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Բացելու համար սահեցրեք վերև"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Բացեք՝ սեղմելով ապակողպման պատկերակը"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ապակողպվել է դեմքով։ Բացեք՝ սեղմելով ապակողպման պատկերակը։"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ապակողպվել է դեմքով։ Սեղմեք բացելու համար։"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Դեմքը ճանաչվեց։ Սեղմեք բացելու համար։"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Դեմքը ճանաչվեց։ Բացելու համար սեղմեք ապակողպման պատկերակը։"</string> <string name="keyguard_retry" msgid="886802522584053523">"Սահեցրեք վերև՝ նորից փորձելու համար"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ապակողպեք՝ NFC-ն օգտագործելու համար"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Այս սարքը պատկանում է ձեր կազմակերպությանը"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 3a15692f3e58..59a3ede831b1 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Dikonfirmasi"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketuk Konfirmasi untuk menyelesaikan"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Kunci dibuka dengan wajah. Tekan ikon buka kunci untuk melanjutkan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Kunci dibuka dengan wajah. Tekan untuk melanjutkan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dikenali. Tekan untuk melanjutkan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dikenali. Tekan ikon buka kunci untuk melanjutkan."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Diautentikasi"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gunakan PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gunakan pola"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Geser ke atas untuk membuka"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tekan ikon buka kunci untuk membuka"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Kunci dibuka dengan wajah. Tekan ikon buka kunci untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Kunci dibuka dengan wajah. Tekan untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Wajah dikenali. Tekan untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Wajah dikenali. Tekan ikon buka kunci untuk membuka."</string> <string name="keyguard_retry" msgid="886802522584053523">"Geser ke atas untuk mencoba lagi"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Perangkat ini milik organisasi Anda"</string> @@ -333,7 +339,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya dengan lambat • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi Daya dengan Dok • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Beralih pengguna"</string> - <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data di sesi ini akan dihapus."</string> + <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua aplikasi dan data dalam sesi ini akan dihapus."</string> <string name="guest_wipe_session_title" msgid="7147965814683990944">"Selamat datang kembali, tamu!"</string> <string name="guest_wipe_session_message" msgid="3393823610257065457">"Lanjutkan sesi Anda?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Mulai ulang"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 5ddb0a358735..779de2dccda5 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Staðfest"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ýttu á „Staðfesta“ til að ljúka"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Opnað með andliti. Ýttu á táknið taka úr lás til að halda áfram."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Opnað með andliti. Ýttu til að halda áfram."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Andlitið var greint. Ýttu til að halda áfram."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Andlitið var greint. Ýttu á opnunartáknið til að halda áfr."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Auðkennt"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Nota PIN-númer"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Nota mynstur"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Strjúktu upp til að opna"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Ýttu á táknið til að taka úr lás til að opna"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Opnað með andliti. Ýttu á táknið taka úr lás til að opna."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Opnað með andliti. Ýttu til að opna."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Andlitið var greint. Ýttu til að opna."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Andlitið var greint. Ýttu á opnunartáknið til að opna."</string> <string name="keyguard_retry" msgid="886802522584053523">"Strjúktu upp til að reyna aftur"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Taktu úr lás til að nota NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Þetta tæki tilheyrir fyrirtækinu þínu"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 55c854b5d361..c24dd863b137 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confermato"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tocca Conferma per completare"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Sbloccato con il volto. Premi l\'icona Sblocca e continua."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Sbloccato con il volto. Premi per continuare."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Volto riconosciuto. Premi per continuare."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Volto riconosciuto. Premi l\'icona Sblocca e continua."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticazione eseguita"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilizza PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usa sequenza"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Scorri verso l\'alto per aprire"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Premi l\'icona Sblocca per aprire"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Sbloccato con il volto. Premi l\'icona Sblocca per aprire."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Sbloccato con il volto. Premi per aprire."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Volto riconosciuto. Premi per aprire."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Volto riconosciuto. Premi l\'icona Sblocca per aprire."</string> <string name="keyguard_retry" msgid="886802522584053523">"Scorri verso l\'alto per riprovare"</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> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 6cbc0a57f535..76e64917b1a0 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"יש אישור"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"יש להקיש על \'אישור\' לסיום התהליך"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"הנעילה בוטלה בזיהוי פנים. להמשך, לוחצים על סמל ביטול הנעילה."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"מאומת"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"שימוש בקוד אימות"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"שימוש בקו ביטול נעילה"</string> @@ -316,6 +322,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"צריך להחליק כדי לפתוח"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"לפתיחה, לוחצים על סמל ביטול הנעילה"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"הנעילה בוטלה בזיהוי פנים. פותחים בלחיצה על סמל ביטול הנעילה."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"יש להחליק למעלה כדי לנסות שוב"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"יש לבטל את הנעילה כדי להשתמש ב-NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"המכשיר הזה שייך לארגון שלך"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 4b7e130c5c04..cb459e994783 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認しました"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"完了するには [確認] をタップしてください"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"顔でロック解除しました。ロック解除アイコンを押して続行します。"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"認証済み"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN を使用"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"パターンを使用"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"開くには上にスワイプします"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ロック解除アイコンを押して開きます"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"顔でロック解除しました。ロック解除アイコンを押して開きます。"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"上にスワイプしてもう一度お試しください"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC を使用するには、ロックを解除してください"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"これは組織が所有するデバイスです"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 160927f13492..70a3ad640dbf 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"დადასტურებული"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"დასასრულებლად შეეხეთ „დადასტურებას“"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"განიბლოკა სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"განიბლოკა სახით. დააჭირეთ გასაგრძელებლად."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ამოცნობილია სახით. დააჭირეთ გასაგრძელებლად."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ამოცნობილია სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ავტორიზებულია"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-კოდის გამოყენება"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ნიმუშის გამოყენება"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"გასახსნელად გადაფურცლეთ ზემოთ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"გასახსნელად დააჭირეთ განბლოკვის ხატულას"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"განიბლოკა სახით. გასახსნელად დააჭირეთ განბლოკვის ხატულას."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"განიბლოკა სახით. დააჭირეთ გასახსნელად."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ამოცნობილია სახით. დააჭირეთ გასახსნელად."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ამოცნობილია სახით. გასახსნელად დააჭირეთ განბლოკვის ხატულას."</string> <string name="keyguard_retry" msgid="886802522584053523">"ხელახლა საცდელად გადაფურცლეთ ზემოთ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"განბლოკეთ NFC-ის გამოსაყენებლად"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 6b233c89f536..9dbea982095c 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Расталды"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Аяқтау үшін \"Растау\" түймесін түртіңіз."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Бет үлгісі арқылы ашылды. Жалғастыру үшін құлыпты ашу белгішесін басыңыз."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аутентификацияланған"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN кодын пайдалану"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Өрнекті пайдалану"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Ашу үшін жоғары қарай сырғытыңыз."</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Ашу үшін құлыпты ашу белгішесін басыңыз."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Бет үлгісі арқылы ашылды. Ашу үшін құлыпты ашу белгішесін басыңыз."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Әрекетті қайталау үшін жоғары сырғытыңыз."</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC пайдалану үшін құлыпты ашыңыз."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Бұл құрылғы ұйымыңызға тиесілі."</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 7dcf066e2891..3d8504e83044 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"បានបញ្ជាក់"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ចុច \"បញ្ជាក់\" ដើម្បីបញ្ចប់"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"បានដោះសោដោយប្រើមុខ។ សូមចុចរូបដោះសោ ដើម្បីបន្ត។"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"បានផ្ទៀងផ្ទាត់"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ប្រើកូដ PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ប្រើលំនាំ"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"អូសឡើងលើដើម្បីបើក"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ចុចរូបដោះសោ ដើម្បីបើក"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"បានដោះសោដោយប្រើមុខ។ សូមចុចរូបដោះសោ ដើម្បីបើក។"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"អូសឡើងលើ ដើម្បីព្យាយាមម្ដងទៀត"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ដោះសោ ដើម្បីប្រើ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ឧបករណ៍នេះគឺជាកម្មសិទ្ធិរបស់ស្ថាប័នអ្នក"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index f6a38b84d699..0ce8ff8bee18 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ಪೂರ್ಣಗೊಳಿಸಲು ದೃಢೀಕರಿಸಿ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಅನ್ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ಪಿನ್ ಬಳಸಿ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ಪ್ಯಾಟರ್ನ್ ಬಳಸಿ"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ತೆರೆಯಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ತೆರೆಯಲು ಅನ್ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ತೆರೆಯಲು ಅನ್ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ಬಳಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 1f4f913a5ae2..c0d827996ad9 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"확인함"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"완료하려면 확인을 탭하세요."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"얼굴 인식으로 잠금 해제되었습니다. 계속하려면 잠금 해제 아이콘을 누르세요."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"인증됨"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN 사용"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"패턴 사용"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"위로 스와이프하여 열기"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"기기를 열려면 잠금 해제 아이콘을 누르세요."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"얼굴 인식으로 잠금 해제되었습니다. 기기를 열려면 잠금 해제 아이콘을 누르세요."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"위로 스와이프하여 다시 시도해 주세요"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"잠금 해제하여 NFC 사용"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"내 조직에 속한 기기입니다."</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 9314c9d0f9f7..2bef2b3b5a55 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ырасталды"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Бүтүрүү үчүн \"Ырастоо\" баскычын басыңыз"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Кулпусун жүзүңүз менен ачтыңыз. Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Кулпусун жүзүңүз менен ачтыңыз. Улантуу үчүн басыңыз."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Жүз таанылды. Улантуу үчүн басыңыз."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Жүз таанылды. Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аныктыгы текшерилди"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN кодду колдонуу"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Графикалык ачкычты колдонуу"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Ачуу үчүн өйдө сүрүңүз"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Ачуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Кулпусун жүзүңүз менен ачтыңыз. Ачуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Кулпусун жүзүңүз менен ачтыңыз. Ачуу үчүн басыңыз."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Жүз таанылды. Ачуу үчүн басыңыз."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Жүз таанылды. Ачуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string> <string name="keyguard_retry" msgid="886802522584053523">"Кайталоо үчүн экранды өйдө сүрүңүз"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC колдонуу үчүн түзмөктүн кулпусун ачыңыз"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Бул түзмөк уюмуңузга таандык"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 2a52ab60364e..685839562e7f 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ຢືນຢັນແລ້ວ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ແຕະຢືນຢັນເພື່ອສຳເລັດ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ຮັບຮອງຄວາມຖືກຕ້ອງແລ້ວ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ໃຊ້ PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ໃຊ້ຮູບແບບ"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ປັດຂຶ້ນເພື່ອເປີດ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ກົດໄອຄອນປົດລັອກເພື່ອເປີດ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອເປີດ."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດເພື່ອເປີດ."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດເພື່ອເປີດ."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອເປີດ."</string> <string name="keyguard_retry" msgid="886802522584053523">"ປັດຂຶ້ນເພື່ອລອງໃໝ່"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ປົດລັອກເພື່ອໃຊ້ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 6a7898a2e2fe..f5967208d9d7 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Patvirtinta"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Paliesk. „Patvirtinti“, kad užbaigtumėte"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Atrakinta pagal veidą. Pasp. atrak. pikt., kad tęstumėte."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikuota"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Naudoti PIN kodą"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Naudoti atrakinimo piešinį"</string> @@ -316,6 +322,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Perbraukite aukštyn, kad atidarytumėte"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Paspauskite atrakinimo piktogramą, kad atidarytumėte"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Atrakinta pagal veidą. Pasp. atr. pikt., kad atidarytumėte."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Jei norite bandyti dar kartą, perbraukite aukštyn"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Norėdami naudoti NFC, atrakinkite"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Šis įrenginys priklauso jūsų organizacijai"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index b53e763470dc..7f98fed592c8 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Apstiprināts"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lai pabeigtu, pieskarieties Apstiprināt"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Atbloķēta ar seju. Turpināt: nospiediet atbloķēšanas ikonu."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikācija veikta"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Izmantot PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Izmantot kombināciju"</string> @@ -314,6 +320,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Velciet augšup, lai atvērtu"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Lai atvērtu, nospiediet atbloķēšanas ikonu"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Atbloķēta ar seju. Atvērt: nospiediet atbloķēšanas ikonu."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Velciet augšup, lai mēģinātu vēlreiz"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Atbloķējiet ierīci, lai izmantotu NFC."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Šī ierīce pieder jūsu organizācijai."</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 2dee0e053d2c..060e964fd4f3 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврдено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Допрете „Потврди“ за да се заврши"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Отклучено со лице. Притиснете ја иконата за отклучување за да продолжите."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Проверена"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Користи PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Користи шема"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Повлечете за да отворите"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Притиснете ја иконата за отклучување за да отворите"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Отклучено со лице. Притиснете ја иконата за отклучување за да отворите."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Повлечете нагоре за да се обидете повторно"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отклучете за да користите NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Уредов е во сопственост на организацијата"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index e32e3051e7ea..38a43172bd4b 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"സ്ഥിരീകരിച്ചു"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"പൂർത്തിയാക്കാൻ സ്ഥിരീകരിക്കുക ടാപ്പ് ചെയ്യൂ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുടരാൻ അമർത്തുക."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അമർത്തുക."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"പരിശോധിച്ചുറപ്പിച്ചു"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"പിൻ ഉപയോഗിക്കുക"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"പാറ്റേൺ ഉപയോഗിക്കുക"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"തുറക്കാൻ മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"തുറക്കാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുറക്കാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തു. തുറക്കാൻ അമർത്തുക."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"മുഖം തിരിച്ചറിഞ്ഞു. തുറക്കാൻ അമർത്തുക."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"മുഖം തിരിച്ചറിഞ്ഞു. തുറക്കാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string> <string name="keyguard_retry" msgid="886802522584053523">"വീണ്ടും ശ്രമിക്കാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റേതാണ്"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index b953a28fee35..13aedc78cca6 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Баталгаажсан"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Дуусгахын тулд баталгаажуулахыг товших"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд дарна уу."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Царайг таньсан. Үргэлжлүүлэхийн тулд дарна уу."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Царайг таньсан. Үргэлжлүүлэх бол түгжээг тайлах дүрсийг дар."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Баталгаажуулагдсан"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ПИН ашиглах"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Хээ ашиглах"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Нээхийн тулд дээш шударна уу"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Нээхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Царайгаар түгжээг тайлсан. Нээхийн тулд түгжээг тайлах дүрс тэмдэг дээр дараарай."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Царайгаар түгжээг тайлсан. Нээхийн тулд дарна уу."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Царайг таньсан. Нээхийн тулд дарна уу."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Царайг таньсан. Нээх бол түгжээг тайлах дүрсийг дарна уу."</string> <string name="keyguard_retry" msgid="886802522584053523">"Дахин оролдохын тулд дээш шударна уу"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC-г ашиглахын тулд түгжээг тайлна уу"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Энэ төхөөрөмж танай байгууллагад харьяалагддаг"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 4add96d210e8..1424efcc12de 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"निश्चित केले"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूर्ण करण्यासाठी खात्री करा वर टॅप करा"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"चेहऱ्याने अनलॉक केले. सुरू ठेवण्यासाठी अनलॉक करा आयकन दाबा."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ऑथेंटिकेशन केलेले"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"पिन वापरा"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"पॅटर्न वापरा"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"उघडण्यासाठी वर स्वाइप करा"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"उघडण्यासाठी अनलॉक करा आयकन दाबा"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"चेहऱ्याने अनलॉक केले. उघडण्यासाठी अनलॉक करा आयकन दाबा."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"पुन्हा प्रयत्न करण्यासाठी वर स्वाइप करा"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC वापरण्यासाठी स्क्रीन अनलॉक करा"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"हे डिव्हाइस तुमच्या संस्थेचे आहे"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 4b31112a58f4..4c90c882ad4e 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Disahkan"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketik Sahkan untuk menyelesaikan"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Dibuka kunci dengan wajah. Tekan ikon buka kunci untuk teruskan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Dibuka kunci dengan wajah. Tekan untuk meneruskan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dicam. Tekan untuk meneruskan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dicam. Tekan ikon buka kunci untuk meneruskan."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Disahkan"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gunakan PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gunakan corak"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Leret ke atas untuk buka"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tekan ikon buka kunci untuk buka"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Dibuka kunci dengan wajah. Tekan ikon buka kunci untuk buka."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Dibuka kunci dengan wajah. Tekan untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Wajah dicam. Tekan untuk membuka."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Wajah dicam. Tekan ikon buka kunci untuk membuka."</string> <string name="keyguard_retry" msgid="886802522584053523">"Leret ke atas untuk mencuba lagi"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Peranti ini milik organisasi anda"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 6f9250cc2c36..726093662ff4 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"အတည်ပြုပြီးပြီ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"အပြီးသတ်ရန်အတွက် \'အတည်ပြုရန်\' ကို တို့ပါ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ရှေ့ဆက်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"အထောက်အထားစိစစ်ပြီးပြီ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ပင်နံပါတ်သုံးရန်"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ပုံစံကို သုံးရန်"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ဖွင့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ဖွင့်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ဖွင့်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ဖွင့်ရန် နှိပ်ပါ။"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"မျက်နှာ မှတ်မိသည်။ ဖွင့်ရန် နှိပ်ပါ။"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"မျက်နှာ မှတ်မိသည်။ ဖွင့်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string> <string name="keyguard_retry" msgid="886802522584053523">"ထပ်စမ်းကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ကို အသုံးပြုရန် လော့ခ်ဖွင့်ပါ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index c946ca58c262..8c9a26233b95 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekreftet"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trykk på Bekreft for å fullføre"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Låst opp med ansiktet. Trykk på lås opp-ikon for å fortsette"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst opp med ansiktet. Trykk for å fortsette."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet er gjenkjent. Trykk for å fortsette."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentisert"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Bruk PIN-kode"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Bruk mønster"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Sveip opp for å åpne"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Trykk på lås opp-ikonet for å åpne"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Låst opp med ansiktet. Trykk på lås opp-ikon for å fortsette"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Låst opp med ansiktet. Trykk for å åpne."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ansiktet er gjenkjent. Trykk for å åpne."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string> <string name="keyguard_retry" msgid="886802522584053523">"Sveip opp for å prøve igjen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås opp for å bruke NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enheten tilhører organisasjonen din"</string> @@ -333,7 +339,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader sakte • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="6150404291427377863">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ladedokk • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Bytt bruker"</string> - <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle appene og all informasjon i denne økten slettes."</string> + <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apper og data i denne økten blir slettet."</string> <string name="guest_wipe_session_title" msgid="7147965814683990944">"Velkommen tilbake, gjest!"</string> <string name="guest_wipe_session_message" msgid="3393823610257065457">"Vil du fortsette økten?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Start på nytt"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index d285c76e49f8..9fa75a8a0f2e 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि भयो"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूरा गर्नका लागि पुष्टि गर्नुहोस् नामक विकल्पमा ट्याप गर्नुहोस्"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"अनुहार प्रयोग गरी अनलक गरियो। जारी राख्न अनलक आइकनमा थिच्नुहोस्।"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"प्रमाणीकरण गरियो"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN प्रयोग गर्नुहोस्"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ढाँचा प्रयोग गर्नुहोस्"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"खोल्न माथितिर स्वाइप गर्नुहोस्"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"खोल्न अनलक आइकनमा थिच्नुहोस्"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"अनुहार प्रयोग गरी अनलक गरियो। खोल्न अनलक आइकनमा थिच्नुहोस्।"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"फेरि प्रयास गर्न माथितिर स्वाइप गर्नुहोस्"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC प्रयोग गर्न स्क्रिन अनलक गर्नुहोस्"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"यो डिभाइस तपाईंको सङ्गठनको स्वामित्वमा छ"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index af703fda6c78..6235dd555903 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestigd"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestigen om te voltooien"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ontgrendeld via gezicht. Druk op het ontgrendelicoon."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontgrendeld via gezicht. Druk om door te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gezicht herkend. Druk om door te gaan."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gezicht herkend. Druk op het ontgrendelicoon."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Geverifieerd"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Pincode gebruiken"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Patroon gebruiken"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe omhoog om te openen"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Druk op het ontgrendelicoon om te openen"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ontgrendeld via gezicht. Druk op het ontgrendelicoon."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Ontgrendeld via gezicht. Druk om te openen."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Gezicht herkend. Druk om te openen."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gezicht herkend. Druk op het ontgrendelicoon."</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe omhoog om het opnieuw te proberen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontgrendel het apparaat om NFC te gebruiken"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dit apparaat is eigendom van je organisatie"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 61be8439ccf7..a8299a571ed5 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ସୁନିଶ୍ଚିତ କରାଯାଇଛି"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ସୁନିଶ୍ଚିତ କରନ୍ତୁରେ ଟାପ୍ କରନ୍ତୁ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ପ୍ରାମାଣିକତା ହୋଇଛି"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ପାଟର୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ଖୋଲିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ଖୋଲିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଖୋଲିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"ପୁଣି ଚେଷ୍ଟା କରିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index e03dbf34fd96..ff40b5500d1b 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ਪੁਸ਼ਟੀ ਕੀਤੀ ਗਈ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ਪੂਰਾ ਕਰਨ ਲਈ ਪੁਸ਼ਟੀ ਕਰੋ \'ਤੇ ਟੈਪ ਕਰੋ"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ਪਿੰਨ ਵਰਤੋ"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ਪੈਟਰਨ ਵਰਤੋ"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"ਖੋਲ੍ਹਣ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"ਖੋਲ੍ਹਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਖੋਲ੍ਹਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਉੱਤੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 0ebbb4999c1b..d439def90141 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potwierdzono"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Aby zakończyć, kliknij Potwierdź"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odblokowano skanem twarzy. Aby kontynuować, kliknij ikonę odblokowywania."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Uwierzytelniono"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Użyj kodu PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Użyj wzoru"</string> @@ -316,6 +322,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Przesuń w górę, by otworzyć"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Aby otworzyć, kliknij ikonę odblokowywania"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Odblokowano skanem twarzy. Aby otworzyć, kliknij ikonę odblokowywania."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Przesuń w górę, by spróbować ponownie"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odblokuj, by użyć komunikacji NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"To urządzenie należy do Twojej organizacji"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 8ae76bc6381d..36ac0d247aaa 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Deslize para cima para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pressione o ícone de desbloqueio para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueado pelo rosto. Pressione para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rosto reconhecido. Pressione para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Pressione o ícone de desbloq. para abrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index f9c4bee31359..fc40c5d930e9 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em Confirmar para concluir."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado c/ rosto. Prima o ícone de desb. p/ continuar."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utilizar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utilizar padrão"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Deslize rapidamente para cima para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Prima o ícone de desbloqueio para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueado com o rosto. Prima o ícone de desbl. p/ abrir."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Deslize rapidamente para cima para tentar novamente."</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquear para utilizar o NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua entidade."</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 8ae76bc6381d..36ac0d247aaa 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Deslize para cima para abrir"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pressione o ícone de desbloqueio para abrir"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Desbloqueado pelo rosto. Pressione o ícone de desbloqueio para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Desbloqueado pelo rosto. Pressione para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Rosto reconhecido. Pressione para abrir."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Pressione o ícone de desbloq. para abrir."</string> <string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index d37b52bf5cde..683b3952b9fa 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Atingeți Confirmați pentru a finaliza"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"S-a deblocat cu ajutorul feței. Apăsați pictograma de deblocare pentru a continua"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"S-a deblocat cu ajutorul feței. Apăsați pentru a continua."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Chipul a fost recunoscut. Apăsați pentru a continua."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Chip recunoscut. Apăsați pictograma de deblocare să continuați."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentificat"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Folosiți PIN-ul"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Folosiți modelul"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Glisați în sus pentru a deschide"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Apăsați pictograma de deblocare pentru a deschide"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"S-a deblocat cu ajutorul feței. Apăsați pictograma de deblocare pentru a deschide"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"S-a deblocat cu ajutorul feței. Apăsați pentru a deschide."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Chipul a fost recunoscut. Apăsați pentru a deschide."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Chip recunoscut. Apăsați pictograma de deblocare pentru a deschide"</string> <string name="keyguard_retry" msgid="886802522584053523">"Glisați pentru a încerca din nou"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Deblocați pentru a folosi NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dispozitivul aparține organizației dvs."</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index e1b48cd88376..573335217090 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Подтверждено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Нажмите \"Подтвердить\""</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Сканирование выполнено. Нажмите на значок разблокировки."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблокировано сканированием лица. Нажмите, чтобы продолжить."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицо распознано. Нажмите, чтобы продолжить."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицо распознано. Нажмите на значок разблокировки."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аутентификация выполнена"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Использовать графический ключ"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Проведите вверх, чтобы открыть"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Нажмите на значок разблокировки."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Сканирование выполнено. Нажмите на значок разблокировки."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Разблокировано сканированием лица. Нажмите, чтобы открыть."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лицо распознано. Нажмите, чтобы открыть."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицо распознано. Нажмите на значок разблокировки."</string> <string name="keyguard_retry" msgid="886802522584053523">"Чтобы повторить попытку, проведите вверх"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Чтобы использовать NFC, разблокируйте устройство."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Это устройство принадлежит вашей организации"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index a3a8534d4136..65a07ef8d1a8 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"තහවුරු කළා"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"සම්පූර්ණ කිරීමට තහවුරු කරන්න තට්ටු කර."</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"මුහුණ මගින් අගුලු හරින ලදි. දිගටම කරගෙන යාමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"මුහුණ මගින් අගුලු හරින ලදි. ඉදිරියට යාමට ඔබන්න."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට ඔබන්න."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"සත්යාපනය විය"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN භාවිත කරන්න"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"රටාව භාවිත කරන්න"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"විවෘත කිරීමට ස්වයිප් කරන්න"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"විවෘත කිරීමට අගුලු හැරීමේ නිරූපකය ඔබන්න"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"මුහුණ මගින් අගුලු හරින ලදි. විවෘත කිරීමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"මුහුණ මගින් අගුලු හරින ලදි. විවෘත කිරීමට ඔබන්න."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"මුහුණ හඳුනා ගන්නා ලදි. විවෘත කිරීමට ඔබන්න."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"මුහුණ හඳුනා ගන්නා ලදි. විවෘත කිරීමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string> <string name="keyguard_retry" msgid="886802522584053523">"නැවත උත්සාහ කිරීමට ඉහළට ස්වයිප් කරන්න"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC භාවිත කිරීමට අගුලු හරින්න"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 2d468298a21f..0b46c880c383 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrdené"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Overenie dokončíte klepnutím na Potvrdiť"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odomknuté tvárou. Pokračujte klepnutím na ikonu odomknutia"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odomknuté tvárou. Pokračujte stlačením."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Tvár bola rozpoznaná. Pokračujte stlačením."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Tvár bola rozpoznaná. Pokračujte stlačením ikony odomknutia"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Overené"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Použiť PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Použiť vzor"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Otvorte potiahnutím prstom nahor"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Otvorte klepnutím na ikonu odomknutia"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Odomknuté tvárou. Otvorte klepnutím na ikonu odomknutia."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odomknuté tvárou. Otvorte stlačením."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Tvár bola rozpoznaná. Otvorte stlačením."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Tvár bola rozpoznaná. Otvorte stlačením ikony odomknutia."</string> <string name="keyguard_retry" msgid="886802522584053523">"Potiahnutím nahor to skúste znova"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ak chcete použiť NFC, odomknite"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zariadenie patrí vašej organizácii"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index aab95f10a162..8f15cfd7b3c7 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potrjeno"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Za dokončanje se dotaknite »Potrdite«"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Odklenjeno z obrazom. Za nadaljevanje pritisnite ikono za odklepanje."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odklenjeno z obrazom. Pritisnite za nadaljevanje."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obraz je prepoznan. Pritisnite za nadaljevanje."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obraz je prepoznan. Za nadaljevanje pritisnite ikono za odklepanje."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Preverjena pristnost"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Uporabi kodo PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Uporabi vzorec"</string> @@ -316,6 +319,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Povlecite navzgor, da odprete"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Za odpiranje pritisnite ikono za odklepanje."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Odklenjeno z obrazom. Za odpiranje pritisnite ikono za odklepanje."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Odklenjeno z obrazom. Pritisnite za odpiranje."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Obraz je prepoznan. Pritisnite za odpiranje."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Obraz je prepoznan. Za odpiranje pritisnite ikono za odklepanje."</string> <string name="keyguard_retry" msgid="886802522584053523">"Povlecite navzgor za vnovičen poskus"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odklenite napravo, če želite uporabljati NFC."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ta naprava pripada vaši organizaciji"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 42aae9f736cb..0205062fc9e1 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Konfirmuar"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trokit \"Konfirmo\" për ta përfunduar"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"U shkyç me fytyrë. Shtyp ikonën e shkyçjes për të vazhduar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"U shkyç me fytyrë. Shtyp për të vazhduar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Fytyra u njoh. Shtyp për të vazhduar."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Fytyra u njoh. Shtyp ikonën e shkyçjes për të vazhduar."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"U vërtetua"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Përdor kodin PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Përdor motivin"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Rrëshqit lart për ta hapur"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Shtyp ikonën e shkyçjes për ta hapur"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"U shkyç me fytyrë. Shtyp ikonën e shkyçjes për ta hapur."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"U shkyç me fytyrë. Shtyp për ta hapur."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Fytyra u njoh. Shtyp për ta hapur."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Fytyra u njoh. Shtyp ikonën e shkyçjes për ta hapur."</string> <string name="keyguard_retry" msgid="886802522584053523">"Rrëshqit lart për të provuar përsëri"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Shkyçe për të përdorur NFC-në"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Kjo pajisje i përket organizatës sate"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 8b9b08841b3b..7d85e4c2b1ce 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврђено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Додирните Потврди да бисте завршили"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Откључано је лицем. Притисните икону откључавања за наставак"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Откључано је лицем. Притисните да бисте наставили."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лице је препознато. Притисните да бисте наставили."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лице препознато. Притисните икону откључавања за наставак."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Идентитет је потврђен"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Користите PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Користите шаблон"</string> @@ -314,6 +317,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Превуците нагоре да бисте отворили"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Притисните икону откључавања за отварање"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Откључано је лицем. Притисните икону откључавања за отварање"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Откључано је лицем. Притисните да бисте отворили."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Лице је препознато. Притисните да бисте отворили."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лице препознато. Притисните икону откључавања за отварање."</string> <string name="keyguard_retry" msgid="886802522584053523">"Превуците нагоре да бисте пробали поново"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Откључајте да бисте користили NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Овај уређај припада организацији"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 9206685be801..4ed90a6a72b4 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekräftat"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Slutför genom att trycka på Bekräfta"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Upplåst med ansiktslås. Tryck på ikonen lås upp för att fortsätta."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Upplåst med ansiktslås. Tryck för att fortsätta."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet har identifierats. Tryck för att fortsätta."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentiserad"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Använd pinkod"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Använd mönster"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Öppna genom att svepa uppåt"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Tryck på ikonen lås upp för att öppna"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Upplåst med ansiktslås. Tryck på ikonen lås upp för att öppna."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Upplåst med ansiktslås. Tryck för att öppna."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Ansiktet har identifierats. Tryck för att öppna."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string> <string name="keyguard_retry" msgid="886802522584053523">"Svep uppåt om du vill försöka igen"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås upp om du vill använda NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Den här enheten tillhör organisationen"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index ad5d132f2fcb..23acb097ddc2 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Imethibitishwa"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Gusa Thibitisha ili ukamilishe"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Imefunguliwa kwa kutumia uso wako. Bonyeza aikoni ya kufungua ili uendelee."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Imefunguliwa kwa kutumia uso wako. Bonyeza ili uendelee."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Uso umetambuliwa. Bonyeza ili uendelee."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili uendelee."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Umethibitishwa"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Tumia PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Tumia mchoro"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Telezesha kidole juu ili ufungue"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Bonyeza aikoni ya kufungua ili ufungue"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Imefunguliwa kwa kutumia uso wako. Bonyeza aikoni ya kufungua ili ufungue."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Imefunguliwa kwa kutumia uso wako. Bonyeza ili ufungue."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Uso umetambuliwa. Bonyeza ili ufungue."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili ufungue."</string> <string name="keyguard_retry" msgid="886802522584053523">"Telezesha kidole juu ili ujaribu tena"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Fungua ili utumie NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Kifaa hiki kinamilikiwa na shirika lako"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index d66bc4117897..a9dec1f77f69 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"உறுதிப்படுத்தப்பட்டது"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"முடிக்க \'உறுதிப்படுத்துக\' என்பதை தட்டவும்"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"முகம் மூலம் அன்லாக் செய்யப்பட்டது. தொடர, அன்லாக் ஐகானை அழுத்துக."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"அங்கீகரிக்கப்பட்டது"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"பின்னைப் பயன்படுத்து"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"பேட்டர்னைப் பயன்படுத்து"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"திறப்பதற்கு மேல் நோக்கி ஸ்வைப் செய்யவும்"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"திறக்க, அன்லாக் ஐகானை அழுத்தவும்"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"முகம் மூலம் அன்லாக் செய்யப்பட்டது. திறக்க, அன்லாக் ஐகானை அழுத்துக."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"மீண்டும் முயல மேல்நோக்கி ஸ்வைப் செய்யவும்"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCயைப் பயன்படுத்த அன்லாக் செய்யவும்"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு சொந்தமானது"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 871282538090..3cc3d2613126 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"నిర్ధారించబడింది"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"పూర్తి చేయడానికి \"నిర్ధారించు\" నొక్కండి"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ముఖం ద్వారా అన్లాక్ చేయబడింది. కొనసాగించడానికి అన్లాక్ చిహ్నాన్ని నొక్కండి."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ప్రామాణీకరించబడింది"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"పిన్ను ఉపయోగించు"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ఆకృతిని ఉపయోగించు"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"తెరవడానికి, పైకి స్వైప్ చేయండి"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"తెరవడానికి అన్లాక్ చిహ్నాన్ని నొక్కండి"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ముఖం ద్వారా అన్లాక్ చేయబడింది. తెరవడానికి అన్లాక్ చిహ్నాన్ని నొక్కండి."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"మళ్ళీ ప్రయత్నించడానికి పైకి స్వైప్ చేయండి"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCని ఉపయోగించడానికి అన్లాక్ చేయండి"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ఈ పరికరం మీ సంస్థకు చెందినది"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 434c4f01c3a4..97806cea044b 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ยืนยันแล้ว"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"แตะยืนยันเพื่อดำเนินการให้เสร็จสมบูรณ์"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"ปลดล็อกด้วยใบหน้าแล้ว กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ปลดล็อกด้วยใบหน้าแล้ว กดเพื่อดำเนินการต่อ"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"จดจำใบหน้าได้ กดเพื่อดำเนินการต่อ"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"ตรวจสอบสิทธิ์แล้ว"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"ใช้ PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"ใช้รูปแบบ"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"เลื่อนขึ้นเพื่อเปิด"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"กดไอคอนปลดล็อกเพื่อเปิด"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"ปลดล็อกด้วยใบหน้าแล้ว กดไอคอนปลดล็อกเพื่อเปิด"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"ปลดล็อกด้วยใบหน้าแล้ว กดเพื่อเปิด"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"จดจำใบหน้าได้ กดเพื่อเปิด"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อเปิด"</string> <string name="keyguard_retry" msgid="886802522584053523">"เลื่อนขึ้นเพื่อลองอีกครั้ง"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ปลดล็อกเพื่อใช้ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 65c09eb558ea..294fa006f861 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Nakumpirma"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"I-tap ang Kumpirmahin para kumpletuhin"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Na-unlock gamit ang mukha. Pindutin ang icon ng unlock para magpatuloy."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Na-unlock gamit ang mukha. Pindutin para magpatuloy."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nakilala ang mukha. Pindutin para magpatuloy."</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nakilala ang mukha. Pindutin ang unlock para magpatuloy."</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Na-authenticate"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Gumamit ng PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Gumamit ng pattern"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Mag-swipe pataas para buksan"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Pindutin ang icon ng unlock para buksan"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Na-unlock gamit ang mukha. Pindutin ang icon ng unlock para buksan."</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"Na-unlock gamit ang mukha. Pindutin para buksan."</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"Nakilala ang mukha. Pindutin para buksan."</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Nakilala ang mukha. Pindutin ang icon ng unlock para buksan."</string> <string name="keyguard_retry" msgid="886802522584053523">"Mag-swipe pataas para subukan ulit"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"I-unlock para magamit ang NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Pagmamay-ari ng iyong organisasyon ang device na ito"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index b7415fd4ee94..efa4043b0377 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Onaylandı"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamak için Onayla\'ya dokunun"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Kilit, yüzünüzle açıldı. Kilit açma simgesine basın."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Kimliği Doğrulandı"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN kullan"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Deseni kullan"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Açmak için yukarı kaydırın"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Açmak için Kilit açma simgesine basın"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Kilit, yüzünüzle açıldı. Kilit açma simgesine basın."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Tekrar denemek için yukarı kaydırın"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC\'yi kullanmak için kilidi açın"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz, kuruluşunuza ait"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 7a2419117d2e..66de3bbeabe6 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Підтверджено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Щоб завершити, натисніть \"Підтвердити\""</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Розблоковано (фейсконтроль). Натисніть значок розблокування."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Автентифіковано"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Ввести PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Намалювати ключ"</string> @@ -316,6 +322,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Проведіть пальцем угору, щоб відкрити"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Щоб відкрити, натисніть значок розблокування."</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Розблоковано (фейсконтроль). Натисніть значок розблокування."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Проведіть пальцем угору, щоб повторити спробу"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Розблокуйте екран, щоб скористатись NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Цей пристрій належить вашій організації"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 6ba3c4fa3163..61a20c3d126c 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تصدیق شدہ"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"مکمل کرنے کیلئے \'تصدیق کریں\' تھپتھپائیں"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"چہرے سے انلاک کیا گیا۔ جاری رکھنے کیلئے انلاک آئیکن دبائیں۔"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"چہرے سے انلاک کیا گیا۔ جاری رکھنے کے لیے دبائیں۔"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کے لیے دبائیں۔"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کیلئے انلاک آئیکن دبائیں۔"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"تصدیق کردہ"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN استعمال کریں"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"پیٹرن کا استعمال کریں"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"کھولنے کے لیے اوپر سوائپ کريں"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"کھولنے کیلئے انلاک آئیکن دبائیں"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"چہرے سے انلاک کیا گیا۔ کھولنے کیلئے انلاک آئیکن دبائیں۔"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"چہرے سے انلاک کیا گیا۔ کھولنے کے لیے دبائیں۔"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"چہرے کی شناخت ہو گئی۔ کھولنے کے لیے دبائیں۔"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"چہرے کی شناخت ہو گئی۔ کھولنے کیلئے انلاک آئیکن دبائیں۔"</string> <string name="keyguard_retry" msgid="886802522584053523">"دوبارہ کوشش کرنے کے لیے اوپر سوائپ کريں"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC استعمال کرنے کیلئے غیر مقفل کریں"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"یہ آلہ آپ کی تنظیم کا ہے"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index a2831e036505..fe583f5b2995 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Tasdiqlangan"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tasdiqlash uchun tegining"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Yuz orqali ochilgan. Davom etish uchun ochish belgisini bosing."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Tasdiqlandi"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN kod kiritish"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Grafik kalitdan foydalanish"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Ochish uchun tepaga suring"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Ochish uchun ochish belgisini bosing"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Yuz orqali ochilgan. Ochish uchun ochish belgisini bosing."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Qayta urinish uchun tepaga suring"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ishlatish uchun qurilma qulfini oching"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu qurilma tashkilotingizga tegishli"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index ef782a2a9c77..9fd4f31a1bf7 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ðã xác nhận"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Nhấn vào Xác nhận để hoàn tất"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Đã mở khoá bằng khuôn mặt. Nhấn biểu tượng mở khoá để tiếp tục."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Đã xác thực"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Dùng mã PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Dùng hình mở khóa"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Vuốt lên để mở"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Nhấn biểu tượng mở khoá để mở"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Đã mở khoá bằng khuôn mặt. Nhấn biểu tượng mở khoá để mở."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Vuốt lên để thử lại"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Mở khóa để sử dụng NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Thiết bị này thuộc về tổ chức của bạn"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index ac1b79087b08..3fa6c60d833d 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已确认"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"点按“确认”即可完成"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"已通过面孔识别解锁。按下解锁图标即可继续。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已通过面孔识别解锁。点按即可继续。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"识别出面孔。点按即可继续。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"识别出面孔。按下解锁图标即可继续。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"已经过身份验证"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN 码"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用图案"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑动即可打开"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"按下解锁图标即可打开"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"已通过面孔识别解锁。按下解锁图标即可打开。"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"已通过面孔识别解锁。点按即可打开。"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"识别出面孔。点按即可打开。"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"识别出面孔。按下解锁图标即可打开。"</string> <string name="keyguard_retry" msgid="886802522584053523">"向上滑动即可重试"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"需要解锁才能使用 NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"此设备归贵单位所有"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 436e29389694..6950c20228de 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已確認"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕按 [確定] 以完成"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"已使用面孔解鎖。按解鎖圖示即可繼續。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已使用面孔解鎖。按下即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"已識別面孔。按下即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"已識別面孔。按解鎖圖示即可繼續。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"驗證咗"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用圖案"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"按解鎖圖示即可開啟"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"已使用面孔解鎖。按解鎖圖示即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"已使用面孔解鎖。按下即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"已識別面孔。按下即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"已識別面孔。按解鎖圖示即可開啟。"</string> <string name="keyguard_retry" msgid="886802522584053523">"請向上滑動以再試一次"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"解鎖方可使用 NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"此裝置屬於您的機構"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 297715d64e15..4222030b33b2 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -136,6 +136,9 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認完畢"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕觸 [確認] 完成驗證設定"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"裝置已透過人臉解鎖,按下「解鎖」圖示即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"裝置已透過你的臉解鎖,按下即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"臉孔辨識完成,按下即可繼續操作。"</string> + <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"臉孔辨識完成,按下「解鎖」圖示即可繼續操作。"</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"已通過驗證"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"使用 PIN 碼"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"使用解鎖圖案"</string> @@ -312,6 +315,9 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"按下「解鎖」圖示即可開啟"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"裝置已透過人臉解鎖,按下「解鎖」圖示即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_1" msgid="5715461103913071474">"裝置已透過你的臉解鎖,按下即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_2" msgid="8310787946357120406">"臉孔辨識完成,按下即可開啟。"</string> + <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"臉孔辨識完成,按下「解鎖」圖示即可開啟。"</string> <string name="keyguard_retry" msgid="886802522584053523">"向上滑動即可重試"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"如要使用 NFC,請先解鎖"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"這部裝置的擁有者為貴機構"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index d932406f1059..bf013c980d16 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -136,6 +136,12 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kuqinisekisiwe"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Thepha okuthi Qinisekisa ukuze uqedele"</string> <string name="biometric_dialog_tap_confirm_with_face" msgid="1092050545851021991">"Ivulwe ngobuso. Cindezela isithonjana sokuvula ukuze uqhubeke."</string> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_1 (439152621640507113) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_2 (8586608186457385108) --> + <skip /> + <!-- no translation found for biometric_dialog_tap_confirm_with_face_alt_3 (2192670471930606539) --> + <skip /> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Kugunyaziwe"</string> <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Sebenzisa iphinikhodi"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Sebenzisa iphethini"</string> @@ -312,6 +318,12 @@ <string name="keyguard_unlock" msgid="8031975796351361601">"Swayiphela phezulu ukuze uvule"</string> <string name="keyguard_unlock_press" msgid="9140109453735019209">"Cindezela isithonjana sokuvula ukuze uvule"</string> <string name="keyguard_face_successful_unlock_press" msgid="25520941264602588">"Ivulwe ngobuso. Cindezela isithonjana sokuvula ukuze uvule."</string> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_1 (5715461103913071474) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_2 (8310787946357120406) --> + <skip /> + <!-- no translation found for keyguard_face_successful_unlock_press_alt_3 (7219030481255573962) --> + <skip /> <string name="keyguard_retry" msgid="886802522584053523">"Swayiphela phezulu ukuze uzame futhi"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Vula ukuze usebenzise i-NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Le divayisi eyenhlangano yakho"</string> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 7ed915600230..597e88093de8 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -580,6 +580,9 @@ 280 </integer> + <!-- The time (in ms) needed to trigger the lock icon view's long-press affordance --> + <integer name="config_lockIconLongPress" translatable="false">200</integer> + <!-- package name of a built-in camera app to use to restrict implicit intent resolution when the double-press power gesture is used. Ignored if empty. --> <string translatable="false" name="config_cameraGesturePackage"></string> @@ -611,6 +614,13 @@ 2 - Override the setting to never bypass keyguard --> <integer name="config_face_unlock_bypass_override">0</integer> + <!-- Which face help messages to surface when fingerprint is also enrolled. + Message ids correspond with the acquired ids in BiometricFaceConstants --> + <integer-array name="config_face_help_msgs_when_fingerprint_enrolled"> + <item>25</item> + <item>26</item> + </integer-array> + <!-- Whether the communal service should be enabled --> <bool name="config_communalServiceEnabled">false</bool> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 66488415ff9f..160dcd0fbccc 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -857,7 +857,7 @@ <!-- The maximum offset for the under-display fingerprint sensor (UDFPS) icon in either direction that elements are moved to prevent burn-in on AOD--> <dimen name="udfps_burn_in_offset_x">7px</dimen> - <dimen name="udfps_burn_in_offset_y">28px</dimen> + <dimen name="udfps_burn_in_offset_y">20px</dimen> <!-- The absolute side margins of quick settings --> <dimen name="quick_settings_bottom_margin_media">8dp</dimen> diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index 5eacc3e6006b..dca5ea836fa4 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -176,5 +176,8 @@ <item type="id" name="rounded_corner_top_right"/> <item type="id" name="rounded_corner_bottom_left"/> <item type="id" name="rounded_corner_bottom_right"/> + + <!-- face scanning view id --> + <item type="id" name="face_scanning_anim"/> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index af8d7ed22ed3..e144b43294c6 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -341,6 +341,12 @@ <string name="biometric_dialog_tap_confirm">Tap Confirm to complete</string> <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]--> <string name="biometric_dialog_tap_confirm_with_face">Unlocked by face. Press the unlock icon to continue.</string> + <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]--> + <string name="biometric_dialog_tap_confirm_with_face_alt_1">Unlocked by face. Press to continue.</string> + <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]--> + <string name="biometric_dialog_tap_confirm_with_face_alt_2">Face recognized. Press to continue.</string> + <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]--> + <string name="biometric_dialog_tap_confirm_with_face_alt_3">Face recognized. Press the unlock icon to continue.</string> <!-- Talkback string when a biometric is authenticated [CHAR LIMIT=NONE] --> <string name="biometric_dialog_authenticated">Authenticated</string> @@ -803,6 +809,13 @@ <!-- Message shown when non-bypass face authentication succeeds and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] --> <string name="keyguard_face_successful_unlock_press">Unlocked by face. Press the unlock icon to open.</string> + <!-- Message shown when non-bypass face authentication succeeds and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] --> + <string name="keyguard_face_successful_unlock_press_alt_1">Unlocked by face. Press to open.</string> + <!-- Message shown when non-bypass face authentication succeeds and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] --> + <string name="keyguard_face_successful_unlock_press_alt_2">Face recognized. Press to open.</string> + <!-- Message shown when non-bypass face authentication succeeds and UDFPS is supported. Provides extra instructions for how the user can enter their device [CHAR LIMIT=60] --> + <string name="keyguard_face_successful_unlock_press_alt_3">Face recognized. Press the unlock icon to open.</string> + <!-- Messages shown when users press outside of udfps region during --> <string-array name="udfps_accessibility_touch_hints"> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 13690f30ab3b..e87feff59b83 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -275,7 +275,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab HashMap<Integer, SimData> mSimDatas = new HashMap<>(); HashMap<Integer, ServiceState> mServiceStates = new HashMap<Integer, ServiceState>(); - private int mRingMode; private int mPhoneState; private boolean mKeyguardIsVisible; private boolean mCredentialAttempted; @@ -752,6 +751,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleFingerprintAuthFailed() { Assert.isMainThread(); + if (mHandler.hasCallbacks(mFpCancelNotReceived)) { + Log.d(TAG, "handleFingerprintAuthFailed()" + + " triggered while waiting for cancellation, removing watchdog"); + mHandler.removeCallbacks(mFpCancelNotReceived); + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -782,6 +786,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) { Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated"); + if (mHandler.hasCallbacks(mFpCancelNotReceived)) { + Log.d(TAG, "handleFingerprintAuthenticated()" + + " triggered while waiting for cancellation, removing watchdog"); + mHandler.removeCallbacks(mFpCancelNotReceived); + } try { final int userId; try { @@ -1041,7 +1050,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleFaceError(int msgId, String errString) { Assert.isMainThread(); - if (DEBUG_FACE) Log.d(TAG, "Face error received: " + errString); + if (DEBUG_FACE) Log.d(TAG, "Face error received: " + errString + " msgId=" + msgId); if (mHandler.hasCallbacks(mFaceCancelNotReceived)) { mHandler.removeCallbacks(mFaceCancelNotReceived); } @@ -1511,6 +1520,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab handleFingerprintAuthenticated(userId, isStrongBiometric); }; + /** + * Propagates a pointer down event to keyguard. + */ + public void onUdfpsPointerDown(int sensorId) { + mFingerprintAuthenticationCallback.onUdfpsPointerDown(sensorId); + } + + /** + * Propagates a pointer up event to keyguard. + */ + public void onUdfpsPointerUp(int sensorId) { + mFingerprintAuthenticationCallback.onUdfpsPointerUp(sensorId); + } + @VisibleForTesting final FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback = new AuthenticationCallback() { @@ -1551,15 +1574,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab Trace.endSection(); } + /** + * Note, this is currently called from UdfpsController. + */ @Override public void onUdfpsPointerDown(int sensorId) { Log.d(TAG, "onUdfpsPointerDown, sensorId: " + sensorId); requestFaceAuth(true); - if (isFaceDetectionRunning()) { - mKeyguardBypassController.setUserHasDeviceEntryIntent(true); - } } + /** + * Note, this is currently called from UdfpsController. + */ @Override public void onUdfpsPointerUp(int sensorId) { Log.d(TAG, "onUdfpsPointerUp, sensorId: " + sensorId); @@ -1587,9 +1613,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab "faceFailure-" + reason); handleFaceAuthFailed(); - if (mKeyguardBypassController != null) { - mKeyguardBypassController.setUserHasDeviceEntryIntent(false); - } } @Override @@ -1597,10 +1620,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded"); handleFaceAuthenticated(result.getUserId(), result.isStrongBiometric()); Trace.endSection(); - - if (mKeyguardBypassController != null) { - mKeyguardBypassController.setUserHasDeviceEntryIntent(false); - } } @Override @@ -1611,9 +1630,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onAuthenticationError(int errMsgId, CharSequence errString) { handleFaceError(errMsgId, errString.toString()); - if (mKeyguardBypassController != null) { - mKeyguardBypassController.setUserHasDeviceEntryIntent(false); - } if (mActiveUnlockConfig.shouldRequestActiveUnlockOnFaceError(errMsgId)) { requestActiveUnlock( @@ -2177,6 +2193,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab && mBiometricEnabledForUser.get(userId)); } + public boolean isFaceSupported() { + return mFaceManager != null && mFaceManager.isHardwareDetected(); + } + /** * @return true if there's at least one udfps enrolled for the current user. */ @@ -2296,10 +2316,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab updateFaceListeningState(BIOMETRIC_ACTION_START); } - public boolean isFaceAuthUserRequested() { - return mIsFaceAuthUserRequested; - } - /** * In case face auth is running, cancel it. */ @@ -2307,6 +2323,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab stopListeningForFace(); } + public boolean isFaceScanning() { + return mFaceRunningState == BIOMETRIC_STATE_RUNNING; + } + private void updateFaceListeningState(int action) { // If this message exists, we should not authenticate again until this message is // consumed by the handler @@ -3160,11 +3180,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mSecureCameraLaunched = false; } - if (mKeyguardBypassController != null) { - // LS visibility has changed, so reset deviceEntryIntent - mKeyguardBypassController.setUserHasDeviceEntryIntent(false); - } - for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -3809,6 +3824,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab pw.println(" enabledByUser=" + mBiometricEnabledForUser.get(userId)); pw.println(" mSecureCameraLaunched=" + mSecureCameraLaunched); pw.println(" mBouncerFullyShown=" + mBouncerFullyShown); + pw.println(" mNeedsSlowUnlockTransition=" + mNeedsSlowUnlockTransition); } mListenModels.print(pw); diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 680b8bd70837..0097196fd841 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -83,8 +83,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme private static final int sLockIconRadiusPx = (int) (sDefaultDensity * 36); private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH); - private static final long LONG_PRESS_TIMEOUT = 200L; // milliseconds + private final long mLongPressTimeout; @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @NonNull private final KeyguardViewController mKeyguardViewController; @NonNull private final StatusBarStateController mStatusBarStateController; @@ -176,6 +176,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mView.setImageDrawable(mIcon); mUnlockedLabel = resources.getString(R.string.accessibility_unlock_button); mLockedLabel = resources.getString(R.string.accessibility_lock_icon); + mLongPressTimeout = resources.getInteger(R.integer.config_lockIconLongPress); dumpManager.registerDumpable(TAG, this); } @@ -545,7 +546,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme /** * Handles the touch if it is within the lock icon view and {@link #isActionable()} is true. * Subsequently, will trigger {@link #onLongPress()} if a touch is continuously in the lock icon - * area for {@link #LONG_PRESS_TIMEOUT} ms. + * area for {@link #mLongPressTimeout} ms. * * Touch speed debouncing mimics logic from the velocity tracker in {@link UdfpsController}. */ @@ -585,7 +586,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mDownDetected = true; mLongPressCancelRunnable = mExecutor.executeDelayed( - this::onLongPress, LONG_PRESS_TIMEOUT); + this::onLongPress, mLongPressTimeout); break; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_HOVER_MOVE: @@ -600,7 +601,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme + "high pointer velocity=" + velocity); mLongPressCancelRunnable.run(); mLongPressCancelRunnable = mExecutor.executeDelayed( - this::onLongPress, LONG_PRESS_TIMEOUT); + this::onLongPress, mLongPressTimeout); } break; case MotionEvent.ACTION_UP: @@ -651,7 +652,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme Process.myUid(), getContext().getOpPackageName(), UdfpsController.EFFECT_CLICK, - "lock-icon-device-entry", + "lock-screen-lock-icon-longpress", TOUCH_VIBRATION_ATTRIBUTES); mKeyguardViewController.showBouncer(/* scrim */ true); @@ -676,6 +677,12 @@ public class LockIconViewController extends ViewController<LockIconView> impleme } private boolean isActionable() { + if (mIsBouncerShowing) { + Log.v(TAG, "lock icon long-press ignored, bouncer already showing."); + // a long press gestures from AOD may have already triggered the bouncer to show, + // so this touch is no longer actionable + return false; + } return mUdfpsSupported || mShowUnlockIcon; } diff --git a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt index 34164f3b7306..d2c229b8ead1 100644 --- a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt +++ b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt @@ -279,7 +279,7 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView { } companion object { - private const val HIDDEN_CAMERA_PROTECTION_SCALE = 0.5f + const val HIDDEN_CAMERA_PROTECTION_SCALE = 0.5f @JvmStatic protected fun transformPhysicalToLogicalCoordinates( @Surface.Rotation rotation: Int, diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt new file mode 100644 index 000000000000..c5955860aebf --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2022 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 + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.AnimatorSet +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Matrix +import android.graphics.Paint +import android.graphics.Path +import android.graphics.RectF +import android.hardware.biometrics.BiometricSourceType +import android.view.View +import androidx.core.graphics.ColorUtils +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.keyguard.KeyguardUpdateMonitorCallback +import com.android.settingslib.Utils +import com.android.systemui.animation.Interpolators +import com.android.systemui.plugins.statusbar.StatusBarStateController +import java.util.concurrent.Executor + +/** + * When the face is enrolled, we use this view to show the face scanning animation and the camera + * protection on the keyguard. + */ +class FaceScanningOverlay( + context: Context, + pos: Int, + val statusBarStateController: StatusBarStateController, + val keyguardUpdateMonitor: KeyguardUpdateMonitor, + val mainExecutor: Executor +) : ScreenDecorations.DisplayCutoutView(context, pos) { + private var showScanningAnim = false + private val rimPaint = Paint() + private var rimProgress: Float = HIDDEN_CAMERA_PROTECTION_SCALE + private var rimAnimator: AnimatorSet? = null + private val rimRect = RectF() + private var cameraProtectionColor = Color.BLACK + var faceScanningAnimColor = Utils.getColorAttrDefaultColor(context, + com.android.systemui.R.attr.wallpaperTextColorAccent) + private var cameraProtectionAnimator: ValueAnimator? = null + var hideOverlayRunnable: Runnable? = null + var faceAuthSucceeded = false + + init { + visibility = View.INVISIBLE // only show this view when face scanning is happening + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + mainExecutor.execute { + keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) + } + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + mainExecutor.execute { + keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback) + } + } + + override fun setColor(color: Int) { + cameraProtectionColor = color + invalidate() + } + + override fun drawCutoutProtection(canvas: Canvas) { + if (rimProgress > HIDDEN_RIM_SCALE && !protectionRect.isEmpty) { + val rimPath = Path(protectionPath) + val scaleMatrix = Matrix().apply { + val rimBounds = RectF() + rimPath.computeBounds(rimBounds, true) + setScale(rimProgress, rimProgress, rimBounds.centerX(), rimBounds.centerY()) + } + rimPath.transform(scaleMatrix) + rimPaint.style = Paint.Style.FILL + val rimPaintAlpha = rimPaint.alpha + rimPaint.color = ColorUtils.blendARGB( + faceScanningAnimColor, + Color.WHITE, + statusBarStateController.dozeAmount) + rimPaint.alpha = rimPaintAlpha + canvas.drawPath(rimPath, rimPaint) + } + + if (cameraProtectionProgress > HIDDEN_CAMERA_PROTECTION_SCALE && + !protectionRect.isEmpty) { + val scaledProtectionPath = Path(protectionPath) + val scaleMatrix = Matrix().apply { + val protectionPathRect = RectF() + scaledProtectionPath.computeBounds(protectionPathRect, true) + setScale(cameraProtectionProgress, cameraProtectionProgress, + protectionPathRect.centerX(), protectionPathRect.centerY()) + } + scaledProtectionPath.transform(scaleMatrix) + paint.style = Paint.Style.FILL + paint.color = cameraProtectionColor + canvas.drawPath(scaledProtectionPath, paint) + } + } + + override fun updateVisOnUpdateCutout(): Boolean { + return false // instead, we always update the visibility whenever face scanning starts/ends + } + + override fun enableShowProtection(show: Boolean) { + val showScanningAnimNow = keyguardUpdateMonitor.isFaceScanning && show + if (showScanningAnimNow == showScanningAnim) { + return + } + showScanningAnim = showScanningAnimNow + updateProtectionBoundingPath() + // Delay the relayout until the end of the animation when hiding, + // otherwise we'd clip it. + if (showScanningAnim) { + visibility = View.VISIBLE + requestLayout() + } + + cameraProtectionAnimator?.cancel() + cameraProtectionAnimator = ValueAnimator.ofFloat(cameraProtectionProgress, + if (showScanningAnimNow) SHOW_CAMERA_PROTECTION_SCALE + else HIDDEN_CAMERA_PROTECTION_SCALE).apply { + startDelay = + if (showScanningAnim) 0 + else if (faceAuthSucceeded) PULSE_SUCCESS_DISAPPEAR_DURATION + else PULSE_ERROR_DISAPPEAR_DURATION + duration = + if (showScanningAnim) CAMERA_PROTECTION_APPEAR_DURATION + else if (faceAuthSucceeded) CAMERA_PROTECTION_SUCCESS_DISAPPEAR_DURATION + else CAMERA_PROTECTION_ERROR_DISAPPEAR_DURATION + interpolator = + if (showScanningAnim) Interpolators.STANDARD_ACCELERATE + else if (faceAuthSucceeded) Interpolators.STANDARD + else Interpolators.STANDARD_DECELERATE + addUpdateListener(ValueAnimator.AnimatorUpdateListener { + animation: ValueAnimator -> + cameraProtectionProgress = animation.animatedValue as Float + invalidate() + }) + addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + cameraProtectionAnimator = null + if (!showScanningAnim) { + visibility = View.INVISIBLE + hideOverlayRunnable?.run() + hideOverlayRunnable = null + requestLayout() + } + } + }) + } + + rimAnimator?.cancel() + rimAnimator = AnimatorSet().apply { + if (showScanningAnim) { + val rimAppearAnimator = ValueAnimator.ofFloat(SHOW_CAMERA_PROTECTION_SCALE, + PULSE_RADIUS_OUT).apply { + duration = PULSE_APPEAR_DURATION + interpolator = Interpolators.STANDARD_DECELERATE + addUpdateListener(ValueAnimator.AnimatorUpdateListener { + animation: ValueAnimator -> + rimProgress = animation.animatedValue as Float + invalidate() + }) + } + + // animate in camera protection, rim, and then pulse in/out + playSequentially(cameraProtectionAnimator, rimAppearAnimator, + createPulseAnimator(), createPulseAnimator(), + createPulseAnimator(), createPulseAnimator(), + createPulseAnimator(), createPulseAnimator()) + } else { + val rimDisappearAnimator = ValueAnimator.ofFloat( + rimProgress, + if (faceAuthSucceeded) PULSE_RADIUS_SUCCESS + else SHOW_CAMERA_PROTECTION_SCALE + ).apply { + duration = + if (faceAuthSucceeded) PULSE_SUCCESS_DISAPPEAR_DURATION + else PULSE_ERROR_DISAPPEAR_DURATION + interpolator = + if (faceAuthSucceeded) Interpolators.STANDARD_DECELERATE + else Interpolators.STANDARD + addUpdateListener(ValueAnimator.AnimatorUpdateListener { + animation: ValueAnimator -> + rimProgress = animation.animatedValue as Float + invalidate() + }) + addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + rimProgress = HIDDEN_RIM_SCALE + invalidate() + } + }) + } + if (faceAuthSucceeded) { + val successOpacityAnimator = ValueAnimator.ofInt(255, 0).apply { + duration = PULSE_SUCCESS_DISAPPEAR_DURATION + interpolator = Interpolators.LINEAR + addUpdateListener(ValueAnimator.AnimatorUpdateListener { + animation: ValueAnimator -> + rimPaint.alpha = animation.animatedValue as Int + invalidate() + }) + addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + rimPaint.alpha = 255 + invalidate() + } + }) + } + val rimSuccessAnimator = AnimatorSet() + rimSuccessAnimator.playTogether(rimDisappearAnimator, successOpacityAnimator) + playTogether(rimSuccessAnimator, cameraProtectionAnimator) + } else { + playTogether(rimDisappearAnimator, cameraProtectionAnimator) + } + } + + addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + rimAnimator = null + if (!showScanningAnim) { + requestLayout() + } + } + }) + start() + } + } + + fun createPulseAnimator(): AnimatorSet { + return AnimatorSet().apply { + val pulseInwards = ValueAnimator.ofFloat( + PULSE_RADIUS_OUT, PULSE_RADIUS_IN).apply { + duration = PULSE_DURATION_INWARDS + interpolator = Interpolators.STANDARD + addUpdateListener(ValueAnimator.AnimatorUpdateListener { + animation: ValueAnimator -> + rimProgress = animation.animatedValue as Float + invalidate() + }) + } + val pulseOutwards = ValueAnimator.ofFloat( + PULSE_RADIUS_IN, PULSE_RADIUS_OUT).apply { + duration = PULSE_DURATION_OUTWARDS + interpolator = Interpolators.STANDARD + addUpdateListener(ValueAnimator.AnimatorUpdateListener { + animation: ValueAnimator -> + rimProgress = animation.animatedValue as Float + invalidate() + }) + } + playSequentially(pulseInwards, pulseOutwards) + } + } + + override fun updateProtectionBoundingPath() { + super.updateProtectionBoundingPath() + rimRect.set(protectionRect) + rimRect.scale(rimProgress) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + if (mBounds.isEmpty()) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + return + } + if (showScanningAnim) { + // Make sure that our measured height encompasses the extra space for the animation + mTotalBounds.union(mBoundingRect) + mTotalBounds.union( + rimRect.left.toInt(), + rimRect.top.toInt(), + rimRect.right.toInt(), + rimRect.bottom.toInt()) + setMeasuredDimension( + resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0), + resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0)) + } else { + setMeasuredDimension( + resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0), + resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0)) + } + } + + private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { + override fun onBiometricAuthenticated( + userId: Int, + biometricSourceType: BiometricSourceType?, + isStrongBiometric: Boolean + ) { + if (biometricSourceType == BiometricSourceType.FACE) { + post { + faceAuthSucceeded = true + enableShowProtection(true) + } + } + } + + override fun onBiometricAcquired( + biometricSourceType: BiometricSourceType?, + acquireInfo: Int + ) { + if (biometricSourceType == BiometricSourceType.FACE) { + post { + faceAuthSucceeded = false // reset + } + } + } + + override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType?) { + if (biometricSourceType == BiometricSourceType.FACE) { + post { + faceAuthSucceeded = false + enableShowProtection(false) + } + } + } + + override fun onBiometricError( + msgId: Int, + errString: String?, + biometricSourceType: BiometricSourceType? + ) { + if (biometricSourceType == BiometricSourceType.FACE) { + post { + faceAuthSucceeded = false + enableShowProtection(false) + } + } + } + } + + companion object { + private const val HIDDEN_RIM_SCALE = HIDDEN_CAMERA_PROTECTION_SCALE + private const val SHOW_CAMERA_PROTECTION_SCALE = 1f + + private const val PULSE_RADIUS_IN = 1.1f + private const val PULSE_RADIUS_OUT = 1.125f + private const val PULSE_RADIUS_SUCCESS = 1.25f + + private const val CAMERA_PROTECTION_APPEAR_DURATION = 250L + private const val PULSE_APPEAR_DURATION = 250L // without start delay + + private const val PULSE_DURATION_INWARDS = 500L + private const val PULSE_DURATION_OUTWARDS = 500L + + private const val PULSE_SUCCESS_DISAPPEAR_DURATION = 400L + private const val CAMERA_PROTECTION_SUCCESS_DISAPPEAR_DURATION = 500L // without start delay + + private const val PULSE_ERROR_DISAPPEAR_DURATION = 200L + private const val CAMERA_PROTECTION_ERROR_DISAPPEAR_DURATION = 300L // without start delay + } +} diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt index 0df2730a48eb..a74f2f8a5e34 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt @@ -44,7 +44,7 @@ import kotlin.math.ceil import kotlin.math.floor /** - * When the HWC of the device supports Composition.DISPLAY_DECORATON, we use this layer to draw + * When the HWC of the device supports Composition.DISPLAY_DECORATION, we use this layer to draw * screen decorations. */ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDecorationSupport) diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index c04463ad6906..edcaf492874d 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -69,12 +69,14 @@ import android.widget.FrameLayout; import androidx.annotation.VisibleForTesting; import com.android.internal.util.Preconditions; +import com.android.settingslib.Utils; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.decor.DecorProvider; import com.android.systemui.decor.DecorProviderFactory; import com.android.systemui.decor.DecorProviderKt; +import com.android.systemui.decor.FaceScanningProviderFactory; import com.android.systemui.decor.OverlayWindow; import com.android.systemui.decor.PrivacyDotDecorProviderFactory; import com.android.systemui.decor.RoundedCornerDecorProviderFactory; @@ -90,8 +92,10 @@ import com.android.systemui.util.settings.SecureSettings; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.concurrent.Executor; import javax.inject.Inject; @@ -131,6 +135,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab private final PrivacyDotViewController mDotViewController; private final ThreadFactory mThreadFactory; private final DecorProviderFactory mDotFactory; + private final FaceScanningProviderFactory mFaceScanningFactory; + public final int mFaceScanningViewId; @VisibleForTesting protected RoundedCornerResDelegate mRoundedCornerResDelegate; @@ -161,46 +167,84 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab @VisibleForTesting protected DisplayInfo mDisplayInfo = new DisplayInfo(); - private CameraAvailabilityListener.CameraTransitionCallback mCameraTransitionCallback = - new CameraAvailabilityListener.CameraTransitionCallback() { - @Override - public void onApplyCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) { - if (mScreenDecorHwcLayer != null) { - mScreenDecorHwcLayer.setProtection(protectionPath, bounds); - mScreenDecorHwcLayer.enableShowProtection(true); + @VisibleForTesting + protected void showCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) { + if (mFaceScanningFactory.shouldShowFaceScanningAnim()) { + DisplayCutoutView overlay = (DisplayCutoutView) getOverlayView( + mFaceScanningViewId); + if (overlay != null) { + overlay.setProtection(protectionPath, bounds); + overlay.enableShowProtection(true); + updateOverlayWindowVisibilityIfViewExists( + overlay.findViewById(mFaceScanningViewId)); + // immediately return, bc FaceScanningOverlay also renders the camera + // protection, so we don't need to show the camera protection in + // mScreenDecorHwcLayer or mCutoutViews return; } - if (mCutoutViews == null) { - Log.w(TAG, "DisplayCutoutView do not initialized"); - return; + } + + if (mScreenDecorHwcLayer != null) { + mScreenDecorHwcLayer.setProtection(protectionPath, bounds); + mScreenDecorHwcLayer.enableShowProtection(true); + return; + } + + if (mCutoutViews == null) { + Log.w(TAG, "DisplayCutoutView not initialized onApplyCameraProtection"); + return; + } + + // Show the extra protection around the front facing camera if necessary + for (DisplayCutoutView dcv : mCutoutViews) { + // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile + if (dcv != null) { + dcv.setProtection(protectionPath, bounds); + dcv.enableShowProtection(true); } - // Show the extra protection around the front facing camera if necessary - for (DisplayCutoutView dcv : mCutoutViews) { - // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile - if (dcv != null) { - dcv.setProtection(protectionPath, bounds); - dcv.enableShowProtection(true); - } + } + } + + @VisibleForTesting + protected void hideCameraProtection() { + FaceScanningOverlay faceScanningOverlay = + (FaceScanningOverlay) getOverlayView(mFaceScanningViewId); + if (faceScanningOverlay != null) { + faceScanningOverlay.setHideOverlayRunnable(() -> { + updateOverlayWindowVisibilityIfViewExists( + faceScanningOverlay.findViewById(mFaceScanningViewId)); + }); + faceScanningOverlay.enableShowProtection(false); + } + + if (mScreenDecorHwcLayer != null) { + mScreenDecorHwcLayer.enableShowProtection(false); + return; + } + + if (mCutoutViews == null) { + Log.w(TAG, "DisplayCutoutView not initialized onHideCameraProtection"); + return; + } + // Go back to the regular anti-aliasing + for (DisplayCutoutView dcv : mCutoutViews) { + // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile + if (dcv != null) { + dcv.enableShowProtection(false); } } + } + + private CameraAvailabilityListener.CameraTransitionCallback mCameraTransitionCallback = + new CameraAvailabilityListener.CameraTransitionCallback() { + @Override + public void onApplyCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) { + showCameraProtection(protectionPath, bounds); + } @Override public void onHideCameraProtection() { - if (mScreenDecorHwcLayer != null) { - mScreenDecorHwcLayer.enableShowProtection(false); - return; - } - if (mCutoutViews == null) { - Log.w(TAG, "DisplayCutoutView do not initialized"); - return; - } - // Go back to the regular anti-aliasing - for (DisplayCutoutView dcv : mCutoutViews) { - // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile - if (dcv != null) { - dcv.enableShowProtection(false); - } - } + hideCameraProtection(); } }; @@ -209,25 +253,24 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab new PrivacyDotViewController.ShowingListener() { @Override public void onPrivacyDotShown(@Nullable View v) { - setOverlayWindowVisibilityIfViewExist(v, View.VISIBLE); + updateOverlayWindowVisibilityIfViewExists(v); } @Override public void onPrivacyDotHidden(@Nullable View v) { - setOverlayWindowVisibilityIfViewExist(v, View.INVISIBLE); + updateOverlayWindowVisibilityIfViewExists(v); } }; @VisibleForTesting - protected void setOverlayWindowVisibilityIfViewExist(@Nullable View view, - @View.Visibility int visibility) { + protected void updateOverlayWindowVisibilityIfViewExists(@Nullable View view) { if (view == null) { return; } mExecutor.execute(() -> { // We don't need to control the window visibility if rounded corners or cutout is drawn // on sw layer since the overlay windows are always visible in this case. - if (mOverlays == null || !isOnlyPrivacyDotInSwLayer()) { + if (mOverlays == null || !shouldOptimizeVisibility()) { return; } @@ -236,7 +279,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab continue; } if (overlay.getView(view.getId()) != null) { - overlay.getRootView().setVisibility(visibility); + overlay.getRootView().setVisibility(getWindowVisibility(overlay, true)); return; } } @@ -258,7 +301,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab UserTracker userTracker, PrivacyDotViewController dotViewController, ThreadFactory threadFactory, - PrivacyDotDecorProviderFactory dotFactory) { + PrivacyDotDecorProviderFactory dotFactory, + FaceScanningProviderFactory faceScanningFactory) { super(context); mMainExecutor = mainExecutor; mSecureSettings = secureSettings; @@ -268,6 +312,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab mDotViewController = dotViewController; mThreadFactory = threadFactory; mDotFactory = dotFactory; + mFaceScanningFactory = faceScanningFactory; + mFaceScanningViewId = com.android.systemui.R.id.face_scanning_anim; } @Override @@ -289,6 +335,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab @NonNull private List<DecorProvider> getProviders(boolean hasHwLayer) { List<DecorProvider> decorProviders = new ArrayList<>(mDotFactory.getProviders()); + decorProviders.addAll(mFaceScanningFactory.getProviders()); if (!hasHwLayer) { decorProviders.addAll(mRoundedCornerFactory.getProviders()); } @@ -446,6 +493,13 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab cutoutView.onDisplayChanged(displayId); } } + + DisplayCutoutView overlay = (DisplayCutoutView) getOverlayView(mFaceScanningViewId); + if (overlay != null) { + // handle display resolution changes + overlay.onDisplayChanged(displayId); + } + if (mScreenDecorHwcLayer != null) { mScreenDecorHwcLayer.onDisplayChanged(displayId); } @@ -466,7 +520,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab if (overlay == null) { continue; } - final View view = overlay.getView(id); if (view != null) { return view; @@ -503,7 +556,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } private void setupDecorations() { - if (hasRoundedCorners() || shouldDrawCutout() || isPrivacyDotEnabled()) { + if (hasRoundedCorners() || shouldDrawCutout() || isPrivacyDotEnabled() + || mFaceScanningFactory.getHasProviders()) { + List<DecorProvider> decorProviders = getProviders(mHwcScreenDecorationSupport != null); removeRedundantOverlayViews(decorProviders); @@ -512,21 +567,24 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } else { removeHwcOverlay(); } + final DisplayCutout cutout = getCutout(); - final boolean isOnlyPrivacyDotInSwLayer = isOnlyPrivacyDotInSwLayer(); + final boolean shouldOptimizeVisibility = shouldOptimizeVisibility(); for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) { - if (shouldShowSwLayerCutout(i, cutout) || shouldShowSwLayerRoundedCorner(i, cutout) + if (shouldShowSwLayerCutout(i, cutout) + || shouldShowSwLayerFaceScan(i, cutout) + || shouldShowSwLayerRoundedCorner(i, cutout) || shouldShowSwLayerPrivacyDot(i, cutout)) { Pair<List<DecorProvider>, List<DecorProvider>> pair = DecorProviderKt.partitionAlignedBound(decorProviders, i); decorProviders = pair.getSecond(); - createOverlay(i, pair.getFirst(), isOnlyPrivacyDotInSwLayer); + createOverlay(i, pair.getFirst(), shouldOptimizeVisibility); } else { removeOverlay(i); } } - if (isOnlyPrivacyDotInSwLayer) { + if (shouldOptimizeVisibility) { mDotViewController.setShowingListener(mPrivacyDotShowingListener); } else { mDotViewController.setShowingListener(null); @@ -565,6 +623,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } mColorInversionSetting.setListening(true); mColorInversionSetting.onChange(false); + updateColorInversion(mColorInversionSetting.getValue()); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_SWITCHED); @@ -626,59 +685,61 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab @View.Visibility private int getWindowVisibility(@NonNull OverlayWindow overlay, - boolean isOnlyPrivacyDotInSwLayer) { - if (!isOnlyPrivacyDotInSwLayer) { - // Multiple views inside overlay, no need to optimize + boolean shouldOptimizeVisibility) { + if (!shouldOptimizeVisibility) { + // All overlays have visible views so there's no need to optimize visibility. + // For example, the rounded corners could exist in each overlay and since the rounded + // corners are always visible, there's no need to optimize visibility. return View.VISIBLE; } + // Optimize if it's just the privacy dot & face scanning animation, since the privacy + // dot and face scanning overlay aren't always visible. int[] ids = { R.id.privacy_dot_top_left_container, R.id.privacy_dot_top_right_container, R.id.privacy_dot_bottom_left_container, - R.id.privacy_dot_bottom_right_container + R.id.privacy_dot_bottom_right_container, + mFaceScanningViewId }; for (int id: ids) { - final View view = overlay.getView(id); - if (view != null && view.getVisibility() == View.VISIBLE) { - // Only privacy dot in sw layers, overlay shall be VISIBLE if one of privacy dot - // views inside this overlay is VISIBLE + final View notAlwaysVisibleViews = overlay.getView(id); + if (notAlwaysVisibleViews != null + && notAlwaysVisibleViews.getVisibility() == View.VISIBLE) { + // Overlay is VISIBLE if one the views inside this overlay is VISIBLE return View.VISIBLE; } } - // Only privacy dot in sw layers, overlay shall be INVISIBLE like default if no privacy dot - // view inside this overlay is VISIBLE. + + // Only non-visible views in this overlay, so set overlay to INVISIBLE return View.INVISIBLE; } private void createOverlay( @BoundsPosition int pos, @NonNull List<DecorProvider> decorProviders, - boolean isOnlyPrivacyDotInSwLayer) { + boolean shouldOptimizeVisibility) { if (mOverlays == null) { mOverlays = new OverlayWindow[BOUNDS_POSITION_LENGTH]; } if (mOverlays[pos] != null) { - initOverlay(mOverlays[pos], decorProviders, isOnlyPrivacyDotInSwLayer); + initOverlay(mOverlays[pos], decorProviders, shouldOptimizeVisibility); return; } - mOverlays[pos] = new OverlayWindow(mContext); - initOverlay(mOverlays[pos], decorProviders, isOnlyPrivacyDotInSwLayer); + initOverlay(mOverlays[pos], decorProviders, shouldOptimizeVisibility); final ViewGroup overlayView = mOverlays[pos].getRootView(); overlayView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); overlayView.setAlpha(0); overlayView.setForceDarkAllowed(false); - // Only show cutout and rounded corners in mOverlays when hwc don't support screen - // decoration. + // Only show cutout in mOverlays when hwc doesn't support screen decoration if (mHwcScreenDecorationSupport == null) { if (mCutoutViews == null) { mCutoutViews = new DisplayCutoutView[BOUNDS_POSITION_LENGTH]; } mCutoutViews[pos] = new DisplayCutoutView(mContext, pos); - mCutoutViews[pos].setColor(mTintColor); overlayView.addView(mCutoutViews[pos]); mCutoutViews[pos].updateRotation(mRotation); } @@ -736,7 +797,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab private void initOverlay( @NonNull OverlayWindow overlay, @NonNull List<DecorProvider> decorProviders, - boolean isOnlyPrivacyDotInSwLayer) { + boolean shouldOptimizeVisibility) { if (!overlay.hasSameProviders(decorProviders)) { decorProviders.forEach(provider -> { if (overlay.getView(provider.getViewId()) != null) { @@ -746,9 +807,10 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab overlay.addDecorProvider(provider, mRotation); }); } - // Use visibility of privacy dot views if only privacy dot in sw layer - overlay.getRootView().setVisibility( - getWindowVisibility(overlay, isOnlyPrivacyDotInSwLayer)); + // Use visibility of privacy dot views & face scanning view to determine the overlay's + // visibility if the screen decoration SW layer overlay isn't persistently showing + // (ie: rounded corners always showing in SW layer) + overlay.getRootView().setVisibility(getWindowVisibility(overlay, shouldOptimizeVisibility)); } @VisibleForTesting @@ -780,7 +842,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH | WindowManager.LayoutParams.FLAG_SLIPPERY - | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT); lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS | WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; @@ -888,23 +951,28 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab mTintColor = Color.RED; } - // When the hwc supports screen decorations, the layer will use the A8 color mode which - // won't be affected by the color inversion. If the composition goes the client composition - // route, the color inversion will be handled by the RenderEngine. - if (mOverlays == null || mHwcScreenDecorationSupport != null) { + if (mOverlays == null) { return; } - ColorStateList tintList = ColorStateList.valueOf(mTintColor); - mRoundedCornerResDelegate.setColorTintList(tintList); - - Integer[] roundedCornerIds = { - R.id.rounded_corner_top_left, - R.id.rounded_corner_top_right, - R.id.rounded_corner_bottom_left, - R.id.rounded_corner_bottom_right - }; - + // When the hwc supports screen decorations, the layer will use the A8 color mode which + // won't be affected by the color inversion. If the composition goes the client composition + // route, the color inversion will be handled by the RenderEngine. + final Set<Integer> viewsMayNeedColorUpdate = new HashSet<>(); + if (mHwcScreenDecorationSupport == null) { + ColorStateList tintList = ColorStateList.valueOf(mTintColor); + mRoundedCornerResDelegate.setColorTintList(tintList); + viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_left); + viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_right); + viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_left); + viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_right); + viewsMayNeedColorUpdate.add(R.id.display_cutout); + } + if (getOverlayView(mFaceScanningViewId) != null) { + viewsMayNeedColorUpdate.add(mFaceScanningViewId); + } + final Integer[] views = new Integer[viewsMayNeedColorUpdate.size()]; + viewsMayNeedColorUpdate.toArray(views); for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) { if (mOverlays[i] == null) { continue; @@ -914,12 +982,13 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab View child; for (int j = 0; j < size; j++) { child = overlayView.getChildAt(j); - if (child instanceof DisplayCutoutView) { + if (viewsMayNeedColorUpdate.contains(child.getId()) + && child instanceof DisplayCutoutView) { ((DisplayCutoutView) child).setColor(mTintColor); } } - mOverlays[i].onReloadResAndMeasure(roundedCornerIds, mProviderRefreshToken, mRotation, - mDisplayUniqueId); + mOverlays[i].onReloadResAndMeasure(views, mProviderRefreshToken, + mRotation, mDisplayUniqueId); } } @@ -971,8 +1040,20 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { pw.println("ScreenDecorations state:"); pw.println(" DEBUG_DISABLE_SCREEN_DECORATIONS:" + DEBUG_DISABLE_SCREEN_DECORATIONS); + if (DEBUG_DISABLE_SCREEN_DECORATIONS) { + return; + } + pw.println(" mIsPrivacyDotEnabled:" + isPrivacyDotEnabled()); - pw.println(" isOnlyPrivacyDotInSwLayer:" + isOnlyPrivacyDotInSwLayer()); + pw.println(" shouldOptimizeOverlayVisibility:" + shouldOptimizeVisibility()); + final boolean supportsShowingFaceScanningAnim = mFaceScanningFactory.getHasProviders(); + pw.println(" supportsShowingFaceScanningAnim:" + supportsShowingFaceScanningAnim); + if (supportsShowingFaceScanningAnim) { + pw.println(" canShowFaceScanningAnim:" + + mFaceScanningFactory.canShowFaceScanningAnim()); + pw.println(" shouldShowFaceScanningAnim (at time dump was taken):" + + mFaceScanningFactory.shouldShowFaceScanningAnim()); + } pw.println(" mPendingConfigChange:" + mPendingConfigChange); if (mHwcScreenDecorationSupport != null) { pw.println(" mHwcScreenDecorationSupport:"); @@ -1041,6 +1122,14 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab // update all provider views inside overlay updateOverlayProviderViews(); } + + FaceScanningOverlay faceScanningOverlay = + (FaceScanningOverlay) getOverlayView(mFaceScanningViewId); + if (faceScanningOverlay != null) { + faceScanningOverlay.setFaceScanningAnimColor( + Utils.getColorAttrDefaultColor(faceScanningOverlay.getContext(), + com.android.systemui.R.attr.wallpaperTextColorAccent)); + } } private boolean hasRoundedCorners() { @@ -1074,6 +1163,11 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab return isPrivacyDotEnabled() && isDefaultShownOverlayPos(pos, cutout); } + private boolean shouldShowSwLayerFaceScan(@BoundsPosition int pos, + @Nullable DisplayCutout cutout) { + return mFaceScanningFactory.getHasProviders() && isDefaultShownOverlayPos(pos, cutout); + } + private boolean shouldShowSwLayerCutout(@BoundsPosition int pos, @Nullable DisplayCutout cutout) { final Rect[] bounds = cutout == null ? null : cutout.getBoundingRectsAll(); @@ -1082,8 +1176,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab && mHwcScreenDecorationSupport == null); } - private boolean isOnlyPrivacyDotInSwLayer() { - return isPrivacyDotEnabled() + private boolean shouldOptimizeVisibility() { + return (isPrivacyDotEnabled() || mFaceScanningFactory.getHasProviders()) && (mHwcScreenDecorationSupport != null || (!hasRoundedCorners() && !shouldDrawCutout()) ); @@ -1197,9 +1291,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } public static class DisplayCutoutView extends DisplayCutoutBaseView { - private final List<Rect> mBounds = new ArrayList(); - private final Rect mBoundingRect = new Rect(); - private Rect mTotalBounds = new Rect(); + final List<Rect> mBounds = new ArrayList(); + final Rect mBoundingRect = new Rect(); + Rect mTotalBounds = new Rect(); private int mColor = Color.BLACK; private int mRotation; @@ -1209,6 +1303,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab public DisplayCutoutView(Context context, @BoundsPosition int pos) { super(context); mInitialPosition = pos; + paint.setColor(mColor); paint.setStyle(Paint.Style.FILL); setId(R.id.display_cutout); @@ -1253,11 +1348,15 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } else { newVisible = GONE; } - if (newVisible != getVisibility()) { + if (updateVisOnUpdateCutout() && newVisible != getVisibility()) { setVisibility(newVisible); } } + protected boolean updateVisOnUpdateCutout() { + return true; + } + private void updateBoundingPath() { final Path path = displayInfo.displayCutout.getCutoutPath(); if (path != null) { @@ -1305,7 +1404,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } if (showProtection) { - // Make sure that our measured height encompases the protection + // Make sure that our measured height encompasses the protection mTotalBounds.union(mBoundingRect); mTotalBounds.union((int) protectionRect.left, (int) protectionRect.top, (int) protectionRect.right, (int) protectionRect.bottom); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt index cd16379cd5b4..606a73a6ac38 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt @@ -36,12 +36,20 @@ open class AuthBiometricFingerprintIconController( iconView: ImageView ) : AuthIconController(context, iconView) { + var iconLayoutParamsSize = 0 + set(value) { + if (field == value) { + return + } + iconView.layoutParams.width = value + iconView.layoutParams.height = value + field = value + } + init { - val size = context.resources.getDimensionPixelSize( + iconLayoutParamsSize = context.resources.getDimensionPixelSize( R.dimen.biometric_dialog_fingerprint_icon_size ) - iconView.layoutParams.width = size - iconView.layoutParams.height = size } override fun updateIcon(@BiometricState lastState: Int, @BiometricState newState: Int) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt index 368bc3aadb70..24046f08e489 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt @@ -22,6 +22,7 @@ import android.util.Log import android.widget.FrameLayout import android.widget.TextView import com.android.systemui.R +import com.android.systemui.biometrics.AuthController.ScaleFactorProvider private const val TAG = "AuthBiometricFingerprintView" @@ -35,6 +36,7 @@ open class AuthBiometricFingerprintView( private set private var udfpsAdapter: UdfpsDialogMeasureAdapter? = null + private var scaleFactorProvider: ScaleFactorProvider? = null /** Set the [sensorProps] of this sensor so the view can be customized prior to layout. */ fun setSensorProperties(sensorProps: FingerprintSensorPropertiesInternal) { @@ -42,9 +44,15 @@ open class AuthBiometricFingerprintView( udfpsAdapter = if (isUdfps) UdfpsDialogMeasureAdapter(this, sensorProps) else null } + fun setScaleFactorProvider(scaleProvider: ScaleFactorProvider?) { + scaleFactorProvider = scaleProvider + } + override fun onMeasureInternal(width: Int, height: Int): AuthDialog.LayoutParams { val layoutParams = super.onMeasureInternal(width, height) - return udfpsAdapter?.onMeasureInternal(width, height, layoutParams) ?: layoutParams + val scale = scaleFactorProvider?.provide() ?: 1.0f + return udfpsAdapter?.onMeasureInternal(width, height, layoutParams, + scale) ?: layoutParams } override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { @@ -80,6 +88,13 @@ open class AuthBiometricFingerprintView( override fun createIconController(): AuthIconController = AuthBiometricFingerprintIconController(mContext, mIconView) + fun updateOverrideIconLayoutParamsSize() { + udfpsAdapter?.let { + (mIconController as? AuthBiometricFingerprintIconController)?.iconLayoutParamsSize = + it.getSensorDiameter(scaleFactorProvider?.provide() ?: 1.0f) + } + } + override fun onAttachedToWindow() { super.onAttachedToWindow() showTouchSensorString() diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index 1413f4a81574..d7ae9ef841bf 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -59,7 +59,7 @@ import java.util.Set; /** * Contains the Biometric views (title, subtitle, icon, buttons, etc.) and its controllers. */ -public class AuthBiometricView extends LinearLayout { +public abstract class AuthBiometricView extends LinearLayout { private static final String TAG = "AuthBiometricView"; @@ -116,7 +116,7 @@ public class AuthBiometricView extends LinearLayout { void onAction(int action); } - protected final Handler mHandler; + private final Handler mHandler; private final AccessibilityManager mAccessibilityManager; private final LockPatternUtils mLockPatternUtils; protected final int mTextColorError; @@ -155,8 +155,8 @@ public class AuthBiometricView extends LinearLayout { // Measurements when biometric view is showing text, buttons, etc. @Nullable @VisibleForTesting AuthDialog.LayoutParams mLayoutParams; - protected Callback mCallback; - protected @BiometricState int mState; + private Callback mCallback; + @BiometricState private int mState; private float mIconOriginalY; @@ -166,6 +166,8 @@ public class AuthBiometricView extends LinearLayout { private final Runnable mResetErrorRunnable; private final Runnable mResetHelpRunnable; + private Animator.AnimatorListener mJankListener; + private final OnClickListener mBackgroundClickListener = (view) -> { if (mState == STATE_AUTHENTICATED) { Log.w(TAG, "Ignoring background click after authenticated"); @@ -250,18 +252,9 @@ public class AuthBiometricView extends LinearLayout { return false; } - /** - * Create the controller for managing the icons transitions during the prompt. - * - * Subclass should override. - */ + /** Create the controller for managing the icons transitions during the prompt.*/ @NonNull - protected AuthIconController createIconController() { - return new AuthIconController(mContext, mIconView) { - @Override - public void updateIcon(int lastState, int newState) {} - }; - } + protected abstract AuthIconController createIconController(); void setPanelController(AuthPanelController panelController) { mPanelController = panelController; @@ -291,6 +284,10 @@ public class AuthBiometricView extends LinearLayout { mRequireConfirmation = requireConfirmation && supportsRequireConfirmation(); } + void setJankListener(Animator.AnimatorListener jankListener) { + mJankListener = jankListener; + } + @VisibleForTesting final void updateSize(@AuthDialog.DialogSize int newSize) { Log.v(TAG, "Current size: " + mSize + " New size: " + newSize); @@ -381,6 +378,9 @@ public class AuthBiometricView extends LinearLayout { } }); + if (mJankListener != null) { + as.addListener(mJankListener); + } as.play(iconAnimator).with(opacityAnimator); as.start(); // Animate the panel @@ -436,6 +436,9 @@ public class AuthBiometricView extends LinearLayout { animators.add(translationAnimator); animators.add(opacityAnimator); + if (mJankListener != null) { + as.addListener(mJankListener); + } as.playTogether(animators); as.setDuration(mAnimationDurationLong * 2 / 3); as.start(); @@ -881,4 +884,14 @@ public class AuthBiometricView extends LinearLayout { @AuthDialog.DialogSize int getSize() { return mSize; } + + /** If authentication has successfully occurred and the view is done. */ + boolean isAuthenticated() { + return mState == STATE_AUTHENTICATED; + } + + /** If authentication is currently in progress. */ + boolean isAuthenticating() { + return mState == STATE_AUTHENTICATING; + } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index 6da2f50aac27..bc1c5f4baceb 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -19,6 +19,9 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_DEFAULT; import static android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode; +import static com.android.internal.jank.InteractionJankMonitor.CUJ_BIOMETRIC_PROMPT_TRANSITION; + +import android.animation.Animator; import android.annotation.DurationMillisLong; import android.annotation.IntDef; import android.annotation.NonNull; @@ -53,13 +56,16 @@ import android.widget.LinearLayout; import android.widget.ScrollView; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; +import com.android.systemui.biometrics.AuthController.ScaleFactorProvider; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.util.concurrency.DelayableExecutor; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.HashSet; @@ -84,6 +90,13 @@ public class AuthContainerView extends LinearLayout private static final int STATE_ANIMATING_OUT = 4; private static final int STATE_GONE = 5; + /** Shows biometric prompt dialog animation. */ + private static final String SHOW = "show"; + /** Dismiss biometric prompt dialog animation. */ + private static final String DISMISS = "dismiss"; + /** Transit biometric prompt dialog to pin, password, pattern credential panel. */ + private static final String TRANSIT = "transit"; + @Retention(RetentionPolicy.SOURCE) @IntDef({STATE_UNKNOWN, STATE_ANIMATING_IN, STATE_PENDING_DISMISS, STATE_SHOWING, STATE_ANIMATING_OUT, STATE_GONE}) @@ -98,6 +111,7 @@ public class AuthContainerView extends LinearLayout private final CredentialCallback mCredentialCallback; private final LockPatternUtils mLockPatternUtils; private final WakefulnessLifecycle mWakefulnessLifecycle; + private final InteractionJankMonitor mInteractionJankMonitor; @VisibleForTesting final BiometricCallback mBiometricCallback; @@ -133,6 +147,7 @@ public class AuthContainerView extends LinearLayout long mRequestId = -1; boolean mSkipAnimation = false; @BiometricMultiSensorMode int mMultiSensorConfig = BIOMETRIC_MULTI_SENSOR_DEFAULT; + ScaleFactorProvider mScaleProvider; } public static class Builder { @@ -196,15 +211,22 @@ public class AuthContainerView extends LinearLayout return this; } + public Builder setScaleFactorProvider(ScaleFactorProvider scaleProvider) { + mConfig.mScaleProvider = scaleProvider; + return this; + } + public AuthContainerView build(@Background DelayableExecutor bgExecutor, int[] sensorIds, @Nullable List<FingerprintSensorPropertiesInternal> fpProps, @Nullable List<FaceSensorPropertiesInternal> faceProps, @NonNull WakefulnessLifecycle wakefulnessLifecycle, @NonNull UserManager userManager, - @NonNull LockPatternUtils lockPatternUtils) { + @NonNull LockPatternUtils lockPatternUtils, + @NonNull InteractionJankMonitor jankMonitor) { mConfig.mSensorIds = sensorIds; return new AuthContainerView(mConfig, fpProps, faceProps, wakefulnessLifecycle, - userManager, lockPatternUtils, new Handler(Looper.getMainLooper()), bgExecutor); + userManager, lockPatternUtils, jankMonitor, new Handler(Looper.getMainLooper()), + bgExecutor); } } @@ -257,6 +279,7 @@ public class AuthContainerView extends LinearLayout @NonNull WakefulnessLifecycle wakefulnessLifecycle, @NonNull UserManager userManager, @NonNull LockPatternUtils lockPatternUtils, + @NonNull InteractionJankMonitor jankMonitor, @NonNull Handler mainHandler, @NonNull @Background DelayableExecutor bgExecutor) { super(config.mContext); @@ -283,6 +306,7 @@ public class AuthContainerView extends LinearLayout mPanelView = mFrameLayout.findViewById(R.id.panel); mPanelController = new AuthPanelController(mContext, mPanelView); mBackgroundExecutor = bgExecutor; + mInteractionJankMonitor = jankMonitor; // Inflate biometric view only if necessary. if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) { @@ -296,12 +320,16 @@ public class AuthContainerView extends LinearLayout (AuthBiometricFingerprintAndFaceView) layoutInflater.inflate( R.layout.auth_biometric_fingerprint_and_face_view, null, false); fingerprintAndFaceView.setSensorProperties(fpProperties); + fingerprintAndFaceView.setScaleFactorProvider(config.mScaleProvider); + fingerprintAndFaceView.updateOverrideIconLayoutParamsSize(); mBiometricView = fingerprintAndFaceView; } else if (fpProperties != null) { final AuthBiometricFingerprintView fpView = (AuthBiometricFingerprintView) layoutInflater.inflate( R.layout.auth_biometric_fingerprint_view, null, false); fpView.setSensorProperties(fpProperties); + fpView.setScaleFactorProvider(config.mScaleProvider); + fpView.updateOverrideIconLayoutParamsSize(); mBiometricView = fpView; } else if (faceProperties != null) { mBiometricView = (AuthBiometricFaceView) layoutInflater.inflate( @@ -320,6 +348,8 @@ public class AuthContainerView extends LinearLayout mBiometricView.setBackgroundView(mBackgroundView); mBiometricView.setUserId(mConfig.mUserId); mBiometricView.setEffectiveUserId(mEffectiveUserId); + mBiometricView.setJankListener(getJankListener(mBiometricView, TRANSIT, + AuthDialog.ANIMATE_MEDIUM_TO_LARGE_DURATION_MS)); } // TODO: De-dupe the logic with AuthCredentialPasswordView @@ -447,6 +477,7 @@ public class AuthContainerView extends LinearLayout .translationY(0) .setDuration(animateDuration) .setInterpolator(mLinearOutSlowIn) + .setListener(getJankListener(mPanelView, SHOW, animateDuration)) .withLayer() .withEndAction(this::onDialogAnimatedIn) .start(); @@ -454,6 +485,7 @@ public class AuthContainerView extends LinearLayout .translationY(0) .setDuration(animateDuration) .setInterpolator(mLinearOutSlowIn) + .setListener(getJankListener(mBiometricScrollView, SHOW, animateDuration)) .withLayer() .start(); if (mCredentialView != null && mCredentialView.isAttachedToWindow()) { @@ -462,6 +494,7 @@ public class AuthContainerView extends LinearLayout .translationY(0) .setDuration(animateDuration) .setInterpolator(mLinearOutSlowIn) + .setListener(getJankListener(mCredentialView, SHOW, animateDuration)) .withLayer() .start(); } @@ -470,11 +503,49 @@ public class AuthContainerView extends LinearLayout .setDuration(animateDuration) .setInterpolator(mLinearOutSlowIn) .withLayer() + .setListener(getJankListener(this, SHOW, animateDuration)) .start(); }); } } + private Animator.AnimatorListener getJankListener(View v, String type, long timeout) { + return new Animator.AnimatorListener() { + @Override + public void onAnimationStart(@androidx.annotation.NonNull Animator animation) { + if (!v.isAttachedToWindow()) { + Log.w(TAG, "Un-attached view should not begin Jank trace."); + return; + } + mInteractionJankMonitor.begin(InteractionJankMonitor.Configuration.Builder.withView( + CUJ_BIOMETRIC_PROMPT_TRANSITION, v).setTag(type).setTimeout(timeout)); + } + + @Override + public void onAnimationEnd(@androidx.annotation.NonNull Animator animation) { + if (!v.isAttachedToWindow()) { + Log.w(TAG, "Un-attached view should not end Jank trace."); + return; + } + mInteractionJankMonitor.end(CUJ_BIOMETRIC_PROMPT_TRANSITION); + } + + @Override + public void onAnimationCancel(@androidx.annotation.NonNull Animator animation) { + if (!v.isAttachedToWindow()) { + Log.w(TAG, "Un-attached view should not cancel Jank trace."); + return; + } + mInteractionJankMonitor.cancel(CUJ_BIOMETRIC_PROMPT_TRANSITION); + } + + @Override + public void onAnimationRepeat(@androidx.annotation.NonNull Animator animation) { + // no-op + } + }; + } + private static boolean shouldUpdatePositionForUdfps(@NonNull View view) { if (view instanceof AuthBiometricFingerprintView) { return ((AuthBiometricFingerprintView) view).isUdfps(); @@ -658,6 +729,7 @@ public class AuthContainerView extends LinearLayout .translationY(mTranslationY) .setDuration(animateDuration) .setInterpolator(mLinearOutSlowIn) + .setListener(getJankListener(mPanelView, DISMISS, animateDuration)) .withLayer() .withEndAction(endActionRunnable) .start(); @@ -665,6 +737,7 @@ public class AuthContainerView extends LinearLayout .translationY(mTranslationY) .setDuration(animateDuration) .setInterpolator(mLinearOutSlowIn) + .setListener(getJankListener(mBiometricScrollView, DISMISS, animateDuration)) .withLayer() .start(); if (mCredentialView != null && mCredentialView.isAttachedToWindow()) { @@ -672,6 +745,7 @@ public class AuthContainerView extends LinearLayout .translationY(mTranslationY) .setDuration(animateDuration) .setInterpolator(mLinearOutSlowIn) + .setListener(getJankListener(mCredentialView, DISMISS, animateDuration)) .withLayer() .start(); } @@ -679,6 +753,7 @@ public class AuthContainerView extends LinearLayout .alpha(0f) .setDuration(animateDuration) .setInterpolator(mLinearOutSlowIn) + .setListener(getJankListener(this, DISMISS, animateDuration)) .withLayer() .start(); }); @@ -739,4 +814,36 @@ public class AuthContainerView extends LinearLayout lp.token = windowToken; return lp; } + + @Override + public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { + pw.println(" isAttachedToWindow=" + isAttachedToWindow()); + pw.println(" containerState=" + mContainerState); + pw.println(" pendingCallbackReason=" + mPendingCallbackReason); + pw.println(" config exist=" + (mConfig != null)); + if (mConfig != null) { + pw.println(" config.sensorIds exist=" + (mConfig.mSensorIds != null)); + } + final AuthBiometricView biometricView = mBiometricView; + pw.println(" scrollView=" + findViewById(R.id.biometric_scrollview)); + pw.println(" biometricView=" + biometricView); + if (biometricView != null) { + int[] ids = { + R.id.title, + R.id.subtitle, + R.id.description, + R.id.biometric_icon_frame, + R.id.biometric_icon, + R.id.indicator, + R.id.button_bar, + R.id.button_negative, + R.id.button_use_credential, + R.id.button_confirm, + R.id.button_try_again + }; + for (final int id: ids) { + pw.println(" " + biometricView.findViewById(id)); + } + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 17396469c10a..a097c5e76149 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -62,6 +62,7 @@ import android.view.WindowManager; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.os.SomeArgs; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.CoreStartable; @@ -75,6 +76,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.Execution; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -143,6 +145,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba private boolean mAllFingerprintAuthenticatorsRegistered; @NonNull private final UserManager mUserManager; @NonNull private final LockPatternUtils mLockPatternUtils; + @NonNull private final InteractionJankMonitor mInteractionJankMonitor; private final @Background DelayableExecutor mBackgroundExecutor; @VisibleForTesting @@ -489,6 +492,9 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio( mStableDisplaySize.x, mStableDisplaySize.y, displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight()); + if (scaleFactor == Float.POSITIVE_INFINITY) { + return new PointF(mFaceAuthSensorLocation.x, mFaceAuthSensorLocation.y); + } return new PointF(mFaceAuthSensorLocation.x * scaleFactor, mFaceAuthSensorLocation.y * scaleFactor); } @@ -549,6 +555,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba @NonNull UserManager userManager, @NonNull LockPatternUtils lockPatternUtils, @NonNull StatusBarStateController statusBarStateController, + @NonNull InteractionJankMonitor jankMonitor, @Main Handler handler, @Background DelayableExecutor bgExecutor) { super(context); @@ -566,6 +573,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba mSidefpsControllerFactory = sidefpsControllerFactory; mDisplayManager = displayManager; mWindowManager = windowManager; + mInteractionJankMonitor = jankMonitor; mUdfpsEnrolledForUser = new SparseBooleanArray(); mOrientationListener = new BiometricDisplayListener( @@ -1037,8 +1045,36 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba .setOperationId(operationId) .setRequestId(requestId) .setMultiSensorConfig(multiSensorConfig) + .setScaleFactorProvider(() -> { + return getScaleFactor(); + }) .build(bgExecutor, sensorIds, mFpProps, mFaceProps, wakefulnessLifecycle, - userManager, lockPatternUtils); + userManager, lockPatternUtils, mInteractionJankMonitor); + } + + @Override + public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { + final AuthDialog dialog = mCurrentDialog; + pw.println(" stableDisplaySize=" + mStableDisplaySize); + pw.println(" faceAuthSensorLocation=" + mFaceAuthSensorLocation); + pw.println(" fingerprintLocation=" + mFingerprintLocation); + pw.println(" udfpsBounds=" + mUdfpsBounds); + pw.println(" allFingerprintAuthenticatorsRegistered=" + + mAllFingerprintAuthenticatorsRegistered); + pw.println(" currentDialog=" + dialog); + if (dialog != null) { + dialog.dump(pw, args); + } + } + + /** + * Provides a float that represents the resolution scale(if the controller is for UDFPS). + */ + public interface ScaleFactorProvider { + /** + * Returns a float representing the scaled resolution(if the controller if for UDFPS). + */ + float provide(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java index 4ff19f6adc11..51f39b358659 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java @@ -23,13 +23,15 @@ import android.hardware.biometrics.BiometricAuthenticator.Modality; import android.os.Bundle; import android.view.WindowManager; +import com.android.systemui.Dumpable; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Interface for the biometric dialog UI. */ -public interface AuthDialog { +public interface AuthDialog extends Dumpable { String KEY_CONTAINER_GOING_AWAY = "container_going_away"; String KEY_BIOMETRIC_SHOWING = "biometric_showing"; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt index 86e501670440..38fab8ffbfad 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt @@ -23,7 +23,6 @@ import android.content.Context import android.graphics.PointF import android.hardware.biometrics.BiometricFingerprintConstants import android.hardware.biometrics.BiometricSourceType -import android.util.DisplayMetrics import android.util.Log import androidx.annotation.VisibleForTesting import com.android.keyguard.KeyguardUpdateMonitor @@ -46,7 +45,6 @@ import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.Cent import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.ViewController -import com.android.systemui.util.leak.RotationUtils import java.io.PrintWriter import javax.inject.Inject import javax.inject.Provider @@ -127,17 +125,37 @@ class AuthRippleController @Inject constructor( } updateSensorLocation() - if (biometricSourceType == BiometricSourceType.FINGERPRINT && - fingerprintSensorLocation != null) { - mView.setFingerprintSensorLocation(fingerprintSensorLocation!!, udfpsRadius) - showUnlockedRipple() - } else if (biometricSourceType == BiometricSourceType.FACE && - faceSensorLocation != null) { - if (!bypassController.canBypass()) { + if (biometricSourceType == BiometricSourceType.FINGERPRINT) { + fingerprintSensorLocation?.let { + mView.setFingerprintSensorLocation(it, udfpsRadius) + circleReveal = CircleReveal( + it.x, + it.y, + 0f, + Math.max( + Math.max(it.x, centralSurfaces.displayWidth - it.x), + Math.max(it.y, centralSurfaces.displayHeight - it.y) + ) + ) + showUnlockedRipple() + } + } else if (biometricSourceType == BiometricSourceType.FACE) { + if (!bypassController.canBypass() && !authController.isUdfpsFingerDown) { return } - mView.setSensorLocation(faceSensorLocation!!) - showUnlockedRipple() + faceSensorLocation?.let { + mView.setSensorLocation(it) + circleReveal = CircleReveal( + it.x, + it.y, + 0f, + Math.max( + Math.max(it.x, centralSurfaces.displayWidth - it.x), + Math.max(it.y, centralSurfaces.displayHeight - it.y) + ) + ) + showUnlockedRipple() + } } } @@ -209,48 +227,8 @@ class AuthRippleController @Inject constructor( } fun updateSensorLocation() { - updateFingerprintLocation() + fingerprintSensorLocation = authController.fingerprintSensorLocation faceSensorLocation = authController.faceAuthSensorLocation - fingerprintSensorLocation?.let { - circleReveal = CircleReveal( - it.x, - it.y, - 0f, - Math.max( - Math.max(it.x, centralSurfaces.displayWidth - it.x), - Math.max(it.y, centralSurfaces.displayHeight - it.y) - ) - ) - } - } - - private fun updateFingerprintLocation() { - val displayMetrics = DisplayMetrics() - sysuiContext.display?.getRealMetrics(displayMetrics) - val width = displayMetrics.widthPixels - val height = displayMetrics.heightPixels - - authController.fingerprintSensorLocation?.let { - fingerprintSensorLocation = when (RotationUtils.getRotation(sysuiContext)) { - RotationUtils.ROTATION_LANDSCAPE -> { - val normalizedYPos: Float = it.y / width - val normalizedXPos: Float = it.x / height - PointF(width * normalizedYPos, height * (1 - normalizedXPos)) - } - RotationUtils.ROTATION_UPSIDE_DOWN -> { - PointF(width - it.x, height - it.y) - } - RotationUtils.ROTATION_SEASCAPE -> { - val normalizedYPos: Float = it.y / width - val normalizedXPos: Float = it.x / height - PointF(width * (1 - normalizedYPos), height * normalizedXPos) - } - else -> { - // ROTATION_NONE - PointF(it.x, it.y) - } - } - } } private fun updateRippleColor() { @@ -372,6 +350,7 @@ class AuthRippleController @Inject constructor( showUnlockRipple(BiometricSourceType.FINGERPRINT) } "face" -> { + // note: only shows when about to proceed to the home screen updateSensorLocation() pw.println("face ripple sensorLocation=$faceSensorLocation") showUnlockRipple(BiometricSourceType.FACE) diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 6e2dcae4728e..fb502e5b72cc 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -20,6 +20,7 @@ import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPR import static android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD; import static com.android.internal.util.Preconditions.checkNotNull; +import static com.android.systemui.classifier.Classifier.LOCK_ICON; import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION; import android.annotation.NonNull; @@ -167,11 +168,16 @@ public class UdfpsController implements DozeReceiver { private final Set<Callback> mCallbacks = new HashSet<>(); @VisibleForTesting - public static final VibrationAttributes VIBRATION_ATTRIBUTES = + public static final VibrationAttributes UDFPS_VIBRATION_ATTRIBUTES = new VibrationAttributes.Builder() // vibration will bypass battery saver mode: .setUsage(VibrationAttributes.USAGE_COMMUNICATION_REQUEST) .build(); + @VisibleForTesting + public static final VibrationAttributes LOCK_ICON_VIBRATION_ATTRIBUTES = + new VibrationAttributes.Builder() + .setUsage(VibrationAttributes.USAGE_TOUCH) + .build(); // haptic to use for successful device entry public static final VibrationEffect EFFECT_CLICK = @@ -671,7 +677,7 @@ public class UdfpsController implements DozeReceiver { mContext.getOpPackageName(), EFFECT_CLICK, "udfps-onStart-click", - VIBRATION_ATTRIBUTES); + UDFPS_VIBRATION_ATTRIBUTES); } } @@ -748,7 +754,19 @@ public class UdfpsController implements DozeReceiver { } if (!mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) { + if (mFalsingManager.isFalseTouch(LOCK_ICON)) { + Log.v(TAG, "aod lock icon long-press rejected by the falsing manager."); + return; + } mKeyguardViewManager.showBouncer(true); + + // play the same haptic as the LockIconViewController longpress + mVibrator.vibrate( + Process.myUid(), + mContext.getOpPackageName(), + UdfpsController.EFFECT_CLICK, + "aod-lock-icon-longpress", + LOCK_ICON_VIBRATION_ATTRIBUTES); return; } @@ -841,6 +859,11 @@ public class UdfpsController implements DozeReceiver { mBiometricExecutor.execute(() -> { mAlternateTouchProvider.onPointerDown(requestId, x, y, minor, major); }); + mFgExecutor.execute(() -> { + if (mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) { + mKeyguardUpdateMonitor.onUdfpsPointerDown((int) requestId); + } + }); } else { mFingerprintManager.onPointerDown(requestId, mSensorId, x, y, minor, major); } @@ -856,7 +879,6 @@ public class UdfpsController implements DozeReceiver { } else { mFingerprintManager.onUiReady(requestId, mSensorId); mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE); - } }); } @@ -875,6 +897,11 @@ public class UdfpsController implements DozeReceiver { mBiometricExecutor.execute(() -> { mAlternateTouchProvider.onPointerUp(requestId); }); + mFgExecutor.execute(() -> { + if (mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) { + mKeyguardUpdateMonitor.onUdfpsPointerUp((int) requestId); + } + }); } else { mFingerprintManager.onPointerUp(requestId, mSensorId); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java index 8de721352069..43745bf74aae 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java @@ -64,15 +64,16 @@ public class UdfpsDialogMeasureAdapter { @NonNull AuthDialog.LayoutParams onMeasureInternal( - int width, int height, @NonNull AuthDialog.LayoutParams layoutParams) { + int width, int height, @NonNull AuthDialog.LayoutParams layoutParams, + float scaleFactor) { final int displayRotation = mView.getDisplay().getRotation(); switch (displayRotation) { case Surface.ROTATION_0: - return onMeasureInternalPortrait(width, height); + return onMeasureInternalPortrait(width, height, scaleFactor); case Surface.ROTATION_90: case Surface.ROTATION_270: - return onMeasureInternalLandscape(width, height); + return onMeasureInternalLandscape(width, height, scaleFactor); default: Log.e(TAG, "Unsupported display rotation: " + displayRotation); return layoutParams; @@ -89,8 +90,16 @@ public class UdfpsDialogMeasureAdapter { return mBottomSpacerHeight; } + /** + * @return sensor diameter size as scaleFactor + */ + public int getSensorDiameter(float scaleFactor) { + return (int) (scaleFactor * mSensorProps.getLocation().sensorRadius * 2); + } + @NonNull - private AuthDialog.LayoutParams onMeasureInternalPortrait(int width, int height) { + private AuthDialog.LayoutParams onMeasureInternalPortrait(int width, int height, + float scaleFactor) { final WindowMetrics windowMetrics = mWindowManager.getMaximumWindowMetrics(); // Figure out where the bottom of the sensor anim should be. @@ -101,12 +110,12 @@ public class UdfpsDialogMeasureAdapter { final Insets navbarInsets = getNavbarInsets(windowMetrics); mBottomSpacerHeight = calculateBottomSpacerHeightForPortrait( mSensorProps, displayHeight, textIndicatorHeight, buttonBarHeight, - dialogMargin, navbarInsets.bottom); + dialogMargin, navbarInsets.bottom, scaleFactor); // Go through each of the children and do the custom measurement. int totalHeight = 0; final int numChildren = mView.getChildCount(); - final int sensorDiameter = mSensorProps.getLocation().sensorRadius * 2; + final int sensorDiameter = getSensorDiameter(scaleFactor); for (int i = 0; i < numChildren; i++) { final View child = mView.getChildAt(i); if (child.getId() == R.id.biometric_icon_frame) { @@ -176,7 +185,8 @@ public class UdfpsDialogMeasureAdapter { } @NonNull - private AuthDialog.LayoutParams onMeasureInternalLandscape(int width, int height) { + private AuthDialog.LayoutParams onMeasureInternalLandscape(int width, int height, + float scaleFactor) { final WindowMetrics windowMetrics = mWindowManager.getMaximumWindowMetrics(); // Find the spacer height needed to vertically align the icon with the sensor. @@ -197,9 +207,9 @@ public class UdfpsDialogMeasureAdapter { final int dialogMargin = getDialogMarginPx(); final int horizontalInset = navbarInsets.left + navbarInsets.right; final int horizontalSpacerWidth = calculateHorizontalSpacerWidthForLandscape( - mSensorProps, displayWidth, dialogMargin, horizontalInset); + mSensorProps, displayWidth, dialogMargin, horizontalInset, scaleFactor); - final int sensorDiameter = mSensorProps.getLocation().sensorRadius * 2; + final int sensorDiameter = getSensorDiameter(scaleFactor); final int remeasuredWidth = sensorDiameter + 2 * horizontalSpacerWidth; int remeasuredHeight = 0; @@ -281,11 +291,11 @@ public class UdfpsDialogMeasureAdapter { static int calculateBottomSpacerHeightForPortrait( @NonNull FingerprintSensorPropertiesInternal sensorProperties, int displayHeightPx, int textIndicatorHeightPx, int buttonBarHeightPx, int dialogMarginPx, - int navbarBottomInsetPx) { + int navbarBottomInsetPx, float scaleFactor) { final SensorLocationInternal location = sensorProperties.getLocation(); final int sensorDistanceFromBottom = displayHeightPx - - location.sensorLocationY - - location.sensorRadius; + - (int) (scaleFactor * location.sensorLocationY) + - (int) (scaleFactor * location.sensorRadius); final int spacerHeight = sensorDistanceFromBottom - textIndicatorHeightPx @@ -298,7 +308,8 @@ public class UdfpsDialogMeasureAdapter { + ", Distance from bottom: " + sensorDistanceFromBottom + ", Bottom margin: " + dialogMarginPx + ", Navbar bottom inset: " + navbarBottomInsetPx - + ", Bottom spacer height (portrait): " + spacerHeight); + + ", Bottom spacer height (portrait): " + spacerHeight + + ", Scale Factor: " + scaleFactor); } return spacerHeight; @@ -346,11 +357,11 @@ public class UdfpsDialogMeasureAdapter { @VisibleForTesting static int calculateHorizontalSpacerWidthForLandscape( @NonNull FingerprintSensorPropertiesInternal sensorProperties, int displayWidthPx, - int dialogMarginPx, int navbarHorizontalInsetPx) { + int dialogMarginPx, int navbarHorizontalInsetPx, float scaleFactor) { final SensorLocationInternal location = sensorProperties.getLocation(); final int sensorDistanceFromEdge = displayWidthPx - - location.sensorLocationY - - location.sensorRadius; + - (int) (scaleFactor * location.sensorLocationY) + - (int) (scaleFactor * location.sensorRadius); final int horizontalPadding = sensorDistanceFromEdge - dialogMarginPx @@ -361,7 +372,8 @@ public class UdfpsDialogMeasureAdapter { + ", Distance from edge: " + sensorDistanceFromEdge + ", Dialog margin: " + dialogMarginPx + ", Navbar horizontal inset: " + navbarHorizontalInsetPx - + ", Horizontal spacer width (landscape): " + horizontalPadding); + + ", Horizontal spacer width (landscape): " + horizontalPadding + + ", Scale Factor: " + scaleFactor); } return horizontalPadding; diff --git a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt index 03ee8b11ab41..169b50edccfc 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt @@ -79,4 +79,16 @@ abstract class CornerDecorProvider : DecorProvider() { override val alignedBounds: List<Int> by lazy { listOf(alignedBound1, alignedBound2) } -}
\ No newline at end of file +} + +/** + * A provider for view shown on bound. + */ +abstract class BoundDecorProvider : DecorProvider() { + /** The bound which a view is aligned based on rotation 0 */ + @DisplayCutout.BoundsPosition protected abstract val alignedBound: Int + + override val alignedBounds: List<Int> by lazy { + listOf(alignedBound) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt new file mode 100644 index 000000000000..81d3d6caebd7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2022 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.decor + +import android.content.Context +import android.util.Log +import android.view.DisplayCutout +import android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM +import android.view.DisplayCutout.BOUNDS_POSITION_LEFT +import android.view.DisplayCutout.BOUNDS_POSITION_RIGHT +import android.view.DisplayCutout.BOUNDS_POSITION_TOP +import android.view.DisplayInfo +import android.view.Gravity +import android.view.Surface +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.FaceScanningOverlay +import com.android.systemui.biometrics.AuthController +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags +import com.android.systemui.plugins.statusbar.StatusBarStateController +import java.util.concurrent.Executor +import javax.inject.Inject + +@SysUISingleton +class FaceScanningProviderFactory @Inject constructor( + private val authController: AuthController, + private val context: Context, + private val statusBarStateController: StatusBarStateController, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + @Main private val mainExecutor: Executor, + private val featureFlags: FeatureFlags +) : DecorProviderFactory() { + private val display = context.display + private val displayInfo = DisplayInfo() + + override val hasProviders: Boolean + get() { + if (!featureFlags.isEnabled(Flags.FACE_SCANNING_ANIM) || + authController.faceAuthSensorLocation == null) { + return false + } + + // update display info + display?.getDisplayInfo(displayInfo) ?: run { + Log.w(TAG, "display is null, can't update displayInfo") + } + return DisplayCutout.getFillBuiltInDisplayCutout( + context.resources, displayInfo.uniqueId) + } + + override val providers: List<DecorProvider> + get() { + if (!hasProviders) { + return emptyList() + } + + return ArrayList<DecorProvider>().also { list -> + // displayInfo must be updated before using it; however it will already have + // been updated when accessing the hasProviders field above + displayInfo.displayCutout?.getBoundBaseOnCurrentRotation()?.let { bounds -> + // Add a face scanning view for each screen orientation. + // Cutout drawing is updated in ScreenDecorations#updateCutout + for (bound in bounds) { + list.add( + FaceScanningOverlayProviderImpl( + bound.baseOnRotation0(displayInfo.rotation), + authController, + statusBarStateController, + keyguardUpdateMonitor, + mainExecutor + ) + ) + } + } + } + } + + fun canShowFaceScanningAnim(): Boolean { + return hasProviders && keyguardUpdateMonitor.isFaceEnrolled + } + + fun shouldShowFaceScanningAnim(): Boolean { + return canShowFaceScanningAnim() && keyguardUpdateMonitor.isFaceScanning + } +} + +class FaceScanningOverlayProviderImpl( + override val alignedBound: Int, + private val authController: AuthController, + private val statusBarStateController: StatusBarStateController, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val mainExecutor: Executor +) : BoundDecorProvider() { + override val viewId: Int = com.android.systemui.R.id.face_scanning_anim + + override fun onReloadResAndMeasure( + view: View, + reloadToken: Int, + rotation: Int, + displayUniqueId: String? + ) { + (view.layoutParams as FrameLayout.LayoutParams).let { + updateLayoutParams(it, rotation) + view.layoutParams = it + } + } + + override fun inflateView( + context: Context, + parent: ViewGroup, + @Surface.Rotation rotation: Int + ): View { + val view = FaceScanningOverlay( + context, + alignedBound, + statusBarStateController, + keyguardUpdateMonitor, + mainExecutor + ) + view.id = viewId + FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT).let { + updateLayoutParams(it, rotation) + parent.addView(view, it) + } + return view + } + + private fun updateLayoutParams( + layoutParams: FrameLayout.LayoutParams, + @Surface.Rotation rotation: Int + ) { + layoutParams.let { lp -> + lp.width = ViewGroup.LayoutParams.MATCH_PARENT + lp.height = ViewGroup.LayoutParams.MATCH_PARENT + authController.faceAuthSensorLocation?.y?.let { faceAuthSensorHeight -> + val faceScanningHeight = (faceAuthSensorHeight * 2).toInt() + when (rotation) { + Surface.ROTATION_0, Surface.ROTATION_180 -> + lp.height = faceScanningHeight + Surface.ROTATION_90, Surface.ROTATION_270 -> + lp.width = faceScanningHeight + } + } + + lp.gravity = when (rotation) { + Surface.ROTATION_0 -> Gravity.TOP or Gravity.START + Surface.ROTATION_90 -> Gravity.LEFT or Gravity.START + Surface.ROTATION_180 -> Gravity.BOTTOM or Gravity.END + Surface.ROTATION_270 -> Gravity.RIGHT or Gravity.END + else -> -1 /* invalid rotation */ + } + } + } +} + +fun DisplayCutout.getBoundBaseOnCurrentRotation(): List<Int> { + return ArrayList<Int>().also { + if (!boundingRectLeft.isEmpty) { + it.add(BOUNDS_POSITION_LEFT) + } + if (!boundingRectTop.isEmpty) { + it.add(BOUNDS_POSITION_TOP) + } + if (!boundingRectRight.isEmpty) { + it.add(BOUNDS_POSITION_RIGHT) + } + if (!boundingRectBottom.isEmpty) { + it.add(BOUNDS_POSITION_BOTTOM) + } + } +} + +fun Int.baseOnRotation0(@DisplayCutout.BoundsPosition currentRotation: Int): Int { + return when (currentRotation) { + Surface.ROTATION_0 -> this + Surface.ROTATION_90 -> when (this) { + BOUNDS_POSITION_LEFT -> BOUNDS_POSITION_TOP + BOUNDS_POSITION_TOP -> BOUNDS_POSITION_RIGHT + BOUNDS_POSITION_RIGHT -> BOUNDS_POSITION_BOTTOM + else /* BOUNDS_POSITION_BOTTOM */ -> BOUNDS_POSITION_LEFT + } + Surface.ROTATION_270 -> when (this) { + BOUNDS_POSITION_LEFT -> BOUNDS_POSITION_BOTTOM + BOUNDS_POSITION_TOP -> BOUNDS_POSITION_LEFT + BOUNDS_POSITION_RIGHT -> BOUNDS_POSITION_TOP + else /* BOUNDS_POSITION_BOTTOM */ -> BOUNDS_POSITION_RIGHT + } + else /* Surface.ROTATION_180 */ -> when (this) { + BOUNDS_POSITION_LEFT -> BOUNDS_POSITION_RIGHT + BOUNDS_POSITION_TOP -> BOUNDS_POSITION_BOTTOM + BOUNDS_POSITION_RIGHT -> BOUNDS_POSITION_LEFT + else /* BOUNDS_POSITION_BOTTOM */ -> BOUNDS_POSITION_TOP + } + } +} + +private const val TAG = "FaceScanningProvider" diff --git a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt index 136f135af759..9f624b3dcb09 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt @@ -28,6 +28,10 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import javax.inject.Inject +/** + * Provides privacy dot views for each orientation. The PrivacyDot orientation and visibility + * of the privacy dot views are controlled by the PrivacyDotViewController. + */ @SysUISingleton class PrivacyDotDecorProviderFactory @Inject constructor( @Main private val res: Resources diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index c8720e409883..da6c163b1eea 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -183,7 +183,8 @@ public class DozeSensors { mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION), null /* setting */, dozeParameters.getPulseOnSigMotion(), - DozeLog.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */, + DozeLog.PULSE_REASON_SENSOR_SIGMOTION, + false /* touchCoords */, false /* touchscreen */), new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE), @@ -193,7 +194,8 @@ public class DozeSensors { DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */, false /* touchscreen */, false /* ignoresSetting */, - false /* requires prox */), + false /* requires prox */, + true /* immediatelyReRegister */), new TriggerSensor( findSensor(config.doubleTapSensorType()), Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, @@ -211,6 +213,7 @@ public class DozeSensors { true /* touchscreen */, false /* ignoresSetting */, dozeParameters.singleTapUsesProx(mDevicePosture) /* requiresProx */, + true /* immediatelyReRegister */, mDevicePosture), new TriggerSensor( findSensor(config.longPressSensorType()), @@ -221,7 +224,8 @@ public class DozeSensors { true /* reports touch coordinates */, true /* touchscreen */, false /* ignoresSetting */, - dozeParameters.longPressUsesProx() /* requiresProx */), + dozeParameters.longPressUsesProx() /* requiresProx */, + true /* immediatelyReRegister */), new TriggerSensor( findSensor(config.udfpsLongPressSensorType()), "doze_pulse_on_auth", @@ -231,7 +235,8 @@ public class DozeSensors { true /* reports touch coordinates */, true /* touchscreen */, false /* ignoresSetting */, - dozeParameters.longPressUsesProx()), + dozeParameters.longPressUsesProx(), + false /* immediatelyReRegister */), new PluginSensor( new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY), Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, @@ -257,7 +262,8 @@ public class DozeSensors { false /* requiresTouchCoordinates */, false /* requiresTouchscreen */, false /* ignoresSetting */, - false /* requiresProx */), + false /* requiresProx */, + true /* immediatelyReRegister */), }; setProxListening(false); // Don't immediately start listening when we register. mProximitySensor.register( @@ -493,6 +499,10 @@ public class DozeSensors { private final boolean mRequiresTouchscreen; private final boolean mRequiresProx; + // Whether to immediately re-register this sensor after the sensor is triggered. + // If false, the sensor registration will be updated on the next AOD state transition. + private final boolean mImmediatelyReRegister; + protected boolean mRequested; protected boolean mRegistered; protected boolean mDisabled; @@ -516,7 +526,8 @@ public class DozeSensors { reportsTouchCoordinates, requiresTouchscreen, false /* ignoresSetting */, - false /* requiresProx */ + false /* requiresProx */, + true /* immediatelyReRegister */ ); } @@ -529,7 +540,8 @@ public class DozeSensors { boolean reportsTouchCoordinates, boolean requiresTouchscreen, boolean ignoresSetting, - boolean requiresProx + boolean requiresProx, + boolean immediatelyReRegister ) { this( new Sensor[]{ sensor }, @@ -541,6 +553,7 @@ public class DozeSensors { requiresTouchscreen, ignoresSetting, requiresProx, + immediatelyReRegister, DevicePostureController.DEVICE_POSTURE_UNKNOWN ); } @@ -555,6 +568,7 @@ public class DozeSensors { boolean requiresTouchscreen, boolean ignoresSetting, boolean requiresProx, + boolean immediatelyReRegister, @DevicePostureController.DevicePostureInt int posture ) { mSensors = sensors; @@ -567,6 +581,7 @@ public class DozeSensors { mIgnoresSetting = ignoresSetting; mRequiresProx = requiresProx; mPosture = posture; + mImmediatelyReRegister = immediatelyReRegister; } /** @@ -702,8 +717,8 @@ public class DozeSensors { screenY = event.values[1]; } mSensorCallback.onSensorPulse(mPulseReason, screenX, screenY, event.values); - if (!mRegistered) { - updateListening(); // reregister, this sensor only fires once + if (!mRegistered && mImmediatelyReRegister) { + updateListening(); } })); } diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index c43dd9041a50..2c798307c196 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -80,6 +80,9 @@ public class Flags { public static final ResourceBooleanFlag BOUNCER_USER_SWITCHER = new ResourceBooleanFlag(204, R.bool.config_enableBouncerUserSwitcher); + public static final ResourceBooleanFlag FACE_SCANNING_ANIM = + new ResourceBooleanFlag(205, R.bool.config_enableFaceScanningAnimation); + /***************************************/ // 300 - power menu public static final BooleanFlag POWER_MENU_LITE = diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index c686b48278a3..5ffc3f101c6f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -169,7 +169,8 @@ class KeyguardUnlockAnimationController @Inject constructor( playingCannedAnimation: Boolean, fromWakeAndUnlock: Boolean, unlockAnimationStartDelay: Long, - unlockAnimationDuration: Long) {} + unlockAnimationDuration: Long + ) {} /** * Called when the remote unlock animation ends, in all cases, canned or swipe-to-unlock. @@ -308,8 +309,12 @@ class KeyguardUnlockAnimationController @Inject constructor( // call onKeyguardExitRemoteAnimationFinished since that will hide the keyguard // and unlock the device as well as hiding the surface. if (surfaceBehindAlpha == 0f) { + Log.d(TAG, "surfaceBehindAlphaAnimator#onAnimationEnd") keyguardViewMediator.get().finishSurfaceBehindRemoteAnimation( false /* cancelled */) + } else { + Log.d(TAG, "skip finishSurfaceBehindRemoteAnimation" + + " surfaceBehindAlpha=$surfaceBehindAlpha") } } }) @@ -325,6 +330,7 @@ class KeyguardUnlockAnimationController @Inject constructor( } addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { + Log.d(TAG, "surfaceBehindEntryAnimator#onAnimationEnd") playingCannedUnlockAnimation = false keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished( false /* cancelled */ @@ -361,7 +367,6 @@ class KeyguardUnlockAnimationController @Inject constructor( // the animations since they won't be visible. !notificationShadeWindowController.isLaunchingActivity && launcherUnlockController != null && - !keyguardStateController.isDismissingFromSwipe && // Temporarily disable for foldables since foldable launcher has two first pages, // which breaks the in-window animation. !isFoldable(context) @@ -372,8 +377,8 @@ class KeyguardUnlockAnimationController @Inject constructor( * changed. */ override fun onKeyguardGoingAwayChanged() { - if (keyguardStateController.isKeyguardGoingAway - && !statusBarStateController.leaveOpenOnKeyguardHide()) { + if (keyguardStateController.isKeyguardGoingAway && + !statusBarStateController.leaveOpenOnKeyguardHide()) { prepareForInWindowLauncherAnimations() } } @@ -427,7 +432,7 @@ class KeyguardUnlockAnimationController @Inject constructor( launcherUnlockController?.prepareForUnlock( willUnlockWithSmartspaceTransition, /* willAnimateSmartspace */ lockscreenSmartspaceBounds, /* lockscreenSmartspaceBounds */ - selectedPage, /* selectedPage */ + selectedPage /* selectedPage */ ) } catch (e: RemoteException) { Log.e(TAG, "Remote exception in prepareForInWindowUnlockAnimations.", e) @@ -466,16 +471,34 @@ class KeyguardUnlockAnimationController @Inject constructor( // If we specifically requested that the surface behind be made visible (vs. it being made // visible because we're unlocking), then we're in the middle of a swipe-to-unlock touch - // gesture and the surface behind the keyguard should be made visible. + // gesture and the surface behind the keyguard should be made visible so that we can animate + // it in. if (requestedShowSurfaceBehindKeyguard) { - // Fade in the surface, as long as we're not now flinging. The touch gesture ending in - // a fling during the time it takes the keyguard exit animation to start is an edge - // case race condition, and we'll handle it by playing a canned animation on the - // now-visible surface to finish unlocking. - if (!keyguardStateController.isFlingingToDismissKeyguard) { - fadeInSurfaceBehind() - } else { + + // If we're flinging to dismiss here, it means the touch gesture ended in a fling during + // the time it takes the keyguard exit animation to start. This is an edge case race + // condition, which we handle by just playing a canned animation on the now-visible + // surface behind the keyguard to finish unlocking. + if (keyguardStateController.isFlingingToDismissKeyguard) { playCannedUnlockAnimation() + } else if (keyguardStateController.isDismissingFromSwipe + && willUnlockWithInWindowLauncherAnimations) { + // If we're swiping to unlock to the Launcher, and can play in-window animations, + // make the launcher surface fully visible and play the in-window unlock animation + // on the launcher icons. System UI will remain locked, using the swipe-to-unlock + // translation logic on the launcher window, until the swipe gesture ends (either in + // a successful unlock, or an aborted unlock). + surfaceBehindAlpha = 1f + setSurfaceBehindAppearAmount(1f) + + launcherUnlockController?.playUnlockAnimation( + true, + UNLOCK_ANIMATION_DURATION_MS + CANNED_UNLOCK_START_DELAY, + 0 /* startDelay */) + } else { + // Otherwise, we're swiping in an app and should just fade it in. The swipe gesture + // will translate it until the end of the swipe gesture. + fadeInSurfaceBehind() } } else { // The surface was made visible since we're unlocking not from a swipe (fingerprint, @@ -502,19 +525,23 @@ class KeyguardUnlockAnimationController @Inject constructor( * by the dismiss amount via [onKeyguardDismissAmountChanged]. */ private fun playCannedUnlockAnimation() { + Log.d(TAG, "playCannedUnlockAnimation") playingCannedUnlockAnimation = true - when { // If we're set up for in-window launcher animations, ask Launcher to play its in-window // canned animation. - willUnlockWithInWindowLauncherAnimations -> unlockToLauncherWithInWindowAnimations() + willUnlockWithInWindowLauncherAnimations -> { + Log.d(TAG, "playCannedUnlockAnimation, unlockToLauncherWithInWindowAnimations") + unlockToLauncherWithInWindowAnimations() + } // If we're waking and unlocking to a non-Launcher app surface (or Launcher in-window // animations are not available), show it immediately and end the remote animation. The // circular light reveal will show the app surface, and it looks weird if it's moving // around behind that. biometricUnlockControllerLazy.get().isWakeAndUnlock -> { + Log.d(TAG, "playCannedUnlockAnimation, isWakeAndUnlock") setSurfaceBehindAppearAmount(1f) keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished( false /* cancelled */) @@ -522,7 +549,10 @@ class KeyguardUnlockAnimationController @Inject constructor( // Otherwise, we're doing a normal full-window unlock. Start this animator, which will // scale/translate the window underneath the lockscreen. - else -> surfaceBehindEntryAnimator.start() + else -> { + Log.d(TAG, "playCannedUnlockAnimation, surfaceBehindEntryAnimator#start") + surfaceBehindEntryAnimator.start() + } } } @@ -687,10 +717,18 @@ class KeyguardUnlockAnimationController @Inject constructor( // Otherwise, animate in the surface's scale/transltion. val surfaceHeight: Int = surfaceBehindRemoteAnimationTarget!!.screenSpaceBounds.height() - val scaleFactor = (SURFACE_BEHIND_START_SCALE_FACTOR + + + var scaleFactor = (SURFACE_BEHIND_START_SCALE_FACTOR + (1f - SURFACE_BEHIND_START_SCALE_FACTOR) * MathUtils.clamp(amount, 0f, 1f)) + // If we're dismissing via swipe to the Launcher, we'll play in-window scale animations, so + // don't also scale the window. + if (keyguardStateController.isDismissingFromSwipe + && willUnlockWithInWindowLauncherAnimations) { + scaleFactor = 1f + } + // Scale up from a point at the center-bottom of the surface. surfaceBehindMatrix.setScale( scaleFactor, @@ -774,16 +812,17 @@ class KeyguardUnlockAnimationController @Inject constructor( } private fun fadeInSurfaceBehind() { + Log.d(TAG, "fadeInSurfaceBehind") surfaceBehindAlphaAnimator.cancel() surfaceBehindAlphaAnimator.start() } private fun fadeOutSurfaceBehind() { + Log.d(TAG, "fadeOutSurfaceBehind") surfaceBehindAlphaAnimator.cancel() surfaceBehindAlphaAnimator.reverse() } - private fun shouldPerformSmartspaceTransition(): Boolean { // Feature is disabled, so we don't want to. if (!featureFlags.isEnabled(Flags.SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED)) { @@ -837,6 +876,12 @@ class KeyguardUnlockAnimationController @Inject constructor( return false } + // If we're swiping to dismiss, the smartspace will be swiped off the top of the screen + // so we can't shared element animate it. + if (keyguardStateController.isDismissingFromSwipe) { + return false + } + // We don't do the shared element on tablets because they're large and the smartspace has to // fly across large distances, which is distracting. if (Utilities.isTablet(context)) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 0783eeec176f..f9b8ce28533b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -635,13 +635,13 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, case TelephonyManager.SIM_STATE_PUK_REQUIRED: synchronized (KeyguardViewMediator.this) { mSimWasLocked.append(slotId, true); + mPendingPinLock = true; if (!mShowing) { if (DEBUG_SIM_STATES) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't " + "showing; need to show keyguard so user can enter sim pin"); doKeyguardLocked(null); } else { - mPendingPinLock = true; resetStateLocked(); } } @@ -2424,7 +2424,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) { Trace.beginSection("KeyguardViewMediator#handleStartKeyguardExitAnimation"); - if (DEBUG) Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime + Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime + " fadeoutDuration=" + fadeoutDuration); synchronized (KeyguardViewMediator.this) { @@ -2620,7 +2620,11 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, * @param cancelled {@code true} if the animation was cancelled before it finishes. */ public void onKeyguardExitRemoteAnimationFinished(boolean cancelled) { + Log.d(TAG, "onKeyguardExitRemoteAnimationFinished"); if (!mSurfaceBehindRemoteAnimationRunning && !mSurfaceBehindRemoteAnimationRequested) { + Log.d(TAG, "skip onKeyguardExitRemoteAnimationFinished cancelled=" + cancelled + + " surfaceAnimationRunning=" + mSurfaceBehindRemoteAnimationRunning + + " surfaceAnimationRequested=" + mSurfaceBehindRemoteAnimationRequested); return; } @@ -2634,7 +2638,13 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, onKeyguardExitFinished(); if (mKeyguardStateController.isDismissingFromSwipe() || wasShowing) { + Log.d(TAG, "onKeyguardExitRemoteAnimationFinished" + + "#hideKeyguardViewAfterRemoteAnimation"); mKeyguardUnlockAnimationControllerLazy.get().hideKeyguardViewAfterRemoteAnimation(); + } else { + Log.d(TAG, "skip hideKeyguardViewAfterRemoteAnimation" + + " dismissFromSwipe=" + mKeyguardStateController.isDismissingFromSwipe() + + " wasShowing=" + wasShowing); } finishSurfaceBehindRemoteAnimation(cancelled); @@ -2682,7 +2692,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, /** Hides the surface behind the keyguard by re-showing the keyguard/activity lock screen. */ public void hideSurfaceBehindKeyguard() { mSurfaceBehindRemoteAnimationRequested = false; - + mKeyguardStateController.notifyKeyguardGoingAway(false); if (mShowing) { setShowingLocked(true, true); } @@ -2974,6 +2984,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, pw.print(" mPendingReset: "); pw.println(mPendingReset); pw.print(" mPendingLock: "); pw.println(mPendingLock); pw.print(" wakeAndUnlocking: "); pw.println(mWakeAndUnlocking); + pw.print(" mPendingPinLock: "); pw.println(mPendingPinLock); } /** diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt index 54b0c1345601..7cc52e428218 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt @@ -106,6 +106,7 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( PowerManager.WAKE_REASON_APPLICATION, "com.android.systemui:media_tap_to_transfer_activated" ) + animateChipIn(currentChipView) } // Cancel and re-set the chip timeout each time we get a new state. @@ -138,6 +139,12 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( abstract fun updateChipView(chipInfo: T, currentChipView: ViewGroup) /** + * A method that can be implemented by subclcasses to do custom animations for when the chip + * appears. + */ + open fun animateChipIn(chipView: ViewGroup) {} + + /** * Returns the size that the icon should be, or null if no size override is needed. */ open fun getIconSize(isAppIcon: Boolean): Int? = null diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt index 9f5ec7e1a330..54b4380e2443 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt @@ -27,6 +27,8 @@ import android.view.WindowManager import android.widget.TextView import com.android.internal.statusbar.IUndoMediaTransferCallback import com.android.systemui.R +import com.android.systemui.animation.Interpolators +import com.android.systemui.animation.ViewHierarchyAnimator import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.taptotransfer.common.ChipInfoCommon @@ -124,7 +126,6 @@ class MediaTttChipControllerSender @Inject constructor( currentChipView.requireViewById<View>(R.id.loading).visibility = chipState.isMidTransfer.visibleIfTrue() - // Undo val undoView = currentChipView.requireViewById<View>(R.id.undo) val undoClickListener = chipState.undoClickListener( @@ -138,6 +139,17 @@ class MediaTttChipControllerSender @Inject constructor( chipState.isTransferFailure.visibleIfTrue() } + override fun animateChipIn(chipView: ViewGroup) { + ViewHierarchyAnimator.animateAddition( + chipView.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner), + ViewHierarchyAnimator.Hotspot.TOP, + Interpolators.EMPHASIZED_DECELERATE, + duration = 500L, + includeMargins = true, + includeFadeIn = true, + ) + } + override fun removeChip(removalReason: String) { // Don't remove the chip if we're mid-transfer since the user should still be able to // see the status of the transfer. (But do remove it if it's finally timed out.) diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index fcd9e10089bc..bf83ad6bff74 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -110,6 +110,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D private Context mUserContext; private UserTracker mUserTracker; private SecureSettings mSecureSettings; + // Keep track of whether mTilesList contains the same information as the Settings value. + // This is a performance optimization to reduce the number of blocking calls to Settings from + // main thread. + // This is enforced by only cleaning the flag at the end of a successful run of #onTuningChanged + private boolean mTilesListDirty = true; private final TileServiceRequestController mTileServiceRequestController; private TileLifecycleManager.Factory mTileLifeCycleManagerFactory; @@ -374,6 +379,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D // the ones that are in the setting, update the Setting. saveTilesToSettings(mTileSpecs); } + mTilesListDirty = false; for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).onTilesChanged(); } @@ -437,6 +443,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D } + // When calling this, you may want to modify mTilesListDirty accordingly. @MainThread private void saveTilesToSettings(List<String> tileSpecs) { mSecureSettings.putStringForUser(TILES_SETTING, TextUtils.join(",", tileSpecs), @@ -446,9 +453,15 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D @MainThread private void changeTileSpecs(Predicate<List<String>> changeFunction) { - final String setting = mSecureSettings.getStringForUser(TILES_SETTING, mCurrentUser); - final List<String> tileSpecs = loadTileSpecs(mContext, setting); + final List<String> tileSpecs; + if (!mTilesListDirty) { + tileSpecs = new ArrayList<>(mTileSpecs); + } else { + tileSpecs = loadTileSpecs(mContext, + mSecureSettings.getStringForUser(TILES_SETTING, mCurrentUser)); + } if (changeFunction.test(tileSpecs)) { + mTilesListDirty = true; saveTilesToSettings(tileSpecs); } } @@ -508,6 +521,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D } } if (DEBUG) Log.d(TAG, "saveCurrentTiles " + newTiles); + mTilesListDirty = true; saveTilesToSettings(newTiles); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 1fb771ef2991..9e029095ea6b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -50,6 +50,7 @@ import android.hardware.biometrics.BiometricSourceType; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.os.BatteryManager; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -61,6 +62,7 @@ import android.text.format.Formatter; import android.util.Log; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; import androidx.annotation.Nullable; @@ -93,6 +95,8 @@ import com.android.systemui.util.wakelock.WakeLock; import java.io.PrintWriter; import java.text.NumberFormat; +import java.util.HashSet; +import java.util.Set; import javax.inject.Inject; @@ -113,12 +117,12 @@ public class KeyguardIndicationController { private static final String TAG = "KeyguardIndication"; private static final boolean DEBUG_CHARGING_SPEED = false; + private static final boolean DEBUG = Build.IS_DEBUGGABLE; private static final int MSG_HIDE_TRANSIENT = 1; private static final int MSG_SHOW_ACTION_TO_UNLOCK = 2; private static final int MSG_HIDE_BIOMETRIC_MESSAGE = 3; private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300; - private static final float BOUNCE_ANIMATION_FINAL_Y = 0f; private final Context mContext; private final BroadcastDispatcher mBroadcastDispatcher; @@ -139,6 +143,7 @@ public class KeyguardIndicationController { private final IActivityManager mIActivityManager; private final FalsingManager mFalsingManager; private final KeyguardBypassController mKeyguardBypassController; + private final AccessibilityManager mAccessibilityManager; private final Handler mHandler; protected KeyguardIndicationRotateTextViewController mRotateTextViewController; @@ -167,6 +172,7 @@ public class KeyguardIndicationController { private boolean mBatteryPresent = true; private long mChargingTimeRemaining; private String mMessageToShowOnScreenOn; + private final Set<Integer> mCoExFaceHelpMsgIdsToShow; private boolean mInited; private KeyguardUpdateMonitorCallback mUpdateMonitorCallback; @@ -214,7 +220,8 @@ public class KeyguardIndicationController { LockPatternUtils lockPatternUtils, ScreenLifecycle screenLifecycle, IActivityManager iActivityManager, - KeyguardBypassController keyguardBypassController) { + KeyguardBypassController keyguardBypassController, + AccessibilityManager accessibilityManager) { mContext = context; mBroadcastDispatcher = broadcastDispatcher; mDevicePolicyManager = devicePolicyManager; @@ -232,9 +239,17 @@ public class KeyguardIndicationController { mIActivityManager = iActivityManager; mFalsingManager = falsingManager; mKeyguardBypassController = keyguardBypassController; + mAccessibilityManager = accessibilityManager; mScreenLifecycle = screenLifecycle; mScreenLifecycle.addObserver(mScreenObserver); + mCoExFaceHelpMsgIdsToShow = new HashSet<>(); + int[] msgIds = context.getResources().getIntArray( + com.android.systemui.R.array.config_face_help_msgs_when_fingerprint_enrolled); + for (int msgId : msgIds) { + mCoExFaceHelpMsgIdsToShow.add(msgId); + } + mHandler = new Handler(mainLooper) { @Override public void handleMessage(Message msg) { @@ -885,7 +900,9 @@ public class KeyguardIndicationController { mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState); } } else { - if (mKeyguardUpdateMonitor.isUdfpsSupported() + if (!mAccessibilityManager.isEnabled() + && !mAccessibilityManager.isTouchExplorationEnabled() + && mKeyguardUpdateMonitor.isUdfpsSupported() && mKeyguardUpdateMonitor.getUserCanSkipBouncer( KeyguardUpdateMonitor.getCurrentUser())) { final int stringId = mKeyguardUpdateMonitor.getIsFaceAuthenticated() @@ -898,15 +915,6 @@ public class KeyguardIndicationController { } } - private void showFaceFailedTryFingerprintMsg(int msgId, String a11yString) { - showBiometricMessage(R.string.keyguard_face_failed_use_fp); - - // Although we suppress face auth errors visually, we still announce them for a11y - if (!TextUtils.isEmpty(a11yString)) { - mLockScreenIndicationView.announceForAccessibility(a11yString); - } - } - public void dump(PrintWriter pw, String[] args) { pw.println("KeyguardIndicationController:"); pw.println(" mInitialTextColorState: " + mInitialTextColorState); @@ -925,6 +933,7 @@ public class KeyguardIndicationController { mTopIndicationView == null ? null : mTopIndicationView.getText())); pw.println(" computePowerIndication(): " + computePowerIndication()); pw.println(" trustGrantedIndication: " + getTrustGrantedIndication()); + pw.println(" mCoExFaceHelpMsgIdsToShow=" + mCoExFaceHelpMsgIdsToShow); mRotateTextViewController.dump(pw, args); } @@ -983,9 +992,20 @@ public class KeyguardIndicationController { .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)) { return; } + boolean showActionToUnlock = msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; - if (mStatusBarKeyguardViewManager.isBouncerShowing()) { + if (biometricSourceType == BiometricSourceType.FACE + && !showActionToUnlock + && mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + KeyguardUpdateMonitor.getCurrentUser()) + && !mCoExFaceHelpMsgIdsToShow.contains(msgId)) { + if (DEBUG) { + Log.d(TAG, "skip showing msgId=" + msgId + " helpString=" + helpString + + ", due to co-ex logic"); + } + return; + } else if (mStatusBarKeyguardViewManager.isBouncerShowing()) { mStatusBarKeyguardViewManager.showBouncerMessage(helpString, mInitialTextColorState); } else if (mScreenLifecycle.getScreenState() == SCREEN_ON) { @@ -1002,14 +1022,28 @@ public class KeyguardIndicationController { if (shouldSuppressBiometricError(msgId, biometricSourceType, mKeyguardUpdateMonitor)) { return; } - if (msgId == FaceManager.FACE_ERROR_TIMEOUT) { + + if (biometricSourceType == BiometricSourceType.FACE + && msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS) { + // suppress all face UNABLE_TO_PROCESS errors + if (DEBUG) { + Log.d(TAG, "skip showing FACE_ERROR_UNABLE_TO_PROCESS errString=" + + errString); + } + } else if (biometricSourceType == BiometricSourceType.FACE + && msgId == FaceManager.FACE_ERROR_TIMEOUT) { + if (mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + KeyguardUpdateMonitor.getCurrentUser())) { + // no message if fingerprint is also enrolled + if (DEBUG) { + Log.d(TAG, "skip showing FACE_ERROR_TIMEOUT due to co-ex logic"); + } + return; + } + // The face timeout message is not very actionable, let's ask the user to // manually retry. - if (!mStatusBarKeyguardViewManager.isBouncerShowing() - && mKeyguardUpdateMonitor.isUdfpsEnrolled() - && mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) { - showFaceFailedTryFingerprintMsg(msgId, errString); - } else if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) { + if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) { mStatusBarKeyguardViewManager.showBouncerMessage( mContext.getResources().getString(R.string.keyguard_try_fingerprint), mInitialTextColorState diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index 76f9db44af66..1ce05ec7e7ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -736,12 +736,10 @@ public class NotificationMediaManager implements Dumpable { } boolean cannotAnimateDoze = mStatusBarStateController.isDozing() && !ScrimState.AOD.getAnimateChange(); - boolean needsBypassFading = mKeyguardStateController.isBypassFadingAnimation(); if (((mBiometricUnlockController != null && mBiometricUnlockController.getMode() == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING - || cannotAnimateDoze) && !needsBypassFading) + || cannotAnimateDoze)) || hideBecauseOccluded) { - // We are unlocking directly - no animation! mBackdrop.setVisibility(View.GONE); mBackdropBack.setImageDrawable(null); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt index 4f27fb4a9661..d88f07ca304c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt @@ -195,7 +195,6 @@ class PrivacyDotViewController @Inject constructor( @UiThread private fun showDotView(dot: View, animate: Boolean) { - showingListener?.onPrivacyDotShown(dot) dot.clearAnimation() if (animate) { dot.visibility = View.VISIBLE @@ -209,6 +208,7 @@ class PrivacyDotViewController @Inject constructor( dot.visibility = View.VISIBLE dot.alpha = 1f } + showingListener?.onPrivacyDotShown(dot) } // Update the gravity and margins of the privacy views diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java index 577d536262b2..755e3e1a208e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java @@ -151,6 +151,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView R.color.notification_ripple_tinted_color); mNormalRippleColor = mContext.getColor( R.color.notification_ripple_untinted_color); + // Reset background color tint and override tint, as they are from an old theme + mBgTint = NO_COLOR; + mOverrideTint = NO_COLOR; + mOverrideAmount = 0.0f; } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index eb496abad460..26614ff4ae58 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -141,7 +141,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public static final float DEFAULT_HEADER_VISIBLE_AMOUNT = 1.0f; private static final long RECENTLY_ALERTED_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(30); - private boolean mUpdateBackgroundOnUpdate; + // We don't correctly track dark mode until the content views are inflated, so always update + // the background on first content update just in case it happens to be during a theme change. + private boolean mUpdateBackgroundOnUpdate = true; private boolean mNotificationTranslationFinished = false; private boolean mIsSnoozed; private boolean mIsFaded; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java index a552f999aeb4..a76f0827fc18 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java @@ -1312,6 +1312,7 @@ public class NotificationChildrenContainer extends ViewGroup } float bottomRoundness = last ? currentBottomRoundness : 0.0f; child.setBottomRoundness(bottomRoundness, isShown() /* animate */); + child.setTopRoundness(0.0f, false /* animate */); last = false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index e946bf1bb238..39620ac23117 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -27,8 +27,11 @@ import android.hardware.fingerprint.FingerprintManager; import android.metrics.LogMaker; import android.os.Handler; import android.os.PowerManager; +import android.os.Process; import android.os.SystemClock; import android.os.Trace; +import android.os.VibrationAttributes; +import android.os.VibrationEffect; import android.util.Log; import androidx.annotation.Nullable; @@ -61,6 +64,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.policy.KeyguardStateController; import java.io.PrintWriter; @@ -83,6 +87,12 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock"; private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl(); private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 2; + private static final VibrationEffect SUCCESS_VIBRATION_EFFECT = + VibrationEffect.get(VibrationEffect.EFFECT_CLICK); + private static final VibrationEffect ERROR_VIBRATION_EFFECT = + VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK); + private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES = + VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK); @IntDef(prefix = { "MODE_" }, value = { MODE_NONE, @@ -91,7 +101,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp MODE_SHOW_BOUNCER, MODE_ONLY_WAKE, MODE_UNLOCK_COLLAPSING, - MODE_UNLOCK_FADING, MODE_DISMISS_BOUNCER, MODE_WAKE_AND_UNLOCK_FROM_DREAM }) @@ -138,15 +147,9 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 6; /** - * Faster mode of dismissing the lock screen when we cross fade to an app - * (used for keyguard bypass.) - */ - public static final int MODE_UNLOCK_FADING = 7; - - /** * When bouncer is visible and will be dismissed. */ - public static final int MODE_DISMISS_BOUNCER = 8; + public static final int MODE_DISMISS_BOUNCER = 7; /** * How much faster we collapse the lockscreen when authenticating with biometric. @@ -165,6 +168,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private final NotificationShadeWindowController mNotificationShadeWindowController; private final SessionTracker mSessionTracker; private final int mConsecutiveFpFailureThreshold; + private final boolean mShouldVibrate; private int mMode; private BiometricSourceType mBiometricType; private KeyguardViewController mKeyguardViewController; @@ -181,6 +185,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private final AuthController mAuthController; private final StatusBarStateController mStatusBarStateController; private final LatencyTracker mLatencyTracker; + private final VibratorHelper mVibratorHelper; private long mLastFpFailureUptimeMillis; private int mNumConsecutiveFpFailures; @@ -285,7 +290,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp KeyguardUnlockAnimationController keyguardUnlockAnimationController, SessionTracker sessionTracker, LatencyTracker latencyTracker, - ScreenOffAnimationController screenOffAnimationController) { + ScreenOffAnimationController screenOffAnimationController, + VibratorHelper vibrator) { mPowerManager = powerManager; mShadeController = shadeController; mUpdateMonitor = keyguardUpdateMonitor; @@ -304,6 +310,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mHandler = handler; mConsecutiveFpFailureThreshold = resources.getInteger( R.integer.fp_consecutive_failure_time_ms); + mShouldVibrate = !(resources.getBoolean( + com.android.internal.R.bool.system_server_plays_face_haptics)); mKeyguardBypassController = keyguardBypassController; mKeyguardBypassController.setUnlockController(this); mMetricsLogger = metricsLogger; @@ -312,6 +320,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; mSessionTracker = sessionTracker; mScreenOffAnimationController = screenOffAnimationController; + mVibratorHelper = vibrator; + dumpManager.registerDumpable(getClass().getName(), this); } @@ -414,8 +424,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp } public void startWakeAndUnlock(BiometricSourceType biometricSourceType, - boolean isStrongBiometric) { - startWakeAndUnlock(calculateMode(biometricSourceType, isStrongBiometric)); + boolean isStrongBiometric) { + int mode = calculateMode(biometricSourceType, isStrongBiometric); + if (BiometricSourceType.FACE == biometricSourceType && (mode == MODE_WAKE_AND_UNLOCK + || mode == MODE_WAKE_AND_UNLOCK_PULSING || mode == MODE_UNLOCK_COLLAPSING + || mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM || mode == MODE_DISMISS_BOUNCER)) { + vibrateSuccess(); + } + startWakeAndUnlock(mode); } public void startWakeAndUnlock(@WakeAndUnlockMode int mode) { @@ -451,8 +467,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp } switch (mMode) { case MODE_DISMISS_BOUNCER: - case MODE_UNLOCK_FADING: - Trace.beginSection("MODE_DISMISS_BOUNCER or MODE_UNLOCK_FADING"); + Trace.beginSection("MODE_DISMISS_BOUNCER"); mKeyguardViewController.notifyKeyguardAuthenticated( false /* strongAuth */); Trace.endSection(); @@ -590,7 +605,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric); boolean deviceDreaming = mUpdateMonitor.isDreaming(); boolean bypass = mKeyguardBypassController.getBypassEnabled() - || mKeyguardBypassController.getUserHasDeviceEntryIntent(); + || mAuthController.isUdfpsFingerDown(); if (!mUpdateMonitor.isDeviceInteractive()) { if (!mKeyguardViewController.isShowing()) { return bypass ? MODE_WAKE_AND_UNLOCK : MODE_ONLY_WAKE; @@ -619,14 +634,9 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp if (mKeyguardViewController.isShowing()) { if ((mKeyguardViewController.bouncerIsOrWillBeShowing() || mKeyguardBypassController.getAltBouncerShowing()) && unlockingAllowed) { - if (bypass && mKeyguardBypassController.canPlaySubtleWindowAnimations()) { - return MODE_UNLOCK_FADING; - } else { - return MODE_DISMISS_BOUNCER; - } - } else if (unlockingAllowed) { - return bypass || mAuthController.isUdfpsFingerDown() - ? MODE_UNLOCK_FADING : MODE_NONE; + return MODE_DISMISS_BOUNCER; + } else if (unlockingAllowed && (bypass || mAuthController.isUdfpsFingerDown())) { + return MODE_UNLOCK_COLLAPSING; } else { return bypass ? MODE_SHOW_BOUNCER : MODE_NONE; } @@ -665,6 +675,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mNumConsecutiveFpFailures = 0; } } + + // Suppress all face auth errors if fingerprint can be used to authenticate + if (biometricSourceType == BiometricSourceType.FACE + && !mUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + KeyguardUpdateMonitor.getCurrentUser())) { + vibrateError(); + } + cleanup(); } @@ -687,9 +705,30 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp startWakeAndUnlock(MODE_SHOW_BOUNCER); UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId()); } + cleanup(); } + private void vibrateSuccess() { + if (mShouldVibrate) { + mVibratorHelper.vibrate(Process.myUid(), + "com.android.systemui", + SUCCESS_VIBRATION_EFFECT, + getClass().getSimpleName() + "::success", + HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES); + } + } + + private void vibrateError() { + if (mShouldVibrate) { + mVibratorHelper.vibrate(Process.myUid(), + "com.android.systemui", + ERROR_VIBRATION_EFFECT, + getClass().getSimpleName() + "::error", + HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES); + } + } + private void cleanup() { releaseBiometricWakeLock(); } @@ -802,7 +841,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp * on or off. */ public boolean isBiometricUnlock() { - return isWakeAndUnlock() || mMode == MODE_UNLOCK_COLLAPSING || mMode == MODE_UNLOCK_FADING; + return isWakeAndUnlock() || mMode == MODE_UNLOCK_COLLAPSING; } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index 9c6ba3af5154..37079e500aa7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -396,8 +396,7 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn void keyguardGoingAway(); - void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration, - boolean isBypassFading); + void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration); void finishKeyguardFadingAway(); @@ -565,8 +564,6 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn void setLaunchEmergencyActionOnFinishedWaking(boolean launch); - void setTopHidesStatusBar(boolean hides); - QSPanelController getQSPanelController(); boolean areNotificationAlertsDisabled(); 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 0e35cbc1aaf5..450d0d3849d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -207,7 +207,6 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; -import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource; import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.logging.NotificationLogger; @@ -238,7 +237,6 @@ import com.android.systemui.util.WallpaperController; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.MessageRouter; import com.android.systemui.volume.VolumeComponent; -import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.startingsurface.SplashscreenContentDrawer; import com.android.wm.shell.startingsurface.StartingSurface; @@ -405,11 +403,6 @@ public class CentralSurfacesImpl extends CoreStartable implements } @Override - public void setTopHidesStatusBar(boolean hides) { - mTopHidesStatusBar = hides; - } - - @Override public QSPanelController getQSPanelController() { return mQSPanelController; } @@ -451,7 +444,6 @@ public class CentralSurfacesImpl extends CoreStartable implements private BiometricUnlockController mBiometricUnlockController; private final LightBarController mLightBarController; private final Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy; - private final LockscreenGestureLogger mLockscreenGestureLogger; @Nullable protected LockscreenWallpaper mLockscreenWallpaper; private final AutoHideController mAutoHideController; @@ -518,9 +510,6 @@ public class CentralSurfacesImpl extends CoreStartable implements private boolean mExpandedVisible; - private final int[] mAbsPos = new int[2]; - - private final NotifShadeEventSource mNotifShadeEventSource; protected final NotificationEntryManager mEntryManager; private final NotificationGutsManager mGutsManager; private final NotificationLogger mNotificationLogger; @@ -602,7 +591,6 @@ public class CentralSurfacesImpl extends CoreStartable implements } } - private Handler mMainHandler; private final DelayableExecutor mMainExecutor; private int mInteractingWindows; @@ -636,12 +624,9 @@ public class CentralSurfacesImpl extends CoreStartable implements // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. private int mLastLoggedStateFingerprint; - private boolean mTopHidesStatusBar; - private boolean mStatusBarWindowHidden; private boolean mIsLaunchingActivityOverLockscreen; private final UserSwitcherController mUserSwitcherController; - private final NetworkController mNetworkController; private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this); protected final BatteryController mBatteryController; protected boolean mPanelExpanded; @@ -661,7 +646,6 @@ public class CentralSurfacesImpl extends CoreStartable implements protected NotificationPresenter mPresenter; private NotificationActivityStarter mNotificationActivityStarter; private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy; - private final Optional<BubblesManager> mBubblesManagerOptional; private final Optional<Bubbles> mBubblesOptional; private final Bubbles.BubbleExpandListener mBubbleExpandListener; private final Optional<StartingSurface> mStartingSurfaceOptional; @@ -703,7 +687,6 @@ public class CentralSurfacesImpl extends CoreStartable implements FalsingManager falsingManager, FalsingCollector falsingCollector, BroadcastDispatcher broadcastDispatcher, - NotifShadeEventSource notifShadeEventSource, NotificationEntryManager notificationEntryManager, NotificationGutsManager notificationGutsManager, NotificationLogger notificationLogger, @@ -718,13 +701,11 @@ public class CentralSurfacesImpl extends CoreStartable implements NotificationLockscreenUserManager lockScreenUserManager, NotificationRemoteInputManager remoteInputManager, UserSwitcherController userSwitcherController, - NetworkController networkController, BatteryController batteryController, SysuiColorExtractor colorExtractor, ScreenLifecycle screenLifecycle, WakefulnessLifecycle wakefulnessLifecycle, SysuiStatusBarStateController statusBarStateController, - Optional<BubblesManager> bubblesManagerOptional, Optional<Bubbles> bubblesOptional, VisualStabilityManager visualStabilityManager, DeviceProvisionedController deviceProvisionedController, @@ -736,7 +717,6 @@ public class CentralSurfacesImpl extends CoreStartable implements DozeParameters dozeParameters, ScrimController scrimController, Lazy<LockscreenWallpaper> lockscreenWallpaperLazy, - LockscreenGestureLogger lockscreenGestureLogger, Lazy<BiometricUnlockController> biometricUnlockControllerLazy, DozeServiceHost dozeServiceHost, PowerManager powerManager, @@ -769,7 +749,6 @@ public class CentralSurfacesImpl extends CoreStartable implements LockscreenShadeTransitionController lockscreenShadeTransitionController, FeatureFlags featureFlags, KeyguardUnlockAnimationController keyguardUnlockAnimationController, - @Main Handler mainHandler, @Main DelayableExecutor delayableExecutor, @Main MessageRouter messageRouter, WallpaperManager wallpaperManager, @@ -799,7 +778,6 @@ public class CentralSurfacesImpl extends CoreStartable implements mFalsingCollector = falsingCollector; mFalsingManager = falsingManager; mBroadcastDispatcher = broadcastDispatcher; - mNotifShadeEventSource = notifShadeEventSource; mEntryManager = notificationEntryManager; mGutsManager = notificationGutsManager; mNotificationLogger = notificationLogger; @@ -814,13 +792,11 @@ public class CentralSurfacesImpl extends CoreStartable implements mLockscreenUserManager = lockScreenUserManager; mRemoteInputManager = remoteInputManager; mUserSwitcherController = userSwitcherController; - mNetworkController = networkController; mBatteryController = batteryController; mColorExtractor = colorExtractor; mScreenLifecycle = screenLifecycle; mWakefulnessLifecycle = wakefulnessLifecycle; mStatusBarStateController = statusBarStateController; - mBubblesManagerOptional = bubblesManagerOptional; mBubblesOptional = bubblesOptional; mVisualStabilityManager = visualStabilityManager; mDeviceProvisionedController = deviceProvisionedController; @@ -834,7 +810,6 @@ public class CentralSurfacesImpl extends CoreStartable implements mDozeParameters = dozeParameters; mScrimController = scrimController; mLockscreenWallpaperLazy = lockscreenWallpaperLazy; - mLockscreenGestureLogger = lockscreenGestureLogger; mScreenPinningRequest = screenPinningRequest; mDozeScrimController = dozeScrimController; mBiometricUnlockControllerLazy = biometricUnlockControllerLazy; @@ -861,7 +836,6 @@ public class CentralSurfacesImpl extends CoreStartable implements mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager; mFeatureFlags = featureFlags; mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; - mMainHandler = mainHandler; mMainExecutor = delayableExecutor; mMessageRouter = messageRouter; mWallpaperManager = wallpaperManager; @@ -1485,12 +1459,16 @@ public class CentralSurfacesImpl extends CoreStartable implements mPowerManager.wakeUp( time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why); mWakeUpComingFromTouch = true; - where.getLocationInWindow(mTmpInt2); // NOTE, the incoming view can sometimes be the entire container... unsure if // this location is valuable enough - mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2, - mTmpInt2[1] + where.getHeight() / 2); + if (where != null) { + where.getLocationInWindow(mTmpInt2); + mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2, + mTmpInt2[1] + where.getHeight() / 2); + } else { + mWakeUpTouchLocation = new PointF(-1, -1); + } mFalsingCollector.onScreenOnFromTouch(); } } @@ -2274,8 +2252,7 @@ public class CentralSurfacesImpl extends CoreStartable implements public void updateBubblesVisibility() { mBubblesOptional.ifPresent(bubbles -> bubbles.onStatusBarVisibilityChanged( mStatusBarMode != MODE_LIGHTS_OUT - && mStatusBarMode != MODE_LIGHTS_OUT_TRANSPARENT - && !mStatusBarWindowHidden)); + && mStatusBarMode != MODE_LIGHTS_OUT_TRANSPARENT)); } void checkBarMode(@TransitionMode int mode, @WindowVisibleState int windowState, @@ -2517,6 +2494,12 @@ public class CentralSurfacesImpl extends CoreStartable implements animate, intent.getPackage(), (adapter) -> { ActivityOptions options = new ActivityOptions( CentralSurfaces.getActivityOptions(mDisplayId, adapter)); + + // We know that the intent of the caller is to dismiss the keyguard and + // this runnable is called right after the keyguard is solved, so we tell + // WM that we should dismiss it to avoid flickers when opening an activity + // that can also be shown over the keyguard. + options.setDismissKeyguard(); options.setDisallowEnterPictureInPictureWhileLaunching( disallowEnterPictureInPictureWhileLaunching); if (CameraIntents.isInsecureCameraIntent(intent)) { @@ -3194,14 +3177,12 @@ public class CentralSurfacesImpl extends CoreStartable implements /** * Notifies the status bar the Keyguard is fading away with the specified timings. - * @param startTime the start time of the animations in uptime millis + * @param startTime the start time of the animations in uptime millis * @param delay the precalculated animation delay in milliseconds * @param fadeoutDuration the duration of the exit animation, in milliseconds - * @param isBypassFading is this a fading away animation while bypassing */ @Override - public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration, - boolean isBypassFading) { + public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) { mCommandQueue.appTransitionStarting(mDisplayId, startTime + fadeoutDuration - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); @@ -3209,7 +3190,7 @@ public class CentralSurfacesImpl extends CoreStartable implements mCommandQueue.appTransitionStarting(mDisplayId, startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); - mKeyguardStateController.notifyKeyguardFadingAway(delay, fadeoutDuration, isBypassFading); + mKeyguardStateController.notifyKeyguardFadingAway(delay, fadeoutDuration); } /** @@ -3560,6 +3541,9 @@ public class CentralSurfacesImpl extends CoreStartable implements setBouncerShowingForStatusBarComponents(bouncerShowing); mStatusBarHideIconsForBouncerManager.setBouncerShowingAndTriggerUpdate(bouncerShowing); mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */); + if (mBouncerShowing) { + wakeUpIfDozing(SystemClock.uptimeMillis(), null, "BOUNCER_VISIBLE"); + } updateScrimController(); if (!mBouncerShowing) { updatePanelExpansionForKeyguard(); @@ -3926,7 +3910,8 @@ public class CentralSurfacesImpl extends CoreStartable implements mScrimController.transitionTo(ScrimState.AOD); } else if (mKeyguardStateController.isShowing() && !isOccluded() && !unlocking) { mScrimController.transitionTo(ScrimState.KEYGUARD); - } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()) { + } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming() + && !unlocking) { mScrimController.transitionTo(ScrimState.DREAMING); } else { mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 8792118fb9ef..9b88e2650816 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -216,9 +216,12 @@ public class KeyguardBouncer { // Split up the work over multiple frames. DejankUtils.removeCallbacks(mResetRunnable); - if (mKeyguardStateController.isFaceAuthEnabled() && !needsFullscreenBouncer() - && !mKeyguardUpdateMonitor.userNeedsStrongAuth() - && !mKeyguardBypassController.getBypassEnabled()) { + if (mKeyguardStateController.isFaceAuthEnabled() + && !mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + KeyguardUpdateMonitor.getCurrentUser()) + && !needsFullscreenBouncer() + && !mKeyguardUpdateMonitor.userNeedsStrongAuth() + && !mKeyguardBypassController.getBypassEnabled()) { mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY); } else { DejankUtils.postAfterTraversal(mShowRunnable); @@ -394,10 +397,6 @@ public class KeyguardBouncer { return mShowingSoon || mExpansion != EXPANSION_HIDDEN && mExpansion != EXPANSION_VISIBLE; } - public boolean getShowingSoon() { - return mShowingSoon; - } - /** * @return {@code true} when bouncer's pre-hide animation already started but isn't completely * hidden yet, {@code false} otherwise. @@ -641,6 +640,10 @@ public class KeyguardBouncer { public interface BouncerExpansionCallback { /** * Invoked when the bouncer expansion reaches {@link KeyguardBouncer#EXPANSION_VISIBLE}. + * This is NOT called each time the bouncer is shown, but rather only when the fully + * shown amount has changed based on the panel expansion. The bouncer is visibility + * can still change when the expansion amount hasn't changed. + * See {@link KeyguardBouncer#isShowing()} for the checks for the bouncer showing state. */ default void onFullyShown() { } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index 034fc589df97..b987f6815000 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -43,7 +43,6 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr private var hasFaceFeature: Boolean private var pendingUnlock: PendingUnlock? = null private val listeners = mutableListOf<OnBypassStateChangedListener>() - var userHasDeviceEntryIntent: Boolean = false // ie: attempted udfps auth private val faceAuthEnabledChangedCallback = object : KeyguardStateController.Callback { override fun onFaceAuthEnabledChanged() = notifyListeners() @@ -197,20 +196,6 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr return false } - /** - * If shorter animations should be played when unlocking. - */ - fun canPlaySubtleWindowAnimations(): Boolean { - if (bypassEnabled) { - return when { - statusBarStateController.state != StatusBarState.KEYGUARD -> false - qSExpanded -> false - else -> true - } - } - return false - } - fun onStartedGoingToSleep() { pendingUnlock = null } @@ -231,7 +216,6 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr pw.println(" launchingAffordance: $launchingAffordance") pw.println(" qSExpanded: $qSExpanded") pw.println(" hasFaceFeature: $hasFaceFeature") - pw.println(" userHasDeviceEntryIntent: $userHasDeviceEntryIntent") } /** Registers a listener for bypass state changes. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 5d417e0b59e2..3e10166e4c3e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -165,6 +165,7 @@ public abstract class PanelViewController { private float mInitialTouchY; private float mInitialTouchX; private boolean mTouchDisabled; + private boolean mInitialTouchFromKeyguard; /** * Whether or not the PanelView can be expanded or collapsed with a drag. @@ -394,6 +395,7 @@ public abstract class PanelViewController { mInitialOffsetOnTouch = expandedHeight; mInitialTouchY = newY; mInitialTouchX = newX; + mInitialTouchFromKeyguard = mKeyguardStateController.isShowing(); if (startTracking) { mTouchSlopExceeded = true; setExpandedHeight(mInitialOffsetOnTouch); @@ -412,24 +414,16 @@ public abstract class PanelViewController { float vectorVel = (float) Math.hypot( mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity()); - final boolean onKeyguard = - mStatusBarStateController.getState() == StatusBarState.KEYGUARD; - + final boolean onKeyguard = mKeyguardStateController.isShowing(); final boolean expand; - if (event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel) { - // If the keyguard is fading away, don't expand it again. This can happen if you're - // swiping to unlock, the app below the keyguard is in landscape, and the screen - // rotates while your finger is still down after the swipe to unlock. - if (mKeyguardStateController.isKeyguardFadingAway()) { - expand = false; - } else if (onKeyguard) { + if (mKeyguardStateController.isKeyguardFadingAway() + || (mInitialTouchFromKeyguard && !onKeyguard)) { + // Don't expand for any touches that started from the keyguard and ended after the + // keyguard is gone. + expand = false; + } else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel) { + if (onKeyguard) { expand = true; - } else if (mKeyguardStateController.isKeyguardFadingAway()) { - // If we're in the middle of dismissing the keyguard, don't expand due to the - // cancelled gesture. Gesture cancellation during an unlock is expected in some - // situations, such keeping your finger down while swiping to unlock to an app - // that is locked in landscape (the rotation will cancel the touch event). - expand = false; } else { // If we get a cancel, put the shade back to the state it was in when the // gesture started @@ -438,7 +432,6 @@ public abstract class PanelViewController { } else { expand = flingExpands(vel, vectorVel, x, y); } - mDozeLog.traceFling(expand, mTouchAboveFalsingThreshold, mCentralSurfaces.isFalsingThresholdNeeded(), mCentralSurfaces.isWakeUpComingFromTouch()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index 4a5f712d587c..b447f0d36c10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -252,7 +252,7 @@ public enum ScrimState { mBehindTint = Color.BLACK; mBlankScreen = false; - if (previousState == ScrimState.AOD) { + if (mDisplayRequiresBlanking && previousState == ScrimState.AOD) { // Set all scrims black, before they fade transparent. updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */); updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 61e123a8e42a..68d95e882ced 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -19,8 +19,8 @@ package com.android.systemui.statusbar.phone; import static android.view.WindowInsets.Type.navigationBars; import static com.android.systemui.plugins.ActivityStarter.OnDismissAction; +import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_DISMISS_BOUNCER; import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_COLLAPSING; -import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_FADING; import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK; import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; @@ -130,8 +130,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void onFullyShown() { mBouncerAnimating = false; updateStates(); - mCentralSurfaces.wakeUpIfDozing(SystemClock.uptimeMillis(), - mCentralSurfaces.getBouncerContainer(), "BOUNCER_VISIBLE"); } @Override @@ -384,6 +382,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); } else if (mShowing && !hideBouncerOverDream) { if (!isWakeAndUnlocking() + && !(mBiometricUnlockController.getMode() == MODE_DISMISS_BOUNCER) && !mCentralSurfaces.isInLaunchTransition() && !isUnlockCollapsing()) { mBouncer.setExpansion(fraction); @@ -395,9 +394,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } } else if (!mShowing && mBouncer.inTransit()) { // Keyguard is not visible anymore, but expansion animation was still running. - // We need to keep propagating the expansion state to the bouncer, otherwise it will be - // stuck in transit. - mBouncer.setExpansion(fraction); + // We need to hide the bouncer, otherwise it will be stuck in transit. + mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); } else if (mPulsing && fraction == KeyguardBouncer.EXPANSION_VISIBLE) { // Panel expanded while pulsing but didn't translate the bouncer (because we are // unlocked.) Let's simply wake-up to dismiss the lock screen. @@ -736,8 +734,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } mNotificationShadeWindowController.setKeyguardOccluded(mOccluded); - // setDozing(false) will call reset once we stop dozing. - if (!mDozing) { + // setDozing(false) will call reset once we stop dozing. Also, if we're going away, there's + // no need to reset the keyguard views as we'll be gone shortly. Resetting now could cause + // unexpected visible behavior if the keyguard is still visible as we're animating unlocked. + if (!mDozing && !mKeyguardStateController.isKeyguardGoingAway()) { // If Keyguard is reshown, don't hide the bouncer as it might just have been requested // by a FLAG_DISMISS_KEYGUARD_ACTIVITY. reset(isOccluding /* hideBouncerWhenShowing*/); @@ -832,46 +832,17 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb executeAfterKeyguardGoneAction(); boolean wakeUnlockPulsing = mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING; - boolean needsFading = needsBypassFading(); - if (needsFading) { - delay = 0; - fadeoutDuration = KeyguardBypassController.BYPASS_FADE_DURATION; - } else if (wakeUnlockPulsing) { - delay = 0; - fadeoutDuration = 240; - } - mCentralSurfaces.setKeyguardFadingAway(startTime, delay, fadeoutDuration, needsFading); + mCentralSurfaces.setKeyguardFadingAway(startTime, delay, fadeoutDuration); mBiometricUnlockController.startKeyguardFadingAway(); hideBouncer(true /* destroyView */); if (wakeUnlockPulsing) { - if (needsFading) { - ViewGroupFadeHelper.fadeOutAllChildrenExcept( - mNotificationPanelViewController.getView(), - mNotificationContainer, - fadeoutDuration, - () -> { - mCentralSurfaces.hideKeyguard(); - onKeyguardFadedAway(); - }); - } else { - mCentralSurfaces.fadeKeyguardWhilePulsing(); - } + mCentralSurfaces.fadeKeyguardWhilePulsing(); wakeAndUnlockDejank(); } else { boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); if (!staying) { mNotificationShadeWindowController.setKeyguardFadingAway(true); - if (needsFading) { - ViewGroupFadeHelper.fadeOutAllChildrenExcept( - mNotificationPanelViewController.getView(), - mNotificationContainer, - fadeoutDuration, - () -> { - mCentralSurfaces.hideKeyguard(); - }); - } else { - mCentralSurfaces.hideKeyguard(); - } + mCentralSurfaces.hideKeyguard(); // hide() will happen asynchronously and might arrive after the scrims // were already hidden, this means that the transition callback won't // be triggered anymore and StatusBarWindowController will be forever in @@ -884,6 +855,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mBiometricUnlockController.finishKeyguardFadingAway(); } } + updateStates(); mNotificationShadeWindowController.setKeyguardShowing(false); mViewMediatorCallback.keyguardGone(); @@ -893,13 +865,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb Trace.endSection(); } - private boolean needsBypassFading() { - return (mBiometricUnlockController.getMode() == MODE_UNLOCK_FADING - || mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING - || mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK) - && mBypassController.getBypassEnabled(); - } - @Override public void onNavigationModeChanged(int mode) { boolean gesturalNav = QuickStepContract.isGesturalMode(mode); @@ -999,7 +964,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public boolean bouncerIsOrWillBeShowing() { - return isBouncerShowing() || mBouncer.getShowingSoon(); + return isBouncerShowing() || mBouncer.inTransit(); } public boolean isFullscreenBouncer() { @@ -1186,7 +1151,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public boolean shouldSubtleWindowAnimationsForUnlock() { - return needsBypassFading(); + return false; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index 597c949168d4..cf1edf9094df 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -483,6 +483,10 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue int state = mAnimationScheduler.getAnimationState(); if (state == IDLE || state == SHOWING_PERSISTENT_DOT) { animateShow(mSystemIconArea, animate); + } else { + // We are in the middle of a system status event animation, which will animate the + // alpha (but not the visibility). Allow the view to become visible again + mSystemIconArea.setVisibility(View.VISIBLE); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java index dce24122aa7e..250d9d46de66 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java @@ -109,28 +109,15 @@ public interface KeyguardStateController extends CallbackController<Callback> { * we're bypassing */ default long getShortenedFadingAwayDuration() { - if (isBypassFadingAnimation()) { - return getKeyguardFadingAwayDuration(); - } else { - return getKeyguardFadingAwayDuration() / 2; - } - } - - /** - * @return {@code true} if the current fading away animation is the fast bypass fading. - */ - default boolean isBypassFadingAnimation() { - return false; + return getKeyguardFadingAwayDuration() / 2; } /** * Notifies that the Keyguard is fading away with the specified timings. * @param delay the precalculated animation delay in milliseconds * @param fadeoutDuration the duration of the exit animation, in milliseconds - * @param isBypassFading is this a fading away animation while bypassing */ - default void notifyKeyguardFadingAway(long delay, long fadeoutDuration, - boolean isBypassFading) { + default void notifyKeyguardFadingAway(long delay, long fadeoutDuratio) { } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java index 2a225b909f90..2fb16ee9b3b9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java @@ -72,7 +72,6 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum private long mKeyguardFadingAwayDuration; private boolean mKeyguardGoingAway; private boolean mLaunchTransitionFadingAway; - private boolean mBypassFadingAnimation; private boolean mTrustManaged; private boolean mTrusted; private boolean mDebugUnlocked = false; @@ -203,10 +202,9 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum } @Override - public void notifyKeyguardFadingAway(long delay, long fadeoutDuration, boolean isBypassFading) { + public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) { mKeyguardFadingAwayDelay = delay; mKeyguardFadingAwayDuration = fadeoutDuration; - mBypassFadingAnimation = isBypassFading; setKeyguardFadingAway(true); } @@ -284,11 +282,6 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum } @Override - public boolean isBypassFadingAnimation() { - return mBypassFadingAnimation; - } - - @Override public long getKeyguardFadingAwayDelay() { return mKeyguardFadingAwayDelay; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index 92e49473927f..90609fa2772f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -50,6 +50,7 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.Insets; +import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -75,14 +76,19 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.biometrics.AuthController; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.decor.CornerDecorProvider; import com.android.systemui.decor.DecorProvider; import com.android.systemui.decor.DecorProviderFactory; +import com.android.systemui.decor.FaceScanningOverlayProviderImpl; +import com.android.systemui.decor.FaceScanningProviderFactory; import com.android.systemui.decor.OverlayWindow; import com.android.systemui.decor.PrivacyDotCornerDecorProviderImpl; import com.android.systemui.decor.PrivacyDotDecorProviderFactory; import com.android.systemui.decor.RoundedCornerResDelegate; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.events.PrivacyDotViewController; import com.android.systemui.tuner.TunerService; @@ -113,6 +119,13 @@ public class ScreenDecorationsTest extends SysuiTestCase { private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); private FakeThreadFactory mThreadFactory; private ArrayList<DecorProvider> mPrivacyDecorProviders; + private ArrayList<DecorProvider> mFaceScanningProviders; + @Mock + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock + private StatusBarStateController mStatusBarStateController; + @Mock + private AuthController mAuthController; @Mock private Display mDisplay; @Mock @@ -128,6 +141,10 @@ public class ScreenDecorationsTest extends SysuiTestCase { @Mock private PrivacyDotDecorProviderFactory mPrivacyDotDecorProviderFactory; @Mock + private FaceScanningProviderFactory mFaceScanningProviderFactory; + @Mock + private FaceScanningOverlayProviderImpl mFaceScanningDecorProvider; + @Mock private CornerDecorProvider mPrivacyDotTopLeftDecorProvider; @Mock private CornerDecorProvider mPrivacyDotTopRightDecorProvider; @@ -189,9 +206,16 @@ public class ScreenDecorationsTest extends SysuiTestCase { DisplayCutout.BOUNDS_POSITION_RIGHT, R.layout.privacy_dot_bottom_right)); + mFaceScanningDecorProvider = spy(new FaceScanningOverlayProviderImpl( + BOUNDS_POSITION_TOP, + mAuthController, + mStatusBarStateController, + mKeyguardUpdateMonitor, + mExecutor)); + mScreenDecorations = spy(new ScreenDecorations(mContext, mExecutor, mSecureSettings, mBroadcastDispatcher, mTunerService, mUserTracker, mDotViewController, - mThreadFactory, mPrivacyDotDecorProviderFactory) { + mThreadFactory, mPrivacyDotDecorProviderFactory, mFaceScanningProviderFactory) { @Override public void start() { super.start(); @@ -211,9 +235,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { } @Override - protected void setOverlayWindowVisibilityIfViewExist(@Nullable View view, - @View.Visibility int visibility) { - super.setOverlayWindowVisibilityIfViewExist(view, visibility); + protected void updateOverlayWindowVisibilityIfViewExists(@Nullable View view) { + super.updateOverlayWindowVisibilityIfViewExists(view); mExecutor.runAllReady(); } }); @@ -269,6 +292,16 @@ public class ScreenDecorationsTest extends SysuiTestCase { } } + private void verifyFaceScanningViewExists(final boolean exists) { + final View overlay = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView(); + final View view = overlay.findViewById(mFaceScanningDecorProvider.getViewId()); + if (exists) { + assertNotNull(view); + } else { + assertNull(view); + } + } + @Nullable private View findViewFromOverlays(@IdRes int id) { for (OverlayWindow overlay: mScreenDecorations.mOverlays) { @@ -393,10 +426,11 @@ public class ScreenDecorationsTest extends SysuiTestCase { } @Test - public void testNoRounding_NoCutout_NoPrivacyDot() { + public void testNoRounding_NoCutout_NoPrivacyDot_NoFaceScanning() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // no cutout doReturn(null).when(mScreenDecorations).getCutout(); @@ -411,10 +445,11 @@ public class ScreenDecorationsTest extends SysuiTestCase { } @Test - public void testNoRounding_NoCutout_PrivacyDot() { + public void testNoRounding_NoCutout_PrivacyDot_NoFaceScanning() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // no cutout doReturn(null).when(mScreenDecorations).getCutout(); @@ -435,6 +470,9 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Privacy dots shall exist but invisible verifyDotViewsVisibility(View.INVISIBLE); + // Face scanning doesn't exist + verifyFaceScanningViewExists(false); + // One tunable. verify(mTunerService, times(1)).addTunable(any(), any()); // Dot controller init @@ -443,10 +481,11 @@ public class ScreenDecorationsTest extends SysuiTestCase { } @Test - public void testRounding_NoCutout_NoPrivacyDot() { + public void testRounding_NoCutout_NoPrivacyDot_NoFaceScanning() { setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 20 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */); + 20 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // no cutout doReturn(null).when(mScreenDecorations).getCutout(); @@ -464,6 +503,9 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Privacy dots shall not exist verifyDotViewsNullable(true); + // Face scanning doesn't exist + verifyFaceScanningViewExists(false); + // One tunable. verify(mTunerService, times(1)).addTunable(any(), any()); // No dot controller init @@ -471,10 +513,11 @@ public class ScreenDecorationsTest extends SysuiTestCase { } @Test - public void testRounding_NoCutout_PrivacyDot() { + public void testRounding_NoCutout_PrivacyDot_NoFaceScanning() { setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 20 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 20 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // no cutout doReturn(null).when(mScreenDecorations).getCutout(); @@ -494,6 +537,9 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Privacy dots shall exist but invisible verifyDotViewsVisibility(View.INVISIBLE); + // Face scanning doesn't exist + verifyFaceScanningViewExists(false); + // One tunable. verify(mTunerService, times(1)).addTunable(any(), any()); // Dot controller init @@ -509,7 +555,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { /* roundedTopDrawable */, getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px) /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // no cutout doReturn(null).when(mScreenDecorations).getCutout(); @@ -527,7 +574,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { /* roundedTopDrawable */, getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px) /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // no cutout doReturn(null).when(mScreenDecorations).getCutout(); @@ -563,7 +611,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { /* roundedTopDrawable */, getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px) /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // left cutout final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null}; @@ -598,7 +647,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testNoRounding_CutoutShortEdge_NoPrivacyDot() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // top cutout final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -621,7 +671,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testNoRounding_CutoutShortEdge_PrivacyDot() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // top cutout final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -655,7 +706,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testNoRounding_CutoutLongEdge_NoPrivacyDot() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // left cutout final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null}; @@ -682,7 +734,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testNoRounding_CutoutLongEdge_PrivacyDot() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // left cutout final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null}; @@ -709,7 +762,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testRounding_CutoutShortEdge_NoPrivacyDot() { setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // top cutout final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -737,7 +791,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testRounding_CutoutShortEdge_PrivacyDot() { setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */); + 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // top cutout final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -768,7 +823,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testRounding_CutoutLongEdge_NoPrivacyDot() { setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // left cutout final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null}; @@ -786,7 +842,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testRounding_CutoutLongEdge_PrivacyDot() { setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */); + 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // left cutout final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null}; @@ -806,7 +863,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testRounding_CutoutShortAndLongEdge_NoPrivacyDot() { setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // top and left cutout final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null}; @@ -825,7 +883,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testRounding_CutoutShortAndLongEdge_PrivacyDot() { setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */); + 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // top and left cutout final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null}; @@ -846,7 +905,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_NoPrivacyDot() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // Set to short edge cutout(top). final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -869,7 +929,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_PrivacyDot() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // Set to short edge cutout(top). final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -912,7 +973,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testDelayedCutout_NoPrivacyDot() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // top cutout final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -935,7 +997,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testDelayedCutout_PrivacyDot() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); // top cutout final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -980,7 +1043,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { /* roundedTopDrawable */, getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px) /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning*/); mDisplayInfo.rotation = Surface.ROTATION_0; mScreenDecorations.start(); @@ -994,7 +1058,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { /* roundedTopDrawable */, getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px) /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning*/); mDisplayInfo.rotation = Surface.ROTATION_270; mScreenDecorations.onConfigurationChanged(null); @@ -1007,7 +1072,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testOnlyRoundedCornerRadiusTop() { setupResources(0 /* radius */, 10 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); mScreenDecorations.start(); @@ -1028,7 +1094,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testOnlyRoundedCornerRadiusBottom() { setupResources(0 /* radius */, 0 /* radiusTop */, 20 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); mScreenDecorations.start(); @@ -1099,7 +1166,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testSupportHwcLayer_SwitchFrom_NotSupport() { setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // top cutout final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -1127,7 +1195,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testNotSupportHwcLayer_SwitchFrom_Support() { setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); decorationSupport.format = PixelFormat.R_8; doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); @@ -1165,7 +1234,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { /* roundedTopDrawable */, getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px) /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */, + true /* faceScanning */); final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); decorationSupport.format = PixelFormat.R_8; doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); @@ -1182,19 +1252,33 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Make sure view found and window visibility changed as well final View view = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() .findViewById(R.id.privacy_dot_bottom_right_container); + view.setVisibility(View.VISIBLE); mPrivacyDotShowingListener.onPrivacyDotShown(view); assertEquals(View.VISIBLE, mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView().getVisibility()); + view.setVisibility(View.INVISIBLE); mPrivacyDotShowingListener.onPrivacyDotHidden(view); assertEquals(View.INVISIBLE, mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView().getVisibility()); + + // Make sure face scanning view found and window visibility updates on camera protection + // update + final View faceScanView = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView() + .findViewById(mFaceScanningDecorProvider.getViewId()); + when(mFaceScanningProviderFactory.shouldShowFaceScanningAnim()).thenReturn(true); + faceScanView.setVisibility(View.VISIBLE); + mScreenDecorations.showCameraProtection(new Path(), new Rect()); + mExecutor.runAllReady(); + assertEquals(View.VISIBLE, + mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView().getVisibility()); } @Test public void testAutoShowHideOverlayWindowWhenNoRoundedAndNoCutout() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */, + true /* faceScanning */); // no cutout doReturn(null).when(mScreenDecorations).getCutout(); @@ -1206,19 +1290,33 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Make sure view found and window visibility changed as well final View view = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() .findViewById(R.id.privacy_dot_bottom_right_container); + view.setVisibility(View.VISIBLE); mPrivacyDotShowingListener.onPrivacyDotShown(view); assertEquals(View.VISIBLE, mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView().getVisibility()); + view.setVisibility(View.INVISIBLE); mPrivacyDotShowingListener.onPrivacyDotHidden(view); assertEquals(View.INVISIBLE, mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView().getVisibility()); + + // Make sure face scanning view found and window visibility updates on camera protection + // update + final View faceScanView = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView() + .findViewById(mFaceScanningDecorProvider.getViewId()); + faceScanView.setVisibility(View.VISIBLE); + when(mFaceScanningProviderFactory.shouldShowFaceScanningAnim()).thenReturn(true); + mScreenDecorations.showCameraProtection(new Path(), new Rect()); + mExecutor.runAllReady(); + assertEquals(View.VISIBLE, + mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView().getVisibility()); } @Test - public void testHwcLayer_noPrivacyDot() { + public void testHwcLayer_noPrivacyDot_noFaceScanning() { setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); decorationSupport.format = PixelFormat.R_8; doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); @@ -1236,10 +1334,11 @@ public class ScreenDecorationsTest extends SysuiTestCase { } @Test - public void testHwcLayer_PrivacyDot() { + public void testHwcLayer_PrivacyDot_FaceScanning() { setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */, + true /* faceScanning */); final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); decorationSupport.format = PixelFormat.R_8; doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); @@ -1257,13 +1356,16 @@ public class ScreenDecorationsTest extends SysuiTestCase { verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); verify(mDotViewController, times(1)).setShowingListener( mScreenDecorations.mPrivacyDotShowingListener); + + verifyFaceScanningViewExists(true); } @Test public void testOnDisplayChanged_hwcLayer() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); decorationSupport.format = PixelFormat.R_8; doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); @@ -1288,7 +1390,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testOnDisplayChanged_nonHwcLayer() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); // top cutout final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null}; @@ -1311,7 +1414,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testHasSameProvidersWithNullOverlays() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */); + 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */, + false /* faceScanning */); mScreenDecorations.start(); @@ -1329,7 +1433,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { public void testHasSameProvidersWithPrivacyDots() { setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, null /* roundedTopDrawable */, null /* roundedBottomDrawable */, - 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */); + 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */, + false /* faceScanning */); mScreenDecorations.start(); @@ -1366,7 +1471,7 @@ public class ScreenDecorationsTest extends SysuiTestCase { private void setupResources(int radius, int radiusTop, int radiusBottom, @Nullable Drawable roundedTopDrawable, @Nullable Drawable roundedBottomDrawable, - int roundedPadding, boolean fillCutout, boolean privacyDot) { + int roundedPadding, boolean fillCutout, boolean privacyDot, boolean faceScanning) { mContext.getOrCreateTestableResources().addOverride( com.android.internal.R.array.config_displayUniqueIdArray, new String[]{}); @@ -1418,6 +1523,13 @@ public class ScreenDecorationsTest extends SysuiTestCase { } when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mPrivacyDecorProviders); when(mPrivacyDotDecorProviderFactory.getHasProviders()).thenReturn(privacyDot); + + mFaceScanningProviders = new ArrayList<>(); + if (faceScanning) { + mFaceScanningProviders.add(mFaceScanningDecorProvider); + } + when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders); + when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(faceScanning); } private DisplayCutout getDisplayCutoutForRotation(Insets safeInsets, Rect[] cutoutBounds) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt index 6a9bb3e343be..b61fbbe1ea75 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt @@ -520,6 +520,145 @@ ViewHierarchyAnimatorTest : SysuiTestCase() { endAnimation(rootView) } + @Test + fun animatesAppearingViewsFadeIn_alphaStartsAtZero_endsAtOne() { + rootView.alpha = 0f + ViewHierarchyAnimator.animateAddition(rootView, includeFadeIn = true) + rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */) + + advanceFadeInAnimation(rootView, fraction = 1f) + endFadeInAnimation(rootView) + + assertNull(rootView.getTag(R.id.tag_alpha_animator)) + assertEquals(1f, rootView.alpha) + } + + @Test + fun animatesAppearingViewsFadeIn_alphaStartsAboveZero_endsAtOne() { + rootView.alpha = 0.2f + ViewHierarchyAnimator.animateAddition(rootView, includeFadeIn = true) + rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */) + + advanceFadeInAnimation(rootView, fraction = 1f) + endFadeInAnimation(rootView) + + assertNull(rootView.getTag(R.id.tag_alpha_animator)) + assertEquals(1f, rootView.alpha) + } + + @Test + fun animatesAppearingViewsFadeIn_alphaStartsAsZero_alphaUpdatedMidAnimation() { + rootView.alpha = 0f + ViewHierarchyAnimator.animateAddition( + rootView, + includeFadeIn = true, + fadeInInterpolator = Interpolators.LINEAR + ) + rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */) + + advanceFadeInAnimation(rootView, fraction = 0.42f) + + assertEquals(0.42f, rootView.alpha) + } + + @Test + fun animatesAppearingViewsFadeIn_alphaStartsAboveZero_alphaUpdatedMidAnimation() { + rootView.alpha = 0.6f + ViewHierarchyAnimator.animateAddition( + rootView, + includeFadeIn = true, + fadeInInterpolator = Interpolators.LINEAR + ) + rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */) + + advanceFadeInAnimation(rootView, fraction = 0.5f) + + assertEquals(0.8f, rootView.alpha) + } + + @Test + fun animatesAppearingViewsFadeIn_childViewAlphasAlsoAnimated() { + rootView.alpha = 0f + val firstChild = View(context) + firstChild.alpha = 0f + val secondChild = View(context) + secondChild.alpha = 0f + rootView.addView(firstChild) + rootView.addView(secondChild) + + ViewHierarchyAnimator.animateAddition( + rootView, + includeFadeIn = true, + fadeInInterpolator = Interpolators.LINEAR + ) + rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */) + + advanceFadeInAnimation(rootView, fraction = 0.5f) + + assertEquals(0.5f, rootView.alpha) + assertEquals(0.5f, firstChild.alpha) + assertEquals(0.5f, secondChild.alpha) + } + + @Test + fun animatesAppearingViewsFadeIn_animatesFromPreviousAnimationProgress() { + rootView.alpha = 0f + ViewHierarchyAnimator.animateAddition( + rootView, + includeFadeIn = true, + fadeInInterpolator = Interpolators.LINEAR + ) + rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */) + + advanceFadeInAnimation(rootView, fraction = 0.5f) + assertEquals(0.5f, rootView.alpha) + assertNotNull(rootView.getTag(R.id.tag_alpha_animator)) + + // IF we request animation again + ViewHierarchyAnimator.animateAddition( + rootView, + includeFadeIn = true, + fadeInInterpolator = Interpolators.LINEAR + ) + + // THEN the alpha remains at its current value (it doesn't get reset to 0) + assertNotNull(rootView.getTag(R.id.tag_alpha_animator)) + assertEquals(0.5f, rootView.alpha) + + // IF we advance the new animation to the end + advanceFadeInAnimation(rootView, fraction = 1f) + endFadeInAnimation(rootView) + + // THEN we still end at the correct value + assertNull(rootView.getTag(R.id.tag_alpha_animator)) + assertEquals(1f, rootView.alpha) + } + + @Test + fun animatesAppearingViews_fadeInFalse_alphasNotUpdated() { + rootView.alpha = 0.3f + val firstChild = View(context) + firstChild.alpha = 0.4f + val secondChild = View(context) + secondChild.alpha = 0.5f + rootView.addView(firstChild) + rootView.addView(secondChild) + + ViewHierarchyAnimator.animateAddition( + rootView, + includeFadeIn = false, + fadeInInterpolator = Interpolators.LINEAR + ) + rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */) + + advanceFadeInAnimation(rootView, fraction = 1f) + + assertEquals(0.3f, rootView.alpha) + assertEquals(0.4f, firstChild.alpha) + assertEquals(0.5f, secondChild.alpha) + } + + @Test fun animatesViewRemovalFromStartToEnd() { setUpRootWithChildren() @@ -1003,6 +1142,16 @@ ViewHierarchyAnimatorTest : SysuiTestCase() { } } + private fun advanceFadeInAnimation(rootView: View, fraction: Float) { + (rootView.getTag(R.id.tag_alpha_animator) as? ObjectAnimator)?.setCurrentFraction(fraction) + + if (rootView is ViewGroup) { + for (i in 0 until rootView.childCount) { + advanceFadeInAnimation(rootView.getChildAt(i), fraction) + } + } + } + private fun endAnimation(rootView: View) { (rootView.getTag(R.id.tag_animator) as? ObjectAnimator)?.end() @@ -1012,4 +1161,14 @@ ViewHierarchyAnimatorTest : SysuiTestCase() { } } } + + private fun endFadeInAnimation(rootView: View) { + (rootView.getTag(R.id.tag_alpha_animator) as? ObjectAnimator)?.end() + + if (rootView is ViewGroup) { + for (i in 0 until rootView.childCount) { + endFadeInAnimation(rootView.getChildAt(i)) + } + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt new file mode 100644 index 000000000000..328ad39cddd5 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 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 + +import android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE +import android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.testing.TestableLooper.RunWithLooper +import android.view.View +import androidx.test.filters.SmallTest +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.junit.MockitoJUnit + +@RunWith(AndroidTestingRunner::class) +@RunWithLooper(setAsMainLooper = true) +@SmallTest +class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() { + + @JvmField @Rule + var mockitoRule = MockitoJUnit.rule() + + @Mock + private lateinit var callback: AuthBiometricView.Callback + @Mock + private lateinit var panelController: AuthPanelController + + private lateinit var biometricView: AuthBiometricFingerprintAndFaceView + + @Before + fun setup() { + biometricView = R.layout.auth_biometric_fingerprint_and_face_view + .asTestAuthBiometricView(mContext, callback, panelController) + waitForIdleSync() + } + + @After + fun tearDown() { + biometricView.destroyDialog() + } + + @Test + fun fingerprintSuccessDoesNotRequireExplicitConfirmation() { + biometricView.onDialogAnimatedIn() + biometricView.onAuthenticationSucceeded(TYPE_FINGERPRINT) + waitForIdleSync() + + assertThat(biometricView.isAuthenticated).isTrue() + verify(callback).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED) + } + + @Test + fun faceSuccessRequiresExplicitConfirmation() { + biometricView.onDialogAnimatedIn() + biometricView.onAuthenticationSucceeded(TYPE_FACE) + waitForIdleSync() + + assertThat(biometricView.isAuthenticated).isFalse() + assertThat(biometricView.isAuthenticating).isFalse() + assertThat(biometricView.mConfirmButton.visibility).isEqualTo(View.GONE) + verify(callback, never()).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED) + + // icon acts as confirm button + biometricView.mIconView.performClick() + waitForIdleSync() + + assertThat(biometricView.isAuthenticated).isTrue() + verify(callback).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED) + } + + @Test + fun ignoresFaceErrors() { + biometricView.onDialogAnimatedIn() + biometricView.onError(TYPE_FACE, "not a face") + waitForIdleSync() + + assertThat(biometricView.isAuthenticating).isTrue() + verify(callback, never()).onAction(AuthBiometricView.Callback.ACTION_ERROR) + + biometricView.onError(TYPE_FINGERPRINT, "that's a nope") + waitForIdleSync() + + verify(callback).onAction(AuthBiometricView.Callback.ACTION_ERROR) + } + + override fun waitForIdleSync() = TestableLooper.get(this).processAllMessages() +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt new file mode 100644 index 000000000000..687cb517b2f4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2022 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 + +import android.hardware.biometrics.BiometricAuthenticator +import android.os.Bundle +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.testing.TestableLooper.RunWithLooper +import android.view.View +import androidx.test.filters.SmallTest +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.junit.MockitoJUnit + +@RunWith(AndroidTestingRunner::class) +@RunWithLooper(setAsMainLooper = true) +@SmallTest +class AuthBiometricFingerprintViewTest : SysuiTestCase() { + + @JvmField @Rule + val mockitoRule = MockitoJUnit.rule() + + @Mock + private lateinit var callback: AuthBiometricView.Callback + @Mock + private lateinit var panelController: AuthPanelController + + private lateinit var biometricView: AuthBiometricView + + private fun createView(allowDeviceCredential: Boolean = false): AuthBiometricFingerprintView { + val view = R.layout.auth_biometric_fingerprint_view.asTestAuthBiometricView( + mContext, callback, panelController, allowDeviceCredential = allowDeviceCredential + ) as AuthBiometricFingerprintView + waitForIdleSync() + return view + } + + @Before + fun setup() { + biometricView = createView() + } + + @After + fun tearDown() { + biometricView.destroyDialog() + } + + @Test + fun testOnAuthenticationSucceeded_noConfirmationRequired_sendsActionAuthenticated() { + biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT) + waitForIdleSync() + + assertThat(biometricView.isAuthenticated).isTrue() + verify(callback).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED) + } + + @Test + fun testOnAuthenticationSucceeded_confirmationRequired_updatesDialogContents() { + biometricView.setRequireConfirmation(true) + biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT) + waitForIdleSync() + + // TODO: this should be tested in the subclasses + if (biometricView.supportsRequireConfirmation()) { + verify(callback, never()).onAction(ArgumentMatchers.anyInt()) + assertThat(biometricView.mNegativeButton.visibility).isEqualTo(View.GONE) + assertThat(biometricView.mCancelButton.visibility).isEqualTo(View.VISIBLE) + assertThat(biometricView.mCancelButton.isEnabled).isTrue() + assertThat(biometricView.mConfirmButton.isEnabled).isTrue() + assertThat(biometricView.mIndicatorView.text) + .isEqualTo(mContext.getText(R.string.biometric_dialog_tap_confirm)) + assertThat(biometricView.mIndicatorView.visibility).isEqualTo(View.VISIBLE) + } else { + assertThat(biometricView.isAuthenticated).isTrue() + verify(callback).onAction(eq(AuthBiometricView.Callback.ACTION_AUTHENTICATED)) + } + } + + @Test + fun testPositiveButton_sendsActionAuthenticated() { + biometricView.mConfirmButton.performClick() + waitForIdleSync() + + verify(callback).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED) + assertThat(biometricView.isAuthenticated).isTrue() + } + + @Test + fun testNegativeButton_beforeAuthentication_sendsActionButtonNegative() { + biometricView.onDialogAnimatedIn() + biometricView.mNegativeButton.performClick() + waitForIdleSync() + + verify(callback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE) + } + + @Test + fun testCancelButton_whenPendingConfirmation_sendsActionUserCanceled() { + biometricView.setRequireConfirmation(true) + biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT) + + assertThat(biometricView.mNegativeButton.visibility).isEqualTo(View.GONE) + biometricView.mCancelButton.performClick() + waitForIdleSync() + + verify(callback).onAction(AuthBiometricView.Callback.ACTION_USER_CANCELED) + } + + @Test + fun testTryAgainButton_sendsActionTryAgain() { + biometricView.mTryAgainButton.performClick() + waitForIdleSync() + + verify(callback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN) + assertThat(biometricView.mTryAgainButton.visibility).isEqualTo(View.GONE) + assertThat(biometricView.isAuthenticating).isTrue() + } + + @Test + fun testOnErrorSendsActionError() { + biometricView.onError(BiometricAuthenticator.TYPE_FACE, "testError") + waitForIdleSync() + + verify(callback).onAction(eq(AuthBiometricView.Callback.ACTION_ERROR)) + } + + @Test + fun testOnErrorShowsMessage() { + // prevent error state from instantly returning to authenticating in the test + biometricView.mAnimationDurationHideDialog = 10_000 + + val message = "another error" + biometricView.onError(BiometricAuthenticator.TYPE_FACE, message) + waitForIdleSync() + + assertThat(biometricView.isAuthenticating).isFalse() + assertThat(biometricView.isAuthenticated).isFalse() + assertThat(biometricView.mIndicatorView.visibility).isEqualTo(View.VISIBLE) + assertThat(biometricView.mIndicatorView.text).isEqualTo(message) + } + + @Test + fun testBackgroundClicked_sendsActionUserCanceled() { + val view = View(mContext) + biometricView.setBackgroundView(view) + view.performClick() + + verify(callback).onAction(eq(AuthBiometricView.Callback.ACTION_USER_CANCELED)) + } + + @Test + fun testBackgroundClicked_afterAuthenticated_neverSendsUserCanceled() { + val view = View(mContext) + biometricView.setBackgroundView(view) + biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT) + view.performClick() + + verify(callback, never()) + .onAction(eq(AuthBiometricView.Callback.ACTION_USER_CANCELED)) + } + + @Test + fun testBackgroundClicked_whenSmallDialog_neverSendsUserCanceled() { + biometricView.mLayoutParams = AuthDialog.LayoutParams(0, 0) + biometricView.updateSize(AuthDialog.SIZE_SMALL) + val view = View(mContext) + biometricView.setBackgroundView(view) + view.performClick() + + verify(callback, never()).onAction(eq(AuthBiometricView.Callback.ACTION_USER_CANCELED)) + } + + @Test + fun testIgnoresUselessHelp() { + biometricView.mAnimationDurationHideDialog = 10_000 + biometricView.onDialogAnimatedIn() + waitForIdleSync() + + assertThat(biometricView.isAuthenticating).isTrue() + + val helpText = biometricView.mIndicatorView.text + biometricView.onHelp(BiometricAuthenticator.TYPE_FINGERPRINT, "") + waitForIdleSync() + + // text should not change + assertThat(biometricView.mIndicatorView.text).isEqualTo(helpText) + verify(callback, never()).onAction(eq(AuthBiometricView.Callback.ACTION_ERROR)) + } + + @Test + fun testRestoresState() { + val requireConfirmation = true + biometricView.mAnimationDurationHideDialog = 10_000 + val failureMessage = "testFailureMessage" + biometricView.setRequireConfirmation(requireConfirmation) + biometricView.onAuthenticationFailed(BiometricAuthenticator.TYPE_FACE, failureMessage) + waitForIdleSync() + + val state = Bundle() + biometricView.onSaveState(state) + assertThat(biometricView.mTryAgainButton.visibility).isEqualTo(View.GONE) + assertThat(state.getInt(AuthDialog.KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY)) + .isEqualTo(View.GONE) + assertThat(state.getInt(AuthDialog.KEY_BIOMETRIC_STATE)) + .isEqualTo(AuthBiometricView.STATE_ERROR) + assertThat(biometricView.mIndicatorView.visibility).isEqualTo(View.VISIBLE) + assertThat(state.getBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_ERROR_SHOWING)).isTrue() + assertThat(biometricView.mIndicatorView.text).isEqualTo(failureMessage) + assertThat(state.getString(AuthDialog.KEY_BIOMETRIC_INDICATOR_STRING)) + .isEqualTo(failureMessage) + + // TODO: Test dialog size. Should move requireConfirmation to buildBiometricPromptBundle + + // Create new dialog and restore the previous state into it + biometricView.destroyDialog() + biometricView = createView() + biometricView.restoreState(state) + biometricView.mAnimationDurationHideDialog = 10_000 + biometricView.setRequireConfirmation(requireConfirmation) + waitForIdleSync() + + assertThat(biometricView.mTryAgainButton.visibility).isEqualTo(View.GONE) + assertThat(biometricView.mIndicatorView.visibility).isEqualTo(View.VISIBLE) + + // TODO: Test restored text. Currently cannot test this, since it gets restored only after + // dialog size is known. + } + + @Test + fun testCredentialButton_whenDeviceCredentialAllowed() { + biometricView.destroyDialog() + biometricView = createView(allowDeviceCredential = true) + + assertThat(biometricView.mUseCredentialButton.visibility).isEqualTo(View.VISIBLE) + assertThat(biometricView.mNegativeButton.visibility).isEqualTo(View.GONE) + + biometricView.mUseCredentialButton.performClick() + waitForIdleSync() + + verify(callback).onAction(AuthBiometricView.Callback.ACTION_USE_DEVICE_CREDENTIAL) + } + + override fun waitForIdleSync() = TestableLooper.get(this).processAllMessages() +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java deleted file mode 100644 index f99b20d47ab8..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2019 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; - -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; -import static android.hardware.biometrics.BiometricManager.Authenticators; - -import static com.android.systemui.biometrics.AuthBiometricView.Callback.ACTION_AUTHENTICATED; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -import android.hardware.biometrics.PromptInfo; -import android.os.Bundle; -import android.test.suitebuilder.annotation.SmallTest; -import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper; -import android.testing.TestableLooper.RunWithLooper; -import android.testing.ViewUtils; -import android.view.LayoutInflater; -import android.view.View; - -import com.android.systemui.R; -import com.android.systemui.SysuiTestCase; - -import org.junit.After; -import org.junit.Ignore; -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; - -@RunWith(AndroidTestingRunner.class) -@RunWithLooper -@SmallTest -public class AuthBiometricViewTest extends SysuiTestCase { - - @Rule - public final MockitoRule mMockitoRule = MockitoJUnit.rule(); - - @Mock - private AuthBiometricView.Callback mCallback; - @Mock - private AuthPanelController mPanelController; - - private AuthBiometricView mBiometricView; - - @After - public void tearDown() { - destroyDialog(); - } - - @Test - public void testOnAuthenticationSucceeded_noConfirmationRequired_sendsActionAuthenticated() { - initDialog(false /* allowDeviceCredential */, mCallback); - - // The onAuthenticated runnable is posted when authentication succeeds. - mBiometricView.onAuthenticationSucceeded(TYPE_FINGERPRINT); - waitForIdleSync(); - assertEquals(AuthBiometricView.STATE_AUTHENTICATED, mBiometricView.mState); - verify(mCallback).onAction(ACTION_AUTHENTICATED); - } - - @Test - public void testOnAuthenticationSucceeded_confirmationRequired_updatesDialogContents() { - initDialog(false /* allowDeviceCredential */, mCallback); - - mBiometricView.setRequireConfirmation(true); - mBiometricView.onAuthenticationSucceeded(TYPE_FINGERPRINT); - waitForIdleSync(); - - // TODO: this should be tested in the subclasses - if (mBiometricView.supportsRequireConfirmation()) { - assertEquals(AuthBiometricView.STATE_PENDING_CONFIRMATION, mBiometricView.mState); - - verify(mCallback, never()).onAction(anyInt()); - - assertEquals(View.GONE, mBiometricView.mNegativeButton.getVisibility()); - assertEquals(View.VISIBLE, mBiometricView.mCancelButton.getVisibility()); - assertTrue(mBiometricView.mCancelButton.isEnabled()); - - assertTrue(mBiometricView.mConfirmButton.isEnabled()); - assertEquals(mContext.getText(R.string.biometric_dialog_tap_confirm), - mBiometricView.mIndicatorView.getText()); - assertEquals(View.VISIBLE, mBiometricView.mIndicatorView.getVisibility()); - } else { - assertEquals(AuthBiometricView.STATE_AUTHENTICATED, mBiometricView.mState); - verify(mCallback).onAction(eq(ACTION_AUTHENTICATED)); - } - - } - - @Test - public void testPositiveButton_sendsActionAuthenticated() { - initDialog(false /* allowDeviceCredential */, mCallback); - - mBiometricView.mConfirmButton.performClick(); - waitForIdleSync(); - - verify(mCallback).onAction(ACTION_AUTHENTICATED); - assertEquals(AuthBiometricView.STATE_AUTHENTICATED, mBiometricView.mState); - } - - @Test - public void testNegativeButton_beforeAuthentication_sendsActionButtonNegative() { - initDialog(false /* allowDeviceCredential */, mCallback); - - mBiometricView.onDialogAnimatedIn(); - mBiometricView.mNegativeButton.performClick(); - waitForIdleSync(); - - verify(mCallback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE); - } - - @Test - public void testCancelButton_whenPendingConfirmation_sendsActionUserCanceled() { - initDialog(false /* allowDeviceCredential */, mCallback); - - mBiometricView.setRequireConfirmation(true); - mBiometricView.onAuthenticationSucceeded(TYPE_FINGERPRINT); - - assertEquals(View.GONE, mBiometricView.mNegativeButton.getVisibility()); - - mBiometricView.mCancelButton.performClick(); - waitForIdleSync(); - - verify(mCallback).onAction(AuthBiometricView.Callback.ACTION_USER_CANCELED); - } - - @Test - public void testTryAgainButton_sendsActionTryAgain() { - initDialog(false /* allowDeviceCredential */, mCallback); - - mBiometricView.mTryAgainButton.performClick(); - waitForIdleSync(); - - verify(mCallback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN); - assertEquals(AuthBiometricView.STATE_AUTHENTICATING, mBiometricView.mState); - } - - @Test - @Ignore("flaky, b/189031816") - public void testError_sendsActionError() { - initDialog(false /* allowDeviceCredential */, mCallback); - final String testError = "testError"; - mBiometricView.onError(TYPE_FACE, testError); - waitForIdleSync(); - - verify(mCallback).onAction(eq(AuthBiometricView.Callback.ACTION_ERROR)); - assertEquals(AuthBiometricView.STATE_IDLE, mBiometricView.mState); - } - - @Test - public void testBackgroundClicked_sendsActionUserCanceled() { - initDialog(false /* allowDeviceCredential */, mCallback); - - View view = new View(mContext); - mBiometricView.setBackgroundView(view); - view.performClick(); - verify(mCallback).onAction(eq(AuthBiometricView.Callback.ACTION_USER_CANCELED)); - } - - @Test - public void testBackgroundClicked_afterAuthenticated_neverSendsUserCanceled() { - initDialog(false /* allowDeviceCredential */, mCallback); - - View view = new View(mContext); - mBiometricView.setBackgroundView(view); - mBiometricView.onAuthenticationSucceeded(TYPE_FINGERPRINT); - view.performClick(); - verify(mCallback, never()).onAction(eq(AuthBiometricView.Callback.ACTION_USER_CANCELED)); - } - - @Test - public void testBackgroundClicked_whenSmallDialog_neverSendsUserCanceled() { - initDialog(false /* allowDeviceCredential */, mCallback); - mBiometricView.mLayoutParams = new AuthDialog.LayoutParams(0, 0); - mBiometricView.updateSize(AuthDialog.SIZE_SMALL); - - View view = new View(mContext); - mBiometricView.setBackgroundView(view); - view.performClick(); - verify(mCallback, never()).onAction(eq(AuthBiometricView.Callback.ACTION_USER_CANCELED)); - } - - @Test - public void testIgnoresUselessHelp() { - initDialog(false /* allowDeviceCredential */, mCallback); - - mBiometricView.onDialogAnimatedIn(); - waitForIdleSync(); - - assertEquals(AuthBiometricView.STATE_AUTHENTICATING, mBiometricView.mState); - - mBiometricView.onHelp(TYPE_FINGERPRINT, ""); - waitForIdleSync(); - - assertEquals("", mBiometricView.mIndicatorView.getText()); - verify(mCallback, never()).onAction(eq(AuthBiometricView.Callback.ACTION_ERROR)); - assertEquals(AuthBiometricView.STATE_AUTHENTICATING, mBiometricView.mState); - } - - @Test - public void testRestoresState() { - final boolean requireConfirmation = true; - - initDialog(false /* allowDeviceCredential */, mCallback, null, 10000); - - final String failureMessage = "testFailureMessage"; - mBiometricView.setRequireConfirmation(requireConfirmation); - mBiometricView.onAuthenticationFailed(TYPE_FACE, failureMessage); - waitForIdleSync(); - - Bundle state = new Bundle(); - mBiometricView.onSaveState(state); - - assertEquals(View.GONE, mBiometricView.mTryAgainButton.getVisibility()); - assertEquals(View.GONE, state.getInt(AuthDialog.KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY)); - - assertEquals(AuthBiometricView.STATE_ERROR, mBiometricView.mState); - assertEquals(AuthBiometricView.STATE_ERROR, state.getInt(AuthDialog.KEY_BIOMETRIC_STATE)); - - assertEquals(View.VISIBLE, mBiometricView.mIndicatorView.getVisibility()); - assertTrue(state.getBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_ERROR_SHOWING)); - - assertEquals(failureMessage, mBiometricView.mIndicatorView.getText()); - assertEquals(failureMessage, state.getString(AuthDialog.KEY_BIOMETRIC_INDICATOR_STRING)); - - // TODO: Test dialog size. Should move requireConfirmation to buildBiometricPromptBundle - - // Create new dialog and restore the previous state into it - destroyDialog(); - initDialog(false /* allowDeviceCredential */, mCallback, state, 10000); - mBiometricView.mAnimationDurationHideDialog = 10000; - mBiometricView.setRequireConfirmation(requireConfirmation); - waitForIdleSync(); - - assertEquals(View.GONE, mBiometricView.mTryAgainButton.getVisibility()); - assertEquals(AuthBiometricView.STATE_ERROR, mBiometricView.mState); - assertEquals(View.VISIBLE, mBiometricView.mIndicatorView.getVisibility()); - - // TODO: Test restored text. Currently cannot test this, since it gets restored only after - // dialog size is known. - } - - @Test - public void testCredentialButton_whenDeviceCredentialAllowed() throws InterruptedException { - initDialog(true /* allowDeviceCredential */, mCallback); - - assertEquals(View.VISIBLE, mBiometricView.mUseCredentialButton.getVisibility()); - assertEquals(View.GONE, mBiometricView.mNegativeButton.getVisibility()); - mBiometricView.mUseCredentialButton.performClick(); - waitForIdleSync(); - - verify(mCallback).onAction(AuthBiometricView.Callback.ACTION_USE_DEVICE_CREDENTIAL); - } - - private PromptInfo buildPromptInfo(boolean allowDeviceCredential) { - PromptInfo promptInfo = new PromptInfo(); - promptInfo.setTitle("Title"); - int authenticators = Authenticators.BIOMETRIC_WEAK; - if (allowDeviceCredential) { - authenticators |= Authenticators.DEVICE_CREDENTIAL; - } else { - promptInfo.setNegativeButtonText("Negative"); - } - promptInfo.setAuthenticators(authenticators); - return promptInfo; - } - - private void initDialog(boolean allowDeviceCredential, AuthBiometricView.Callback callback) { - initDialog(allowDeviceCredential, callback, - null /* savedState */, 0 /* hideDelay */); - } - - private void initDialog(boolean allowDeviceCredential, - AuthBiometricView.Callback callback, Bundle savedState, int hideDelay) { - final LayoutInflater inflater = LayoutInflater.from(mContext); - mBiometricView = (AuthBiometricView) inflater.inflate( - R.layout.auth_biometric_view, null, false); - mBiometricView.mAnimationDurationLong = 0; - mBiometricView.mAnimationDurationShort = 0; - mBiometricView.mAnimationDurationHideDialog = hideDelay; - mBiometricView.setPromptInfo(buildPromptInfo(allowDeviceCredential)); - mBiometricView.setCallback(callback); - mBiometricView.restoreState(savedState); - ViewUtils.attachView(mBiometricView); - mBiometricView.setPanelController(mPanelController); - waitForIdleSync(); - } - - private void destroyDialog() { - if (mBiometricView != null && mBiometricView.isAttachedToWindow()) { - ViewUtils.detachView(mBiometricView); - } - } - - @Override - protected void waitForIdleSync() { - TestableLooper.get(this).processAllMessages(); - super.waitForIdleSync(); - } -} 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 52b5857a2106..bc5a4d3d274e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt @@ -16,13 +16,11 @@ package com.android.systemui.biometrics import android.app.admin.DevicePolicyManager +import android.hardware.biometrics.BiometricAuthenticator import android.hardware.biometrics.BiometricConstants import android.hardware.biometrics.BiometricManager -import android.hardware.biometrics.ComponentInfoInternal import android.hardware.biometrics.PromptInfo -import android.hardware.biometrics.SensorProperties import android.hardware.face.FaceSensorPropertiesInternal -import android.hardware.fingerprint.FingerprintSensorProperties import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.os.Handler import android.os.IBinder @@ -36,11 +34,11 @@ import android.view.WindowInsets import android.view.WindowManager import android.widget.ScrollView import androidx.test.filters.SmallTest +import com.android.internal.jank.InteractionJankMonitor import com.android.internal.widget.LockPatternUtils import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.WakefulnessLifecycle -import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat @@ -57,12 +55,12 @@ import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever @RunWith(AndroidTestingRunner::class) -@RunWithLooper +@RunWithLooper(setAsMainLooper = true) @SmallTest class AuthContainerViewTest : SysuiTestCase() { @JvmField @Rule - var rule = MockitoJUnit.rule() + var mockitoRule = MockitoJUnit.rule() @Mock lateinit var callback: AuthDialogCallback @@ -74,6 +72,8 @@ class AuthContainerViewTest : SysuiTestCase() { lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock lateinit var windowToken: IBinder + @Mock + lateinit var interactionJankMonitor: InteractionJankMonitor private var authContainer: TestAuthContainerView? = null @@ -86,13 +86,13 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testNotifiesAnimatedIn() { - initializeContainer() + initializeFingerprintContainer() verify(callback).onDialogAnimatedIn() } @Test fun testIgnoresAnimatedInWhenDismissed() { - val container = initializeContainer(addToView = false) + val container = initializeFingerprintContainer(addToView = false) container.dismissFromSystemServer() waitForIdleSync() @@ -107,7 +107,7 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testDismissesOnFocusLoss() { - val container = initializeContainer() + val container = initializeFingerprintContainer() waitForIdleSync() verify(callback).onDialogAnimatedIn() @@ -124,7 +124,7 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testActionAuthenticated_sendsDismissedAuthenticated() { - val container = initializeContainer() + val container = initializeFingerprintContainer() container.mBiometricCallback.onAction( AuthBiometricView.Callback.ACTION_AUTHENTICATED ) @@ -139,7 +139,7 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testActionUserCanceled_sendsDismissedUserCanceled() { - val container = initializeContainer() + val container = initializeFingerprintContainer() container.mBiometricCallback.onAction( AuthBiometricView.Callback.ACTION_USER_CANCELED ) @@ -157,7 +157,7 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testActionButtonNegative_sendsDismissedButtonNegative() { - val container = initializeContainer() + val container = initializeFingerprintContainer() container.mBiometricCallback.onAction( AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE ) @@ -172,7 +172,9 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testActionTryAgain_sendsTryAgain() { - val container = initializeContainer(BiometricManager.Authenticators.BIOMETRIC_WEAK) + val container = initializeFingerprintContainer( + authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK + ) container.mBiometricCallback.onAction( AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN ) @@ -183,8 +185,8 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testActionError_sendsDismissedError() { - val container = initializeContainer() - authContainer!!.mBiometricCallback.onAction( + val container = initializeFingerprintContainer() + container.mBiometricCallback.onAction( AuthBiometricView.Callback.ACTION_ERROR ) waitForIdleSync() @@ -198,8 +200,8 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testActionUseDeviceCredential_sendsOnDeviceCredentialPressed() { - val container = initializeContainer( - BiometricManager.Authenticators.BIOMETRIC_WEAK or + val container = initializeFingerprintContainer( + authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL ) container.mBiometricCallback.onAction( @@ -213,8 +215,8 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testAnimateToCredentialUI_invokesStartTransitionToCredentialUI() { - val container = initializeContainer( - BiometricManager.Authenticators.BIOMETRIC_WEAK or + val container = initializeFingerprintContainer( + authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL ) container.animateToCredentialUI() @@ -225,7 +227,7 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testShowBiometricUI() { - val container = initializeContainer() + val container = initializeFingerprintContainer() waitForIdleSync() @@ -235,7 +237,9 @@ class AuthContainerViewTest : SysuiTestCase() { @Test fun testShowCredentialUI() { - val container = initializeContainer(BiometricManager.Authenticators.DEVICE_CREDENTIAL) + val container = initializeFingerprintContainer( + authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL + ) waitForIdleSync() assertThat(container.hasCredentialView()).isTrue() @@ -249,7 +253,9 @@ class AuthContainerViewTest : SysuiTestCase() { DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ) - val container = initializeContainer(BiometricManager.Authenticators.DEVICE_CREDENTIAL) + val container = initializeFingerprintContainer( + authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL + ) waitForIdleSync() assertThat(container.hasCredentialPatternView()).isTrue() @@ -266,7 +272,9 @@ class AuthContainerViewTest : SysuiTestCase() { // In the credential view, clicking on the background (to cancel authentication) is not // valid. Thus, the listener should be null, and it should not be in the accessibility // hierarchy. - val container = initializeContainer(BiometricManager.Authenticators.DEVICE_CREDENTIAL) + val container = initializeFingerprintContainer( + authenticators = BiometricManager.Authenticators.DEVICE_CREDENTIAL + ) waitForIdleSync() assertThat(container.hasCredentialPasswordView()).isTrue() @@ -294,49 +302,52 @@ class AuthContainerViewTest : SysuiTestCase() { assertThat((layoutParams.fitInsetsTypes and WindowInsets.Type.ime()) == 0).isTrue() } - private fun initializeContainer( + @Test + fun coexFaceRestartsOnTouch() { + val container = initializeCoexContainer() + + container.onPointerDown() + waitForIdleSync() + + container.onAuthenticationFailed(BiometricAuthenticator.TYPE_FACE, "failed") + waitForIdleSync() + + verify(callback, never()).onTryAgainPressed() + + container.onPointerDown() + waitForIdleSync() + + verify(callback).onTryAgainPressed() + } + + private fun initializeFingerprintContainer( + authenticators: Int = BiometricManager.Authenticators.BIOMETRIC_WEAK, + addToView: Boolean = true + ) = initializeContainer( + TestAuthContainerView( + authenticators = authenticators, + fingerprintProps = fingerprintSensorPropertiesInternal() + ), + addToView + ) + + private fun initializeCoexContainer( authenticators: Int = BiometricManager.Authenticators.BIOMETRIC_WEAK, addToView: Boolean = true + ) = initializeContainer( + TestAuthContainerView( + authenticators = authenticators, + fingerprintProps = fingerprintSensorPropertiesInternal(), + faceProps = faceSensorPropertiesInternal() + ), + addToView + ) + + private fun initializeContainer( + view: TestAuthContainerView, + addToView: Boolean ): TestAuthContainerView { - val config = AuthContainerView.Config() - config.mContext = mContext - config.mCallback = callback - config.mSensorIds = intArrayOf(0) - config.mSkipAnimation = true - config.mPromptInfo = PromptInfo() - config.mPromptInfo.authenticators = authenticators - val componentInfo = listOf( - ComponentInfoInternal( - "faceSensor" /* componentId */, - "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */, - "00000001" /* serialNumber */, "" /* softwareVersion */ - ), - ComponentInfoInternal( - "matchingAlgorithm" /* componentId */, - "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */, - "vendor/version/revision" /* softwareVersion */ - ) - ) - val fpProps = listOf( - FingerprintSensorPropertiesInternal( - 0, - SensorProperties.STRENGTH_STRONG, - 5 /* maxEnrollmentsPerUser */, - componentInfo, - FingerprintSensorProperties.TYPE_REAR, - false /* resetLockoutRequiresHardwareAuthToken */ - ) - ) - authContainer = TestAuthContainerView( - config, - fpProps, - listOf(), - wakefulnessLifecycle, - userManager, - lockPatternUtils, - Handler(TestableLooper.get(this).looper), - FakeExecutor(FakeSystemClock()) - ) + authContainer = view if (addToView) { authContainer!!.addToView() @@ -346,27 +357,35 @@ class AuthContainerViewTest : SysuiTestCase() { } private inner class TestAuthContainerView( - config: Config, - fpProps: List<FingerprintSensorPropertiesInternal>, - faceProps: List<FaceSensorPropertiesInternal>, - wakefulnessLifecycle: WakefulnessLifecycle, - userManager: UserManager, - lockPatternUtils: LockPatternUtils, - mainHandler: Handler, - bgExecutor: DelayableExecutor + authenticators: Int = BiometricManager.Authenticators.BIOMETRIC_WEAK, + fingerprintProps: List<FingerprintSensorPropertiesInternal> = listOf(), + faceProps: List<FaceSensorPropertiesInternal> = listOf() ) : AuthContainerView( - config, fpProps, faceProps, - wakefulnessLifecycle, userManager, lockPatternUtils, mainHandler, bgExecutor + Config().apply { + mContext = this@AuthContainerViewTest.context + mCallback = callback + mSensorIds = (fingerprintProps.map { it.sensorId } + + faceProps.map { it.sensorId }).toIntArray() + mSkipAnimation = true + mPromptInfo = PromptInfo().apply { + this.authenticators = authenticators + } + }, + fingerprintProps, + faceProps, + wakefulnessLifecycle, + userManager, + lockPatternUtils, + interactionJankMonitor, + Handler(TestableLooper.get(this).looper), + FakeExecutor(FakeSystemClock()) ) { override fun postOnAnimation(runnable: Runnable) { runnable.run() } } - override fun waitForIdleSync() { - TestableLooper.get(this).processAllMessages() - super.waitForIdleSync() - } + override fun waitForIdleSync() = TestableLooper.get(this).processAllMessages() private fun AuthContainerView.addToView() { ViewUtils.attachView(this) diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index eefc412e3ffa..d948a99f8ad8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -77,6 +77,7 @@ import android.view.WindowManager; import androidx.test.filters.SmallTest; import com.android.internal.R; +import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.SysuiTestCase; import com.android.systemui.keyguard.WakefulnessLifecycle; @@ -150,6 +151,8 @@ public class AuthControllerTest extends SysuiTestCase { private LockPatternUtils mLockPatternUtils; @Mock private StatusBarStateController mStatusBarStateController; + @Mock + private InteractionJankMonitor mInteractionJankMonitor; @Captor ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor; @Captor @@ -788,8 +791,8 @@ public class AuthControllerTest extends SysuiTestCase { super(context, execution, commandQueue, activityTaskManager, windowManager, fingerprintManager, faceManager, udfpsControllerFactory, sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle, - mUserManager, mLockPatternUtils, statusBarStateController, mHandler, - mBackgroundExecutor); + mUserManager, mLockPatternUtils, statusBarStateController, + mInteractionJankMonitor, mHandler, mBackgroundExecutor); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt index 7f8656c1ecbc..d6afd6d192ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt @@ -292,7 +292,7 @@ class AuthRippleControllerTest : SysuiTestCase() { @Test @RunWithLooper(setAsMainLooper = true) - fun testAnimatorRunWhenWakeAndUnlock() { + fun testAnimatorRunWhenWakeAndUnlock_fingerprint() { val fpsLocation = PointF(5f, 5f) `when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation) controller.onViewAttached() @@ -309,6 +309,25 @@ class AuthRippleControllerTest : SysuiTestCase() { } @Test + @RunWithLooper(setAsMainLooper = true) + fun testAnimatorRunWhenWakeAndUnlock_faceUdfpsFingerDown() { + val faceLocation = PointF(5f, 5f) + `when`(authController.faceAuthSensorLocation).thenReturn(faceLocation) + controller.onViewAttached() + `when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true) + `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true) + `when`(authController.isUdfpsFingerDown).thenReturn(true) + + controller.showUnlockRipple(BiometricSourceType.FACE) + assertTrue("reveal didn't start on keyguardFadingAway", + controller.startLightRevealScrimOnKeyguardFadingAway) + `when`(keyguardStateController.isKeyguardFadingAway).thenReturn(true) + controller.onKeyguardFadingAwayChanged() + assertFalse("reveal triggers multiple times", + controller.startLightRevealScrimOnKeyguardFadingAway) + } + + @Test fun testUpdateRippleColor() { controller.onViewAttached() val captor = ArgumentCaptor diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt index 92c2a1b9b23a..8820c164cba4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt @@ -16,29 +16,123 @@ package com.android.systemui.biometrics +import android.annotation.IdRes +import android.content.Context +import android.hardware.biometrics.BiometricManager import android.hardware.biometrics.ComponentInfoInternal -import android.hardware.biometrics.SensorLocationInternal +import android.hardware.biometrics.PromptInfo import android.hardware.biometrics.SensorProperties +import android.hardware.face.FaceSensorPropertiesInternal +import android.hardware.face.FaceSensorProperties import android.hardware.fingerprint.FingerprintSensorProperties import android.hardware.fingerprint.FingerprintSensorPropertiesInternal +import android.os.Bundle -/** Creates properties from the sensor location with test values. */ -fun SensorLocationInternal.asFingerprintSensorProperties( - sensorId: Int = 22, - @SensorProperties.Strength sensorStrength: Int = SensorProperties.STRENGTH_WEAK, - @FingerprintSensorProperties.SensorType sensorType: Int = - FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, - maxEnrollmentsPerUser: Int = 1, - halControlsIllumination: Boolean = true, - info: List<ComponentInfoInternal> = listOf(ComponentInfoInternal("a", "b", "c", "d", "e")), - resetLockoutRequiresHardwareAuthToken: Boolean = false -) = FingerprintSensorPropertiesInternal( - sensorId, - sensorStrength, - maxEnrollmentsPerUser, - info, - sensorType, - halControlsIllumination, - resetLockoutRequiresHardwareAuthToken, - listOf(this) -) +import android.testing.ViewUtils +import android.view.LayoutInflater + +/** + * Inflate the given BiometricPrompt layout and initialize it with test parameters. + * + * This attaches the view so be sure to call [destroyDialog] at the end of the test. + */ +@IdRes +internal fun <T : AuthBiometricView> Int.asTestAuthBiometricView( + context: Context, + callback: AuthBiometricView.Callback, + panelController: AuthPanelController, + allowDeviceCredential: Boolean = false, + savedState: Bundle? = null, + hideDelay: Int = 0 +): T { + val view = LayoutInflater.from(context).inflate(this, null, false) as T + view.mAnimationDurationLong = 0 + view.mAnimationDurationShort = 0 + view.mAnimationDurationHideDialog = hideDelay + view.setPromptInfo(buildPromptInfo(allowDeviceCredential)) + view.setCallback(callback) + view.restoreState(savedState) + view.setPanelController(panelController) + + ViewUtils.attachView(view) + + return view +} + +private fun buildPromptInfo(allowDeviceCredential: Boolean): PromptInfo { + val promptInfo = PromptInfo() + promptInfo.title = "Title" + var authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK + if (allowDeviceCredential) { + authenticators = authenticators or BiometricManager.Authenticators.DEVICE_CREDENTIAL + } else { + promptInfo.negativeButtonText = "Negative" + } + promptInfo.authenticators = authenticators + return promptInfo +} + +/** Detach the view, if needed. */ +internal fun AuthBiometricView?.destroyDialog() { + if (this != null && isAttachedToWindow) { + ViewUtils.detachView(this) + } +} + +/** Create [FingerprintSensorPropertiesInternal] for a test. */ +internal fun fingerprintSensorPropertiesInternal( + ids: List<Int> = listOf(0) +): List<FingerprintSensorPropertiesInternal> { + val componentInfo = listOf( + ComponentInfoInternal( + "fingerprintSensor" /* componentId */, + "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */, + "00000001" /* serialNumber */, "" /* softwareVersion */ + ), + ComponentInfoInternal( + "matchingAlgorithm" /* componentId */, + "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */, + "vendor/version/revision" /* softwareVersion */ + ) + ) + return ids.map { id -> + FingerprintSensorPropertiesInternal( + id, + SensorProperties.STRENGTH_STRONG, + 5 /* maxEnrollmentsPerUser */, + componentInfo, + FingerprintSensorProperties.TYPE_REAR, + false /* resetLockoutRequiresHardwareAuthToken */ + ) + } +} + +/** Create [FaceSensorPropertiesInternal] for a test. */ +internal fun faceSensorPropertiesInternal( + ids: List<Int> = listOf(1) +): List<FaceSensorPropertiesInternal> { + val componentInfo = listOf( + ComponentInfoInternal( + "faceSensor" /* componentId */, + "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */, + "00000001" /* serialNumber */, "" /* softwareVersion */ + ), + ComponentInfoInternal( + "matchingAlgorithm" /* componentId */, + "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */, + "vendor/version/revision" /* softwareVersion */ + ) + ) + return ids.map { id -> + FaceSensorPropertiesInternal( + id, + SensorProperties.STRENGTH_STRONG, + 2 /* maxEnrollmentsPerUser */, + componentInfo, + FaceSensorProperties.TYPE_RGB, + true /* supportsFaceDetection */, + true /* supportsSelfIllumination */, + false /* resetLockoutRequiresHardwareAuthToken */ + ) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index 21b8baf85369..d7a0a0ae974d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -592,6 +592,7 @@ public class UdfpsControllerTest extends SysuiTestCase { // Configure UdfpsView to accept the ACTION_DOWN event when(mUdfpsView.isIlluminationRequested()).thenReturn(false); when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); + when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true); // GIVEN that the overlay is showing mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID, @@ -609,6 +610,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); mBiometricsExecutor.runAllReady(); moveEvent.recycle(); + mFgExecutor.runAllReady(); // THEN FingerprintManager is notified about onPointerDown verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(0), eq(0), eq(0f), eq(0f)); @@ -618,6 +620,7 @@ public class UdfpsControllerTest extends SysuiTestCase { // AND illumination begins verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture()); verify(mLatencyTracker, never()).onActionEnd(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); + verify(mKeyguardUpdateMonitor).onUdfpsPointerDown(eq((int) TEST_REQUEST_ID)); // AND onIlluminatedRunnable notifies FingerprintManager about onUiReady mOnIlluminatedRunnableCaptor.getValue().run(); mBiometricsExecutor.runAllReady(); @@ -636,6 +639,7 @@ public class UdfpsControllerTest extends SysuiTestCase { when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true); // WHEN fingerprint is requested because of AOD interrupt mUdfpsController.onAodInterrupt(0, 0, 2f, 3f); + mFgExecutor.runAllReady(); // THEN illumination begins // AND onIlluminatedRunnable that notifies FingerprintManager is set verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture()); @@ -645,6 +649,7 @@ public class UdfpsControllerTest extends SysuiTestCase { eq(0), eq(0), eq(3f) /* minor */, eq(2f) /* major */); verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(), anyInt(), anyFloat(), anyFloat()); + verify(mKeyguardUpdateMonitor).onUdfpsPointerDown(eq((int) TEST_REQUEST_ID)); } @Test @@ -672,6 +677,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mFgExecutor.runAllReady(); when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true); mUdfpsController.onAodInterrupt(0, 0, 0f, 0f); + mFgExecutor.runAllReady(); when(mUdfpsView.isIlluminationRequested()).thenReturn(true); // WHEN it times out mFgExecutor.advanceClockToNext(); @@ -740,12 +746,12 @@ public class UdfpsControllerTest extends SysuiTestCase { anyString(), any(), eq("udfps-onStart-click"), - eq(UdfpsController.VIBRATION_ATTRIBUTES)); + eq(UdfpsController.UDFPS_VIBRATION_ATTRIBUTES)); // THEN make sure vibration attributes has so that it always will play the haptic, // even in battery saver mode assertEquals(VibrationAttributes.USAGE_COMMUNICATION_REQUEST, - UdfpsController.VIBRATION_ATTRIBUTES.getUsage()); + UdfpsController.UDFPS_VIBRATION_ATTRIBUTES.getUsage()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java index cd646c665d03..78fb5b00a21e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java @@ -70,7 +70,7 @@ public class UdfpsDialogMeasureAdapterTest extends SysuiTestCase { assertEquals(970, UdfpsDialogMeasureAdapter.calculateBottomSpacerHeightForPortrait( props, displayHeightPx, textIndicatorHeightPx, buttonBarHeightPx, - dialogBottomMarginPx, navbarHeightPx + dialogBottomMarginPx, navbarHeightPx, 1.0f /* resolutionScale */ )); } @@ -135,6 +135,7 @@ public class UdfpsDialogMeasureAdapterTest extends SysuiTestCase { assertEquals(1205, UdfpsDialogMeasureAdapter.calculateHorizontalSpacerWidthForLandscape( - props, displayWidthPx, dialogMarginPx, navbarHorizontalInsetPx)); + props, displayWidthPx, dialogMarginPx, navbarHorizontalInsetPx, + 1.0f /* resolutionScale */)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java index 0a1e45c2b28f..9ffc5a57cef6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java @@ -461,7 +461,8 @@ public class DozeSensorsTest extends SysuiTestCase { /* reportsTouchCoordinate*/ false, /* requiresTouchscreen */ false, /* ignoresSetting */ false, - requiresTouchScreen); + requiresTouchScreen, + /* immediatelyReRegister */ true); } public TriggerSensor createDozeSensor( @@ -477,7 +478,8 @@ public class DozeSensorsTest extends SysuiTestCase { /* reportsTouchCoordinate*/ false, /* requiresTouchscreen */ false, /* ignoresSetting */ false, - /* requiresTouchScreen */false); + /* requiresTouchScreen */ false, + /* immediatelyReRegister*/ true); } /** @@ -492,7 +494,8 @@ public class DozeSensorsTest extends SysuiTestCase { /* reportsTouchCoordinate*/ false, /* requiresTouchscreen */ false, /* ignoresSetting */ true, - /* requiresProx */false, + /* requiresProx */ false, + /* immediatelyReRegister */ true, posture); } 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 a80aed7a6d18..8a36a68d189a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -186,6 +186,31 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { } @Test + @TestableLooper.RunWithLooper(setAsMainLooper = true) + public void restoreBouncerWhenSimLockedAndKeyguardIsGoingAway_initiallyNotShowing() { + // When showing and provisioned + mViewMediator.onSystemReady(); + when(mUpdateMonitor.isDeviceProvisioned()).thenReturn(true); + mViewMediator.setShowingLocked(false); + + // and a SIM becomes locked and requires a PIN + mViewMediator.mUpdateCallback.onSimStateChanged( + 1 /* subId */, + 0 /* slotId */, + TelephonyManager.SIM_STATE_PIN_REQUIRED); + + // and the keyguard goes away + mViewMediator.setShowingLocked(false); + when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false); + mViewMediator.mUpdateCallback.onKeyguardVisibilityChanged(false); + + TestableLooper.get(this).processAllMessages(); + + // then make sure it comes back + verify(mStatusBarKeyguardViewManager, atLeast(1)).show(null); + } + + @Test public void testBouncerPrompt_deviceLockedByAdmin() { // GIVEN no trust agents enabled and biometrics aren't enrolled when(mUpdateMonitor.isTrustUsuallyManaged(anyInt())).thenReturn(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt index 9a01464fc869..a8c72ddfd5d7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt @@ -25,9 +25,9 @@ import android.os.PowerManager import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View +import android.view.ViewGroup import android.view.WindowManager import android.widget.ImageView -import android.widget.LinearLayout import android.widget.TextView import androidx.test.filters.SmallTest import com.android.internal.logging.testing.UiEventLoggerFake @@ -620,22 +620,22 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { verify(windowManager).removeView(any()) } - private fun LinearLayout.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon) + private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon) - private fun LinearLayout.getChipText(): String = + private fun ViewGroup.getChipText(): String = (this.requireViewById<TextView>(R.id.text)).text as String - private fun LinearLayout.getLoadingIconVisibility(): Int = + private fun ViewGroup.getLoadingIconVisibility(): Int = this.requireViewById<View>(R.id.loading).visibility - private fun LinearLayout.getUndoButton(): View = this.requireViewById(R.id.undo) + private fun ViewGroup.getUndoButton(): View = this.requireViewById(R.id.undo) - private fun LinearLayout.getFailureIcon(): View = this.requireViewById(R.id.failure_icon) + private fun ViewGroup.getFailureIcon(): View = this.requireViewById(R.id.failure_icon) - private fun getChipView(): LinearLayout { + private fun getChipView(): ViewGroup { val viewCaptor = ArgumentCaptor.forClass(View::class.java) verify(windowManager).addView(viewCaptor.capture(), any()) - return viewCaptor.value as LinearLayout + return viewCaptor.value as ViewGroup } /** Helper method providing default parameters to not clutter up the tests. */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index d394d7dcebbe..d67e26f138f2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -45,6 +45,7 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -59,6 +60,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.UserInfo; import android.graphics.Color; +import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricSourceType; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; @@ -69,6 +71,7 @@ import android.os.UserManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -106,6 +109,9 @@ import org.mockito.MockitoAnnotations; import java.text.NumberFormat; import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -119,7 +125,6 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { private static final int TEST_STRING_RES = R.string.keyguard_indication_trust_unlocked; - private String mKeyguardTryFingerprintMsg; private String mDisclosureWithOrganization; private String mDisclosureGeneric; private String mFinancedDisclosureWithOrganization; @@ -159,6 +164,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { @Mock private KeyguardBypassController mKeyguardBypassController; @Mock + private AccessibilityManager mAccessibilityManager; + @Mock private ScreenLifecycle mScreenLifecycle; @Captor private ArgumentCaptor<DockManager.AlignmentStateListener> mAlignmentListener; @@ -198,7 +205,6 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mContext.addMockSystemService(UserManager.class, mUserManager); mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class)); mContext.addMockSystemService(Context.FINGERPRINT_SERVICE, mock(FingerprintManager.class)); - mKeyguardTryFingerprintMsg = mContext.getString(R.string.keyguard_try_fingerprint); mDisclosureWithOrganization = mContext.getString(R.string.do_disclosure_with_name, ORGANIZATION_NAME); mDisclosureGeneric = mContext.getString(R.string.do_disclosure_generic); @@ -249,7 +255,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor, mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats, mUserManager, mExecutor, mExecutor, mFalsingManager, mLockPatternUtils, - mScreenLifecycle, mIActivityManager, mKeyguardBypassController); + mScreenLifecycle, mIActivityManager, mKeyguardBypassController, + mAccessibilityManager); mController.init(); mController.setIndicationArea(mIndicationArea); verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture()); @@ -578,6 +585,106 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { } @Test + public void faceErrorTimeout_whenFingerprintEnrolled_doesNotShowMessage() { + createController(); + when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + 0)).thenReturn(true); + String message = "A message"; + + mController.setVisible(true); + mController.getKeyguardCallback().onBiometricError( + FaceManager.FACE_ERROR_TIMEOUT, message, BiometricSourceType.FACE); + verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); + } + + @Test + public void sendFaceHelpMessages_fingerprintEnrolled() { + createController(); + + // GIVEN fingerprint enrolled + when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + 0)).thenReturn(true); + + // WHEN help messages received that are allowed to show + final String helpString = "helpString"; + final int[] msgIds = new int[]{ + BiometricFaceConstants.FACE_ACQUIRED_MOUTH_COVERING_DETECTED, + BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED + }; + Set<CharSequence> messages = new HashSet<>(); + for (int msgId : msgIds) { + final String message = helpString + msgId; + messages.add(message); + mKeyguardUpdateMonitorCallback.onBiometricHelp( + msgId, message, BiometricSourceType.FACE); + } + + // THEN FACE_ACQUIRED_MOUTH_COVERING_DETECTED and DARK_GLASSES help messages shown + verifyIndicationMessages(INDICATION_TYPE_BIOMETRIC_MESSAGE, + messages); + } + + @Test + public void doNotSendMostFaceHelpMessages_fingerprintEnrolled() { + createController(); + + // GIVEN fingerprint enrolled + when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + 0)).thenReturn(true); + + // WHEN help messages received that aren't supposed to show + final String helpString = "helpString"; + final int[] msgIds = new int[]{ + BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED, + BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT, + BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT, + BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH, + BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW, + BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT, + BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK + }; + for (int msgId : msgIds) { + mKeyguardUpdateMonitorCallback.onBiometricHelp( + msgId, helpString + msgId, BiometricSourceType.FACE); + } + + // THEN no messages shown + verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); + } + + @Test + public void sendAllFaceHelpMessages_fingerprintNotEnrolled() { + createController(); + + // GIVEN fingerprint NOT enrolled + when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + 0)).thenReturn(false); + + // WHEN help messages received + final Set<CharSequence> helpStrings = new HashSet<>(); + final String helpString = "helpString"; + final int[] msgIds = new int[]{ + BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED, + BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED, + BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT, + BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT, + BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH, + BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW, + BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT, + BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK + }; + for (int msgId : msgIds) { + final String numberedHelpString = helpString + msgId; + mKeyguardUpdateMonitorCallback.onBiometricHelp( + msgId, numberedHelpString, BiometricSourceType.FACE); + helpStrings.add(numberedHelpString); + } + + // THEN message shown for each call + verifyIndicationMessages(INDICATION_TYPE_BIOMETRIC_MESSAGE, helpStrings); + } + + @Test public void updateMonitor_listenerUpdatesIndication() { createController(); String restingIndication = "Resting indication"; @@ -846,10 +953,84 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { trustGrantedMsg); } + @Test + public void nonBypassFaceSuccess_touchExplorationEnabled_showsSwipeToOpen() { + // GIVEN non bypass face auth and touch exploration is enabled + when(mKeyguardBypassController.canBypass()).thenReturn(false); + when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true); + when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); + createController(); + String swipeToOpen = mContext.getString(R.string.keyguard_unlock); + mController.setVisible(true); + + // WHEN face authenticated + mController.getKeyguardCallback().onBiometricAuthenticated(0, + BiometricSourceType.FACE, false); + + // THEN show 'swipe up to open' message + verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, swipeToOpen); + } + + @Test + public void nonBypassFaceSuccess_a11yEnabled_showsSwipeToOpen() { + // GIVEN non bypass face auth and a11y is enabled + when(mKeyguardBypassController.canBypass()).thenReturn(false); + when(mAccessibilityManager.isEnabled()).thenReturn(true); + when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); + createController(); + String swipeToOpen = mContext.getString(R.string.keyguard_unlock); + mController.setVisible(true); + + // WHEN face auth is successful + mController.getKeyguardCallback().onBiometricAuthenticated(0, + BiometricSourceType.FACE, false); + + // THEN show 'swipe up to open' message + verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, swipeToOpen); + } + + @Test + public void coEx_nonBypassFaceSuccess_showsPressLockIcon() { + // GIVEN udfps is supported, non-bypass face auth, and no a11y enabled + when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(true); + when(mKeyguardBypassController.canBypass()).thenReturn(false); + when(mKeyguardUpdateMonitor.getIsFaceAuthenticated()).thenReturn(true); + when(mAccessibilityManager.isEnabled()).thenReturn(false); + when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); + when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); + when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(KeyguardUpdateMonitor.getCurrentUser())) + .thenReturn(true); + createController(); + mController.setVisible(true); + + // WHEN face auth succeeds + mController.getKeyguardCallback().onBiometricAuthenticated(0, + BiometricSourceType.FACE, false); + + // THEN press unlock icon to open message shows + String pressLockIcon = mContext.getString(R.string.keyguard_face_successful_unlock_press); + verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, pressLockIcon); + + assertThat(mTextView.getText()).isNotEqualTo(pressLockIcon); + } + private void sendUpdateDisclosureBroadcast() { mBroadcastReceiver.onReceive(mContext, new Intent()); } + private void verifyIndicationMessages(int type, Set<CharSequence> messages) { + verify(mRotateTextViewController, times(messages.size())).updateIndication(eq(type), + mKeyguardIndicationCaptor.capture(), anyBoolean()); + List<KeyguardIndication> kis = mKeyguardIndicationCaptor.getAllValues(); + + for (KeyguardIndication ki : kis) { + final CharSequence msg = ki.getMessage(); + assertTrue(messages.contains(msg)); // check message is shown + messages.remove(msg); + } + assertThat(messages.size()).isEqualTo(0); // check that all messages accounted for (removed) + } + private void verifyIndicationMessage(int type, String message) { verify(mRotateTextViewController).updateIndication(eq(type), mKeyguardIndicationCaptor.capture(), anyBoolean()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt new file mode 100644 index 000000000000..5f5769572008 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 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.annotation.ColorInt +import android.graphics.Color +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper +import android.view.View +import androidx.test.filters.SmallTest +import com.android.settingslib.Utils +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.notification.FakeShadowView +import com.android.systemui.statusbar.notification.NotificationUtils +import com.android.systemui.util.mockito.mock +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@RunWithLooper +class ActivatableNotificationViewTest : SysuiTestCase() { + private val mContentView: View = mock() + private lateinit var mView: ActivatableNotificationView + + @ColorInt + private var mNormalColor = 0 + + @Before + fun setUp() { + mView = object : ActivatableNotificationView(mContext, null) { + + init { + onFinishInflate() + } + + override fun getContentView(): View { + return mContentView + } + + override fun <T : View> findViewTraversal(id: Int): T? = when (id) { + R.id.backgroundNormal -> mock<NotificationBackgroundView>() + R.id.fake_shadow -> mock<FakeShadowView>() + else -> null + } as T? + } + mNormalColor = + Utils.getColorAttrDefaultColor(mContext, com.android.internal.R.attr.colorSurface) + } + + @Test + fun testBackgroundBehaviors() { + // Color starts with the normal color + mView.updateBackgroundColors() + assertThat(mView.currentBackgroundTint).isEqualTo(mNormalColor) + + // Setting a tint changes the background to that color specifically + mView.setTintColor(Color.BLUE) + assertThat(mView.currentBackgroundTint).isEqualTo(Color.BLUE) + + // Setting an override tint blends with the previous tint + mView.setOverrideTintColor(Color.RED, 0.5f) + assertThat(mView.currentBackgroundTint) + .isEqualTo(NotificationUtils.interpolateColors(Color.BLUE, Color.RED, 0.5f)) + + // Updating the background colors resets tints, as those won't match the latest theme + mView.updateBackgroundColors() + assertThat(mView.currentBackgroundTint).isEqualTo(mNormalColor) + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index 6864c65c9af4..e5b6286fcd7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -51,6 +51,7 @@ import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.policy.KeyguardStateController; import org.junit.Before; @@ -115,6 +116,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { private LatencyTracker mLatencyTracker; @Mock private ScreenOffAnimationController mScreenOffAnimationController; + @Mock + private VibratorHelper mVibratorHelper; private BiometricUnlockController mBiometricUnlockController; @Before @@ -128,7 +131,6 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { when(mKeyguardBypassController.onBiometricAuthenticated(any(), anyBoolean())) .thenReturn(true); when(mAuthController.isUdfpsFingerDown()).thenReturn(false); - when(mKeyguardBypassController.canPlaySubtleWindowAnimations()).thenReturn(true); mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager); mBiometricUnlockController = new BiometricUnlockController(mDozeScrimController, mKeyguardViewMediator, mScrimController, mShadeController, @@ -137,7 +139,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mMetricsLogger, mDumpManager, mPowerManager, mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle, mAuthController, mStatusBarStateController, mKeyguardUnlockAnimationController, - mSessionTracker, mLatencyTracker, mScreenOffAnimationController); + mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper); mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener); } @@ -258,11 +260,9 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, BiometricSourceType.FACE, true /* isStrongBiometric */); - verify(mShadeController, never()).animateCollapsePanels(anyInt(), anyBoolean(), - anyBoolean(), anyFloat()); verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false)); assertThat(mBiometricUnlockController.getMode()) - .isEqualTo(BiometricUnlockController.MODE_UNLOCK_FADING); + .isEqualTo(BiometricUnlockController.MODE_UNLOCK_COLLAPSING); } @Test @@ -277,11 +277,9 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, BiometricSourceType.FACE, true /* isStrongBiometric */); - verify(mShadeController, never()).animateCollapsePanels(anyInt(), anyBoolean(), - anyBoolean(), anyFloat()); verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false)); assertThat(mBiometricUnlockController.getMode()) - .isEqualTo(BiometricUnlockController.MODE_UNLOCK_FADING); + .isEqualTo(BiometricUnlockController.MODE_UNLOCK_COLLAPSING); } @Test @@ -378,21 +376,6 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { } @Test - public void onBiometricAuthenticated_whenBypassOnBouncer_respectsCanPlaySubtleAnim() { - when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true); - when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true); - when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true); - // the value of isStrongBiometric doesn't matter here since we only care about the returned - // value of isUnlockingWithBiometricAllowed() - mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, - BiometricSourceType.FACE, true /* isStrongBiometric */); - - verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false)); - assertThat(mBiometricUnlockController.getMode()) - .isEqualTo(BiometricUnlockController.MODE_UNLOCK_FADING); - } - - @Test public void onBiometricAuthenticated_whenFaceAndPulsing_dontDismissKeyguard() { reset(mUpdateMonitor); reset(mStatusBarKeyguardViewManager); 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 2faff0ced70a..ef681a52f797 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 @@ -129,7 +129,6 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; -import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource; import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider; import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; @@ -159,7 +158,6 @@ import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.concurrency.MessageRouterImpl; import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.volume.VolumeComponent; -import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.startingsurface.StartingSurface; @@ -223,7 +221,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase { @Mock private NotificationShadeWindowView mNotificationShadeWindowView; @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock private AssistManager mAssistManager; - @Mock private NotifShadeEventSource mNotifShadeEventSource; @Mock private NotificationEntryManager mNotificationEntryManager; @Mock private NotificationGutsManager mNotificationGutsManager; @Mock private NotificationMediaManager mNotificationMediaManager; @@ -240,15 +237,12 @@ public class CentralSurfacesImplTest extends SysuiTestCase { @Mock private StatusBarWindowStateController mStatusBarWindowStateController; @Mock private NotificationViewHierarchyManager mNotificationViewHierarchyManager; @Mock private UserSwitcherController mUserSwitcherController; - @Mock private NetworkController mNetworkController; - @Mock private BubblesManager mBubblesManager; @Mock private Bubbles mBubbles; @Mock private NotificationShadeWindowController mNotificationShadeWindowController; @Mock private NotificationIconAreaController mNotificationIconAreaController; @Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController; @Mock private DozeParameters mDozeParameters; @Mock private Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy; - @Mock private LockscreenGestureLogger mLockscreenGestureLogger; @Mock private LockscreenWallpaper mLockscreenWallpaper; @Mock private DozeServiceHost mDozeServiceHost; @Mock private ViewMediatorCallback mKeyguardVieMediatorCallback; @@ -403,7 +397,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase { new FalsingManagerFake(), new FalsingCollectorFake(), mBroadcastDispatcher, - mNotifShadeEventSource, mNotificationEntryManager, mNotificationGutsManager, notificationLogger, @@ -418,13 +411,11 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mLockscreenUserManager, mRemoteInputManager, mUserSwitcherController, - mNetworkController, mBatteryController, mColorExtractor, new ScreenLifecycle(mDumpManager), wakefulnessLifecycle, mStatusBarStateController, - Optional.of(mBubblesManager), Optional.of(mBubbles), mVisualStabilityManager, mDeviceProvisionedController, @@ -436,7 +427,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mDozeParameters, mScrimController, mLockscreenWallpaperLazy, - mLockscreenGestureLogger, mBiometricUnlockControllerLazy, mDozeServiceHost, mPowerManager, mScreenPinningRequest, @@ -468,7 +458,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mLockscreenTransitionController, mFeatureFlags, mKeyguardUnlockAnimationController, - new Handler(TestableLooper.get(this).getLooper()), mMainExecutor, new MessageRouterImpl(mMainExecutor), mWallpaperManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java index 9c02216722e2..39021d8732d3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java @@ -399,9 +399,8 @@ public class KeyguardBouncerTest extends SysuiTestCase { mBouncer.hide(false /* destroyView */); verify(mHandler).removeCallbacks(eq(showRunnable.getValue())); } - @Test - public void testShow_delaysIfFaceAuthIsRunning_unlessBypass() { + public void testShow_delaysIfFaceAuthIsRunning_unlessBypassEnabled() { when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true); when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true); mBouncer.show(true /* reset */); @@ -410,6 +409,16 @@ public class KeyguardBouncerTest extends SysuiTestCase { } @Test + public void testShow_delaysIfFaceAuthIsRunning_unlessFingerprintEnrolled() { + when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true); + when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(0)) + .thenReturn(true); + mBouncer.show(true /* reset */); + + verify(mHandler, never()).postDelayed(any(), anyLong()); + } + + @Test public void testRegisterUpdateMonitorCallback() { verify(mKeyguardUpdateMonitor).registerCallback(any()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 09009c6ee260..32df2d790bd1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -833,7 +833,7 @@ public class ScrimControllerTest extends SysuiTestCase { } @Test - public void scrimBlanksWhenUnlockingFromPulse() { + public void scrimBlankCallbackWhenUnlockingFromPulse() { boolean[] blanked = {false}; // Simulate unlock with fingerprint mScrimController.transitionTo(ScrimState.PULSING); @@ -846,7 +846,50 @@ public class ScrimControllerTest extends SysuiTestCase { } }); finishAnimationsImmediately(); - Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]); + Assert.assertTrue("Scrim should send display blanked callback when unlocking " + + "from pulse.", blanked[0]); + } + + @Test + public void blankingNotRequired_leavingAoD() { + // GIVEN display does NOT need blanking + when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(false); + + mScrimController = new ScrimController(mLightBarController, + mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder, + new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor, + mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()), + mScreenOffAnimationController, + mPanelExpansionStateManager, + mKeyguardUnlockAnimationController, + mStatusBarKeyguardViewManager); + mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible); + mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront); + mScrimController.setAnimatorListener(mAnimatorListener); + mScrimController.setHasBackdrop(false); + mScrimController.setWallpaperSupportsAmbientMode(false); + mScrimController.transitionTo(ScrimState.KEYGUARD); + finishAnimationsImmediately(); + + // WHEN Simulate unlock with fingerprint + mScrimController.transitionTo(ScrimState.AOD); + finishAnimationsImmediately(); + + // WHEN transitioning to UNLOCKED, onDisplayCallbackBlanked callback called to continue + // the transition but the scrim was not actually blanked + mScrimController.transitionTo(ScrimState.UNLOCKED, + new ScrimController.Callback() { + @Override + public void onDisplayBlanked() { + // Front scrim should not be black nor opaque + Assert.assertTrue("Scrim should NOT be visible during transition." + + " Alpha: " + mScrimInFront.getViewAlpha(), + mScrimInFront.getViewAlpha() == 0f); + Assert.assertSame("Scrim should not be visible during transition.", + mScrimVisibility, TRANSPARENT); + } + }); + finishAnimationsImmediately(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 4f2abf263a9b..2dcb2f4f1203 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -192,12 +192,12 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { } @Test - public void onPanelExpansionChanged_propagatesToBouncer_evenAfterHidden() { + public void onPanelExpansionChanged_hideBouncer_afterKeyguardHidden() { mStatusBarKeyguardViewManager.hide(0, 0); when(mBouncer.inTransit()).thenReturn(true); mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT); - verify(mBouncer).setExpansion(eq(EXPANSION_EVENT.getFraction())); + verify(mBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_HIDDEN)); } @Test @@ -239,6 +239,23 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { } @Test + public void onPanelExpansionChanged_neverTranslatesBouncerWhenDismissBouncer() { + // Since KeyguardBouncer.EXPANSION_VISIBLE = 0 panel expansion, if the unlock is dismissing + // the bouncer, there may be an onPanelExpansionChanged(0) call to collapse the panel + // which would mistakenly cause the bouncer to show briefly before its visibility + // is set to hide. Therefore, we don't want to propagate panelExpansionChanged to the + // bouncer if the bouncer is dismissing as a result of a biometric unlock. + when(mBiometricUnlockController.getMode()) + .thenReturn(BiometricUnlockController.MODE_DISMISS_BOUNCER); + mStatusBarKeyguardViewManager.onPanelExpansionChanged( + expansionEvent( + /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE, + /* expanded= */ true, + /* tracking= */ false)); + verify(mBouncer, never()).setExpansion(anyFloat()); + } + + @Test public void onPanelExpansionChanged_neverTranslatesBouncerWhenLaunchingApp() { when(mCentralSurfaces.isInLaunchTransition()).thenReturn(true); mStatusBarKeyguardViewManager.onPanelExpansionChanged( @@ -381,6 +398,16 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { } @Test + public void testBouncerIsOrWillBeShowing_whenBouncerIsInTransit() { + when(mBouncer.isShowing()).thenReturn(false); + when(mBouncer.inTransit()).thenReturn(true); + + assertTrue( + "Is or will be showing should be true when bouncer is in transit", + mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()); + } + + @Test public void testShowAltAuth_unlockingWithBiometricNotAllowed() { // GIVEN alt auth exists, unlocking with biometric isn't allowed mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index 6abc687f0ebb..034e06d7e8c4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -16,6 +16,11 @@ package com.android.systemui.statusbar.phone.fragment; import static android.view.Display.DEFAULT_DISPLAY; +import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_IN; +import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_OUT; +import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.IDLE; +import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.RUNNING_CHIP_ANIM; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -25,6 +30,7 @@ import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.animation.Animator; import android.app.Fragment; import android.app.StatusBarManager; import android.content.Context; @@ -127,7 +133,8 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { } @Test - public void testDisableSystemInfo() { + public void testDisableSystemInfo_systemAnimationIdle_doesHide() { + when(mAnimationScheduler.getAnimationState()).thenReturn(IDLE); CollapsedStatusBarFragment fragment = resumeAndGetFragment(); fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_SYSTEM_INFO, 0, false); @@ -140,6 +147,98 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { } @Test + public void testSystemStatusAnimation_startedDisabled_finishedWithAnimator_showsSystemInfo() { + // GIVEN the status bar hides the system info via disable flags, while there is no event + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + when(mAnimationScheduler.getAnimationState()).thenReturn(IDLE); + fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_SYSTEM_INFO, 0, false); + assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility()); + + // WHEN the disable flags are cleared during a system event animation + when(mAnimationScheduler.getAnimationState()).thenReturn(RUNNING_CHIP_ANIM); + fragment.disable(DEFAULT_DISPLAY, 0, 0, false); + + // THEN the view is made visible again, but still low alpha + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(0, getSystemIconAreaView().getAlpha(), 0.01); + + // WHEN the system event animation finishes + when(mAnimationScheduler.getAnimationState()).thenReturn(ANIMATING_OUT); + Animator anim = fragment.onSystemEventAnimationFinish(false); + anim.start(); + processAllMessages(); + anim.end(); + + // THEN the system info is full alpha + assertEquals(1, getSystemIconAreaView().getAlpha(), 0.01); + } + + @Test + public void testSystemStatusAnimation_systemInfoDisabled_staysInvisible() { + // GIVEN the status bar hides the system info via disable flags, while there is no event + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + when(mAnimationScheduler.getAnimationState()).thenReturn(IDLE); + fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_SYSTEM_INFO, 0, false); + assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility()); + + // WHEN the system event animation finishes + when(mAnimationScheduler.getAnimationState()).thenReturn(ANIMATING_OUT); + Animator anim = fragment.onSystemEventAnimationFinish(false); + anim.start(); + processAllMessages(); + anim.end(); + + // THEN the system info is at full alpha, but still INVISIBLE (since the disable flag is + // still set) + assertEquals(1, getSystemIconAreaView().getAlpha(), 0.01); + assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility()); + } + + + @Test + public void testSystemStatusAnimation_notDisabled_animatesAlphaZero() { + // GIVEN the status bar is not disabled + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + when(mAnimationScheduler.getAnimationState()).thenReturn(ANIMATING_IN); + // WHEN the system event animation begins + Animator anim = fragment.onSystemEventAnimationBegin(); + anim.start(); + processAllMessages(); + anim.end(); + + // THEN the system info is visible but alpha 0 + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(0, getSystemIconAreaView().getAlpha(), 0.01); + } + + @Test + public void testSystemStatusAnimation_notDisabled_animatesBackToAlphaOne() { + // GIVEN the status bar is not disabled + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + when(mAnimationScheduler.getAnimationState()).thenReturn(ANIMATING_IN); + // WHEN the system event animation begins + Animator anim = fragment.onSystemEventAnimationBegin(); + anim.start(); + processAllMessages(); + anim.end(); + + // THEN the system info is visible but alpha 0 + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(0, getSystemIconAreaView().getAlpha(), 0.01); + + // WHEN the system event animation finishes + when(mAnimationScheduler.getAnimationState()).thenReturn(ANIMATING_OUT); + anim = fragment.onSystemEventAnimationFinish(false); + anim.start(); + processAllMessages(); + anim.end(); + + // THEN the syste info is full alpha and VISIBLE + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(1, getSystemIconAreaView().getAlpha(), 0.01); + } + + @Test public void testDisableNotifications() { CollapsedStatusBarFragment fragment = resumeAndGetFragment(); diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java index e78c8d1ddcac..76df8b9f84e8 100644 --- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java +++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java @@ -24,10 +24,8 @@ import static com.android.server.backup.UserBackupManagerService.BACKUP_METADATA import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE; import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT; -import android.annotation.NonNull; import android.app.ApplicationThreadConstants; import android.app.IBackupAgent; -import android.app.backup.BackupAgent; import android.app.backup.BackupManager; import android.app.backup.FullBackup; import android.app.backup.IBackupManagerMonitor; @@ -40,12 +38,10 @@ import android.content.pm.Signature; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.provider.Settings; -import android.system.OsConstants; import android.text.TextUtils; import android.util.Slog; import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; import com.android.server.backup.BackupAgentTimeoutParameters; import com.android.server.backup.BackupRestoreTask; @@ -61,7 +57,6 @@ import com.android.server.backup.utils.FullBackupRestoreObserverUtils; import com.android.server.backup.utils.RestoreUtils; import com.android.server.backup.utils.TarBackupReader; -import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -140,8 +135,6 @@ public class FullRestoreEngine extends RestoreEngine { private boolean mPipesClosed; private final BackupEligibilityRules mBackupEligibilityRules; - private FileMetadata mReadOnlyParent = null; - public FullRestoreEngine( UserBackupManagerService backupManagerService, OperationStorage operationStorage, BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer, @@ -165,22 +158,6 @@ public class FullRestoreEngine extends RestoreEngine { mBackupEligibilityRules = backupEligibilityRules; } - @VisibleForTesting - FullRestoreEngine() { - mIsAdbRestore = false; - mAllowApks = false; - mEphemeralOpToken = 0; - mUserId = 0; - mBackupEligibilityRules = null; - mAgentTimeoutParameters = null; - mBuffer = null; - mBackupManagerService = null; - mOperationStorage = null; - mMonitor = null; - mMonitorTask = null; - mOnlyPackage = null; - } - public IBackupAgent getAgent() { return mAgent; } @@ -420,11 +397,6 @@ public class FullRestoreEngine extends RestoreEngine { okay = false; } - if (shouldSkipReadOnlyDir(info)) { - // b/194894879: We don't support restore of read-only dirs. - okay = false; - } - // At this point we have an agent ready to handle the full // restore data as well as a pipe for sending data to // that agent. Tell the agent to start reading from the @@ -601,45 +573,6 @@ public class FullRestoreEngine extends RestoreEngine { return (info != null); } - boolean shouldSkipReadOnlyDir(FileMetadata info) { - if (isValidParent(mReadOnlyParent, info)) { - // This file has a read-only parent directory, we shouldn't - // restore it. - return true; - } else { - // We're now in a different branch of the file tree, update the parent - // value. - if (isReadOnlyDir(info)) { - // Current directory is read-only. Remember it so that we can skip all - // of its contents. - mReadOnlyParent = info; - Slog.w(TAG, "Skipping restore of " + info.path + " and its contents as " - + "read-only dirs are currently not supported."); - return true; - } else { - mReadOnlyParent = null; - } - } - - return false; - } - - private static boolean isValidParent(FileMetadata parentDir, @NonNull FileMetadata childDir) { - return parentDir != null - && childDir.packageName.equals(parentDir.packageName) - && childDir.domain.equals(parentDir.domain) - && childDir.path.startsWith(getPathWithTrailingSeparator(parentDir.path)); - } - - private static String getPathWithTrailingSeparator(String path) { - return path.endsWith(File.separator) ? path : path + File.separator; - } - - private static boolean isReadOnlyDir(FileMetadata file) { - // Check if owner has 'write' bit in the file's mode value (see 'man -7 inode' for details). - return file.type == BackupAgent.TYPE_DIRECTORY && (file.mode & OsConstants.S_IWUSR) == 0; - } - private void setUpPipes() throws IOException { synchronized (mPipesLock) { mPipes = ParcelFileDescriptor.createPipe(); diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index c678a67e5bd3..1fab28efb1ac 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -160,6 +160,8 @@ public class Watchdog implements Dumpable { public static final String[] AIDL_INTERFACE_PREFIXES_OF_INTEREST = new String[] { "android.hardware.biometrics.face.IFace/", "android.hardware.biometrics.fingerprint.IFingerprint/", + "android.hardware.graphics.composer3.IComposer/", + "android.hardware.input.processor.IInputProcessor/", "android.hardware.light.ILights/", "android.hardware.power.IPower/", "android.hardware.power.stats.IPowerStats/", diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 82d0b67d5018..869c6a4d3a5c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -185,7 +185,7 @@ final class ActivityManagerShellCommand extends ShellCommand { private boolean mAsync; private BroadcastOptions mBroadcastOptions; private boolean mShowSplashScreen; - private boolean mDismissKeyguardIfInsecure; + private boolean mDismissKeyguard; final boolean mDumping; @@ -449,8 +449,8 @@ final class ActivityManagerShellCommand extends ShellCommand { mAsync = true; } else if (opt.equals("--splashscreen-show-icon")) { mShowSplashScreen = true; - } else if (opt.equals("--dismiss-keyguard-if-insecure")) { - mDismissKeyguardIfInsecure = true; + } else if (opt.equals("--dismiss-keyguard")) { + mDismissKeyguard = true; } else { return false; } @@ -601,11 +601,11 @@ final class ActivityManagerShellCommand extends ShellCommand { } options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON); } - if (mDismissKeyguardIfInsecure) { + if (mDismissKeyguard) { if (options == null) { options = ActivityOptions.makeBasic(); } - options.setDismissKeyguardIfInsecure(); + options.setDismissKeyguard(); } if (mWaitOption) { result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, null, intent, diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index f7fbbe4ebead..e9658dbc7b1a 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1556,14 +1556,22 @@ public class OomAdjuster { boolean foregroundActivities = false; boolean hasVisibleActivities = false; - if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) { + if (app == topApp && (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP + || PROCESS_STATE_CUR_TOP == PROCESS_STATE_IMPORTANT_FOREGROUND)) { // The last app on the list is the foreground app. adj = ProcessList.FOREGROUND_APP_ADJ; - schedGroup = ProcessList.SCHED_GROUP_TOP_APP; - state.setAdjType("top-activity"); + if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP) { + schedGroup = ProcessList.SCHED_GROUP_TOP_APP; + state.setAdjType("top-activity"); + } else { + // Demote the scheduling group to avoid CPU contention if there is another more + // important process which also uses top-app, such as if SystemUI is animating. + schedGroup = ProcessList.SCHED_GROUP_DEFAULT; + state.setAdjType("intermediate-top-activity"); + } foregroundActivities = true; hasVisibleActivities = true; - procState = PROCESS_STATE_CUR_TOP; + procState = PROCESS_STATE_TOP; if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 30572481e72b..2130c38f4d62 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -346,6 +346,8 @@ public class AudioService extends IAudioService.Stub private static final int MSG_REMOVE_ASSISTANT_SERVICE_UID = 45; private static final int MSG_UPDATE_ACTIVE_ASSISTANT_SERVICE_UID = 46; private static final int MSG_DISPATCH_DEVICE_VOLUME_BEHAVIOR = 47; + private static final int MSG_ROTATION_UPDATE = 48; + private static final int MSG_FOLD_UPDATE = 49; private static final int MSG_RESET_SPATIALIZER = 50; // start of messages handled under wakelock @@ -1218,7 +1220,9 @@ public class AudioService extends IAudioService.Stub intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); if (mMonitorRotation) { - RotationHelper.init(mContext, mAudioHandler); + RotationHelper.init(mContext, mAudioHandler, + rotationParam -> onRotationUpdate(rotationParam), + foldParam -> onFoldUpdate(foldParam)); } intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION); @@ -1365,6 +1369,20 @@ public class AudioService extends IAudioService.Stub } //----------------------------------------------------------------- + // rotation/fold updates coming from RotationHelper + void onRotationUpdate(String rotationParameter) { + // use REPLACE as only the last rotation matters + sendMsg(mAudioHandler, MSG_ROTATION_UPDATE, SENDMSG_REPLACE, /*arg1*/ 0, /*arg2*/ 0, + /*obj*/ rotationParameter, /*delay*/ 0); + } + + void onFoldUpdate(String foldParameter) { + // use REPLACE as only the last fold state matters + sendMsg(mAudioHandler, MSG_FOLD_UPDATE, SENDMSG_REPLACE, /*arg1*/ 0, /*arg2*/ 0, + /*obj*/ foldParameter, /*delay*/ 0); + } + + //----------------------------------------------------------------- // monitoring requests for volume range initialization @Override // AudioSystemAdapter.OnVolRangeInitRequestListener public void onVolumeRangeInitRequestFromNative() { @@ -8324,6 +8342,16 @@ public class AudioService extends IAudioService.Stub case MSG_DISPATCH_DEVICE_VOLUME_BEHAVIOR: dispatchDeviceVolumeBehavior((AudioDeviceAttributes) msg.obj, msg.arg1); break; + + case MSG_ROTATION_UPDATE: + // rotation parameter format: "rotation=x" where x is one of 0, 90, 180, 270 + mAudioSystem.setParameters((String) msg.obj); + break; + + case MSG_FOLD_UPDATE: + // fold parameter format: "device_folded=x" where x is one of on, off + mAudioSystem.setParameters((String) msg.obj); + break; } } } diff --git a/services/core/java/com/android/server/audio/RotationHelper.java b/services/core/java/com/android/server/audio/RotationHelper.java index eb8387fe85e5..5cdf58bdd62f 100644 --- a/services/core/java/com/android/server/audio/RotationHelper.java +++ b/services/core/java/com/android/server/audio/RotationHelper.java @@ -21,13 +21,14 @@ import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager.FoldStateListener; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; -import android.media.AudioSystem; import android.os.Handler; import android.os.HandlerExecutor; import android.util.Log; import android.view.Display; import android.view.Surface; +import java.util.function.Consumer; + /** * Class to handle device rotation events for AudioService, and forward device rotation * and folded state to the audio HALs through AudioSystem. @@ -53,6 +54,10 @@ class RotationHelper { private static AudioDisplayListener sDisplayListener; private static FoldStateListener sFoldStateListener; + /** callback to send rotation updates to AudioSystem */ + private static Consumer<String> sRotationUpdateCb; + /** callback to send folded state updates to AudioSystem */ + private static Consumer<String> sFoldUpdateCb; private static final Object sRotationLock = new Object(); private static final Object sFoldStateLock = new Object(); @@ -67,13 +72,16 @@ class RotationHelper { * - sDisplayListener != null * - sContext != null */ - static void init(Context context, Handler handler) { + static void init(Context context, Handler handler, + Consumer<String> rotationUpdateCb, Consumer<String> foldUpdateCb) { if (context == null) { throw new IllegalArgumentException("Invalid null context"); } sContext = context; sHandler = handler; sDisplayListener = new AudioDisplayListener(); + sRotationUpdateCb = rotationUpdateCb; + sFoldUpdateCb = foldUpdateCb; enable(); } @@ -115,21 +123,26 @@ class RotationHelper { if (DEBUG_ROTATION) { Log.i(TAG, "publishing device rotation =" + rotation + " (x90deg)"); } + String rotationParam; switch (rotation) { case Surface.ROTATION_0: - AudioSystem.setParameters("rotation=0"); + rotationParam = "rotation=0"; break; case Surface.ROTATION_90: - AudioSystem.setParameters("rotation=90"); + rotationParam = "rotation=90"; break; case Surface.ROTATION_180: - AudioSystem.setParameters("rotation=180"); + rotationParam = "rotation=180"; break; case Surface.ROTATION_270: - AudioSystem.setParameters("rotation=270"); + rotationParam = "rotation=270"; break; default: Log.e(TAG, "Unknown device rotation"); + rotationParam = null; + } + if (rotationParam != null) { + sRotationUpdateCb.accept(rotationParam); } } @@ -140,11 +153,13 @@ class RotationHelper { synchronized (sFoldStateLock) { if (sDeviceFold != newFolded) { sDeviceFold = newFolded; + String foldParam; if (newFolded) { - AudioSystem.setParameters("device_folded=on"); + foldParam = "device_folded=on"; } else { - AudioSystem.setParameters("device_folded=off"); + foldParam = "device_folded=off"; } + sFoldUpdateCb.accept(foldParam); } } } diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 0d9b75481ea9..4767969bd3ed 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -958,7 +958,7 @@ public class BiometricService extends SystemService { public boolean isCoexFaceNonBypassHapticsDisabled(Context context) { return Settings.Secure.getInt(context.getContentResolver(), - CoexCoordinator.FACE_HAPTIC_DISABLE, 1) != 0; + CoexCoordinator.FACE_HAPTIC_DISABLE, 0) != 0; } public Supplier<Long> getRequestGenerator() { diff --git a/services/core/java/com/android/server/biometrics/OWNERS b/services/core/java/com/android/server/biometrics/OWNERS index f05f40353e30..cd281e06f40d 100644 --- a/services/core/java/com/android/server/biometrics/OWNERS +++ b/services/core/java/com/android/server/biometrics/OWNERS @@ -1,9 +1,14 @@ set noparent -kchyn@google.com -jaggies@google.com -curtislb@google.com +graciecheng@google.com ilyamaty@google.com -joshmccloskey@google.com +jaggies@google.com jbolinger@google.com -graciecheng@google.com +jeffpu@google.com +joshmccloskey@google.com + +firewall@google.com +jasonsfchang@google.com +lbill@google.com +mingjuwu@google.com + diff --git a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java index 5aa9b79c074c..c8a90e7a564b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java +++ b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java @@ -92,7 +92,7 @@ public class CoexCoordinator { void sendHapticFeedback(); } - private static CoexCoordinator sInstance; + private static final CoexCoordinator sInstance = new CoexCoordinator(); @VisibleForTesting public static class SuccessfulAuth { @@ -147,14 +147,9 @@ public class CoexCoordinator { } } - /** - * @return a singleton instance. - */ + /** The singleton instance. */ @NonNull public static CoexCoordinator getInstance() { - if (sInstance == null) { - sInstance = new CoexCoordinator(); - } return sInstance; } @@ -339,18 +334,8 @@ public class CoexCoordinator { auth.mCallback.sendHapticFeedback(); auth.mCallback.sendAuthenticationResult(true /* addAuthTokenIfStrong */); auth.mCallback.handleLifecycleAfterAuth(); - } else if (isFaceScanning()) { - // UDFPS rejected but face is still scanning - Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face: " + face); - callback.handleLifecycleAfterAuth(); - - // TODO(b/193089985): Enforce/ensure that face auth finishes (whether - // accept/reject) within X amount of time. Otherwise users will be stuck - // waiting with their finger down for a long time. } else { - // Face not scanning, and was not found in the queue. Most likely, face - // auth was too long ago. - Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face not scanning"); + Slog.d(TAG, "UDFPS rejected in multi-sensor auth"); callback.sendHapticFeedback(); callback.handleLifecycleAfterAuth(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java index a0999771a1be..ae75b7dcc101 100644 --- a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java @@ -67,6 +67,14 @@ public class UserAwareBiometricScheduler extends BiometricScheduler { public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { mHandler.post(() -> { Slog.d(getTag(), "[Client finished] " + clientMonitor + ", success: " + success); + + // Set mStopUserClient to null when StopUserClient fails. Otherwise it's possible + // for that the queue will wait indefinitely until the field is cleared. + if (clientMonitor instanceof StopUserClient<?> && !success) { + Slog.w(getTag(), + "StopUserClient failed(), is the HAL stuck? Clearing mStopUserClient"); + mStopUserClient = null; + } if (mCurrentOperation != null && mCurrentOperation.isFor(mOwner)) { mCurrentOperation = null; } else { @@ -166,4 +174,9 @@ public class UserAwareBiometricScheduler extends BiometricScheduler { mStopUserClient.onUserStopped(); mStopUserClient = null; } + + @VisibleForTesting + @Nullable public StopUserClient<?> getStopUserClient() { + return mStopUserClient; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java index 9ae6750dbcbf..d0c58fd0545f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java @@ -99,7 +99,10 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession> super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, cookie, requireConfirmation, sensorId, logger, biometricContext, isStrongBiometric, null /* taskStackListener */, lockoutCache, - allowBackgroundAuthentication, true /* shouldVibrate */, + allowBackgroundAuthentication, + context.getResources().getBoolean( + com.android.internal.R.bool.system_server_plays_face_haptics) + /* shouldVibrate */, isKeyguardBypassEnabled); setRequestId(requestId); mUsageStats = usageStats; diff --git a/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java b/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java index e222c644da9e..d238dae634ad 100644 --- a/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java +++ b/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java @@ -27,8 +27,6 @@ import android.view.InputWindowHandle; import android.view.SurfaceControl; import android.view.WindowManager; -import com.android.server.policy.WindowManagerPolicy; - /** * An internal implementation of an {@link InputMonitor} that uses a spy window. * @@ -69,9 +67,7 @@ class GestureMonitorSpyWindow { final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); t.setInputWindowInfo(mInputSurface, mWindowHandle); - // Gesture monitor should be above handwriting event surface, hence setting it to - // WindowManagerPolicy.INPUT_DISPLAY_OVERLAY_LAYER + 1 - t.setLayer(mInputSurface, WindowManagerPolicy.INPUT_DISPLAY_OVERLAY_LAYER + 1); + t.setLayer(mInputSurface, Integer.MAX_VALUE); t.setPosition(mInputSurface, 0, 0); t.setCrop(mInputSurface, null /* crop to parent surface */); t.show(mInputSurface); diff --git a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java index 5438faa8793e..8180e66166d9 100644 --- a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java +++ b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java @@ -27,8 +27,6 @@ import android.view.InputWindowHandle; import android.view.SurfaceControl; import android.view.WindowManager; -import com.android.server.policy.WindowManagerPolicy; - final class HandwritingEventReceiverSurface { public static final String TAG = HandwritingEventReceiverSurface.class.getSimpleName(); @@ -38,8 +36,7 @@ final class HandwritingEventReceiverSurface { // is above gesture monitors, then edge-back and swipe-up gestures won't work when this surface // is intercepting. // TODO(b/217538817): Specify the ordering in WM by usage. - private static final int HANDWRITING_SURFACE_LAYER = - WindowManagerPolicy.INPUT_DISPLAY_OVERLAY_LAYER; + private static final int HANDWRITING_SURFACE_LAYER = Integer.MAX_VALUE - 1; private final InputWindowHandle mWindowHandle; private final InputChannel mClientChannel; diff --git a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java index 12f8776a8e18..1435016fc55a 100644 --- a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java +++ b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java @@ -21,6 +21,7 @@ import android.os.PersistableBundle; import android.os.SystemProperties; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -73,6 +74,8 @@ public class GnssConfiguration { static final String CONFIG_NFW_PROXY_APPS = "NFW_PROXY_APPS"; private static final String CONFIG_ENABLE_PSDS_PERIODIC_DOWNLOAD = "ENABLE_PSDS_PERIODIC_DOWNLOAD"; + private static final String CONFIG_ENABLE_ACTIVE_SIM_EMERGENCY_SUPL = + "ENABLE_ACTIVE_SIM_EMERGENCY_SUPL"; static final String CONFIG_LONGTERM_PSDS_SERVER_1 = "LONGTERM_PSDS_SERVER_1"; static final String CONFIG_LONGTERM_PSDS_SERVER_2 = "LONGTERM_PSDS_SERVER_2"; static final String CONFIG_LONGTERM_PSDS_SERVER_3 = "LONGTERM_PSDS_SERVER_3"; @@ -207,6 +210,14 @@ public class GnssConfiguration { } /** + * Returns true if during an emergency call, the GnssConfiguration of the activeSubId will be + * injected for the emergency SUPL flow; Returns false otherwise. Default false if not set. + */ + boolean isActiveSimEmergencySuplEnabled() { + return getBooleanConfig(CONFIG_ENABLE_ACTIVE_SIM_EMERGENCY_SUPL, false); + } + + /** * Returns true if a long-term PSDS server is configured. */ boolean isLongTermPsdsServerConfigured() { @@ -232,16 +243,31 @@ public class GnssConfiguration { /** * Loads the GNSS properties from carrier config file followed by the properties from - * gps debug config file. + * gps debug config file, and injects the GNSS properties into the HAL. */ void reloadGpsProperties() { - if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + mProperties.size()); - loadPropertiesFromCarrierConfig(); + reloadGpsProperties(/* inEmergency= */ false, /* activeSubId= */ -1); + } - String lpp_prof = SystemProperties.get(LPP_PROFILE); - if (!TextUtils.isEmpty(lpp_prof)) { - // override default value of this if lpp_prof is not empty - mProperties.setProperty(CONFIG_LPP_PROFILE, lpp_prof); + /** + * Loads the GNSS properties from carrier config file followed by the properties from + * gps debug config file, and injects the GNSS properties into the HAL. + */ + void reloadGpsProperties(boolean inEmergency, int activeSubId) { + if (DEBUG) { + Log.d(TAG, + "Reset GPS properties, previous size = " + mProperties.size() + ", inEmergency:" + + inEmergency + ", activeSubId=" + activeSubId); + } + loadPropertiesFromCarrierConfig(inEmergency, activeSubId); + + if (isSimAbsent(mContext)) { + // Use the default SIM's LPP profile when SIM is absent. + String lpp_prof = SystemProperties.get(LPP_PROFILE); + if (!TextUtils.isEmpty(lpp_prof)) { + // override default value of this if lpp_prof is not empty + mProperties.setProperty(CONFIG_LPP_PROFILE, lpp_prof); + } } /* @@ -322,16 +348,19 @@ public class GnssConfiguration { /** * Loads GNSS properties from carrier config file. */ - void loadPropertiesFromCarrierConfig() { + void loadPropertiesFromCarrierConfig(boolean inEmergency, int activeSubId) { CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); if (configManager == null) { return; } - int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId(); - PersistableBundle configs = SubscriptionManager.isValidSubscriptionId(ddSubId) - ? configManager.getConfigForSubId(ddSubId) : configManager.getConfig(); + int subId = SubscriptionManager.getDefaultDataSubscriptionId(); + if (inEmergency && activeSubId >= 0) { + subId = activeSubId; + } + PersistableBundle configs = SubscriptionManager.isValidSubscriptionId(subId) + ? configManager.getConfigForSubId(subId) : configManager.getConfig(); if (configs == null) { if (DEBUG) Log.d(TAG, "SIM not ready, use default carrier config."); configs = CarrierConfigManager.getDefaultConfig(); @@ -422,6 +451,12 @@ public class GnssConfiguration { return gnssConfiguartionIfaceVersion.mMajor < 2; } + private static boolean isSimAbsent(Context context) { + TelephonyManager phone = (TelephonyManager) context.getSystemService( + Context.TELEPHONY_SERVICE); + return phone.getSimState() == TelephonyManager.SIM_STATE_ABSENT; + } + private static native HalInterfaceVersion native_get_gnss_configuration_version(); private static native boolean native_set_supl_version(int version); diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index f5c2bbc8d5a2..a6a3db11b729 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -126,6 +126,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; /** * A GNSS implementation of LocationProvider used by LocationManager. @@ -359,8 +360,9 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } } if (isKeepLppProfile) { - // load current properties for the carrier - mGnssConfiguration.loadPropertiesFromCarrierConfig(); + // load current properties for the carrier of ddSubId + mGnssConfiguration.loadPropertiesFromCarrierConfig(/* inEmergency= */ false, + /* activeSubId= */ -1); String lpp_profile = mGnssConfiguration.getLppProfile(); // set the persist property LPP_PROFILE for the value if (lpp_profile != null) { @@ -431,13 +433,38 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // this approach is just fine because events are posted to our handler anyway mGnssConfiguration = mGnssNative.getConfiguration(); // Create a GPS net-initiated handler (also needed by handleInitialize) + GpsNetInitiatedHandler.EmergencyCallCallback emergencyCallCallback = + new GpsNetInitiatedHandler.EmergencyCallCallback() { + + @Override + public void onEmergencyCallStart(int subId) { + if (!mGnssConfiguration.isActiveSimEmergencySuplEnabled()) { + return; + } + mHandler.post(() -> mGnssConfiguration.reloadGpsProperties( + mNIHandler.getInEmergency(), subId)); + } + + @Override + public void onEmergencyCallEnd() { + if (!mGnssConfiguration.isActiveSimEmergencySuplEnabled()) { + return; + } + mHandler.postDelayed(() -> mGnssConfiguration.reloadGpsProperties( + /* inEmergency= */ false, + SubscriptionManager.getDefaultDataSubscriptionId()), + TimeUnit.SECONDS.toMillis(mGnssConfiguration.getEsExtensionSec())); + } + }; mNIHandler = new GpsNetInitiatedHandler(context, mNetInitiatedListener, + emergencyCallCallback, mSuplEsEnabled); // Trigger PSDS data download when the network comes up after booting. mPendingDownloadPsdsTypes.add(GnssPsdsDownloader.LONG_TERM_PSDS_SERVER_INDEX); mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(context, - GnssLocationProvider.this::onNetworkAvailable, mHandler.getLooper(), mNIHandler); + GnssLocationProvider.this::onNetworkAvailable, + mHandler.getLooper(), mNIHandler); mNtpTimeHelper = new NtpTimeHelper(mContext, mHandler.getLooper(), this); mGnssSatelliteBlocklistHelper = @@ -1694,9 +1721,12 @@ public class GnssLocationProvider extends AbstractLocationProvider implements int type = AGPS_SETID_TYPE_NONE; String setId = null; - int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId(); - if (SubscriptionManager.isValidSubscriptionId(ddSubId)) { - phone = phone.createForSubscriptionId(ddSubId); + int subId = SubscriptionManager.getDefaultDataSubscriptionId(); + if (mNIHandler.getInEmergency() && mNetworkConnectivityHandler.getActiveSubId() >= 0) { + subId = mNetworkConnectivityHandler.getActiveSubId(); + } + if (SubscriptionManager.isValidSubscriptionId(subId)) { + phone = phone.createForSubscriptionId(subId); } if ((flags & AGPS_REQUEST_SETID_IMSI) == AGPS_REQUEST_SETID_IMSI) { setId = phone.getSubscriberId(); diff --git a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java index d9ca4d341e8e..dc1f4ddb19b9 100644 --- a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java +++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java @@ -190,7 +190,7 @@ class GnssNetworkConnectivityHandler { mContext = context; mGnssNetworkListener = gnssNetworkListener; - SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class); + SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class); if (subManager != null) { subManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener); } @@ -311,6 +311,13 @@ class GnssNetworkConnectivityHandler { } /** + * Returns the active Sub ID for emergency SUPL connection. + */ + int getActiveSubId() { + return mActiveSubId; + } + + /** * Called from native code to update AGPS connection status, or to request or release a SUPL * connection. * diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java index 03e568c4599e..88b4a94f7027 100644 --- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java @@ -413,8 +413,8 @@ public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stu return result; } mContext.getSystemService(AppOpsManager.class).noteOpNoThrow( - AppOpsManager.OP_RECORD_AUDIO_HOTWORD, uid, packageName, attributionTag, - reason); + AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO, uid, packageName, + attributionTag, reason); return result; } } diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java index ebd9126d1439..a6d148c824c9 100644 --- a/services/core/java/com/android/server/policy/AppOpsPolicy.java +++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java @@ -202,8 +202,9 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat } private static boolean isHotwordDetectionServiceRequired(PackageManager pm) { - // Usage of the HotwordDetectionService won't be enforced until a later release. - return false; + // The HotwordDetectionService APIs aren't ready yet for Auto or TV. + return !(pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) + || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)); } @Override diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 89178139ffec..7ca09ab5154f 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -156,10 +156,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { int FINISH_LAYOUT_REDO_ANIM = 0x0008; /** Layer for the screen off animation */ int COLOR_FADE_LAYER = 0x40000001; - /** Layer for Input overlays for capturing inputs for gesture detection, etc. */ - int INPUT_DISPLAY_OVERLAY_LAYER = 0x7f000000; - /** Layer for Screen Decoration: The top most visible layer just below input overlay layers */ - int SCREEN_DECOR_DISPLAY_OVERLAY_LAYER = INPUT_DISPLAY_OVERLAY_LAYER - 1; /** * Register shortcuts for window manager to dispatch. diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 83687e9ebccd..026e5d286630 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -874,7 +874,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean mEnteringAnimation; boolean mOverrideTaskTransition; - boolean mDismissKeyguardIfInsecure; + boolean mDismissKeyguard; boolean mAppStopped; // A hint to override the window specified rotation animation, or -1 to use the window specified @@ -1993,7 +1993,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } mOverrideTaskTransition = options.getOverrideTaskTransition(); - mDismissKeyguardIfInsecure = options.getDismissKeyguardIfInsecure(); + mDismissKeyguard = options.getDismissKeyguard(); } ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService( diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index d190b4f07121..39a061149f08 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -64,8 +64,8 @@ import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS; import static android.provider.Settings.System.FONT_SCALE; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; -import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT; import static android.view.WindowManager.TRANSIT_WAKE; +import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; @@ -400,6 +400,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { /** The time at which the previous process was last visible. */ private long mPreviousProcessVisibleTime; + /** It is set from keyguard-going-away to set-keyguard-shown. */ + static final int DEMOTE_TOP_REASON_DURING_UNLOCKING = 1; + /** It is set if legacy recents animation is running. */ + static final int DEMOTE_TOP_REASON_ANIMATING_RECENTS = 1 << 1; + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + DEMOTE_TOP_REASON_DURING_UNLOCKING, + DEMOTE_TOP_REASON_ANIMATING_RECENTS, + }) + @interface DemoteTopReason {} + + /** + * If non-zero, getTopProcessState() will + * return {@link ActivityManager#PROCESS_STATE_IMPORTANT_FOREGROUND} to avoid top app from + * preempting CPU while another process is running an important animation. + */ + @DemoteTopReason + volatile int mDemoteTopAppReasons; + /** List of intents that were used to start the most recent tasks. */ private RecentTasks mRecentTasks; /** State of external calls telling us if the device is awake or asleep. */ @@ -2839,12 +2859,24 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { keyguardShowing); mH.sendMessage(msg); } + // Always reset the state regardless of keyguard-showing change, because that means the + // unlock is either completed or canceled. + if ((mDemoteTopAppReasons & DEMOTE_TOP_REASON_DURING_UNLOCKING) != 0) { + mDemoteTopAppReasons &= ~DEMOTE_TOP_REASON_DURING_UNLOCKING; + // The scheduling group of top process was demoted by unlocking, so recompute + // to restore its real top priority if possible. + if (mTopApp != null) { + mTopApp.scheduleUpdateOomAdj(); + } + } try { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "setLockScreenShown"); mRootWindowContainer.forAllDisplays(displayContent -> { mKeyguardController.setKeyguardShown(displayContent.getDisplayId(), keyguardShowing, aodShowing); }); } finally { + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); Binder.restoreCallingIdentity(ident); } } @@ -2871,6 +2903,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // animation of system UI. Even if AOD is not enabled, it should be no harm. final WindowProcessController proc; synchronized (mGlobalLockWithoutBoost) { + mDemoteTopAppReasons &= ~DEMOTE_TOP_REASON_DURING_UNLOCKING; final WindowState notificationShade = mRootWindowContainer.getDefaultDisplay() .getDisplayPolicy().getNotificationShade(); proc = notificationShade != null @@ -3408,8 +3441,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { try { synchronized (mGlobalLock) { // Keyguard asked us to clear the home task snapshot before going away, so do that. - if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT) != 0) { + if ((flags & KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT) != 0) { mActivityClientController.invalidateHomeTaskSnapshot(null /* token */); + } else if (mKeyguardShown) { + // Only set if it is not unlocking to launcher which may also animate. + mDemoteTopAppReasons |= DEMOTE_TOP_REASON_DURING_UNLOCKING; } mRootWindowContainer.forAllDisplays(displayContent -> { @@ -3977,6 +4013,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mTaskOrganizerController.dump(pw, " "); mVisibleActivityProcessTracker.dump(pw, " "); mActiveUids.dump(pw, " "); + if (mDemoteTopAppReasons != 0) { + pw.println(" mDemoteTopAppReasons=" + mDemoteTopAppReasons); + } } if (!printedAnything) { @@ -5604,12 +5643,17 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @HotPath(caller = HotPath.OOM_ADJUSTMENT) @Override public int getTopProcessState() { + final int topState = mTopProcessState; + if (mDemoteTopAppReasons != 0 && topState == ActivityManager.PROCESS_STATE_TOP) { + // There may be a more important UI/animation than the top app. + return ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + } if (mRetainPowerModeAndTopProcessState) { // There is a launching app while device may be sleeping, force the top state so // the launching process can have top-app scheduling group. return ActivityManager.PROCESS_STATE_TOP; } - return mTopProcessState; + return topState; } @HotPath(caller = HotPath.PROCESS_CHANGE) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index a03dce364209..79aef00750a1 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3233,10 +3233,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } public void setRotationAnimation(ScreenRotationAnimation screenRotationAnimation) { - if (mScreenRotationAnimation != null) { - mScreenRotationAnimation.kill(); - } + final ScreenRotationAnimation prev = mScreenRotationAnimation; mScreenRotationAnimation = screenRotationAnimation; + if (prev != null) { + prev.kill(); + } // Hide the windows which are not significant in rotation animation. So that the windows // don't need to block the unfreeze time. @@ -5395,7 +5396,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp SurfaceControl[] findRoundedCornerOverlays() { List<SurfaceControl> roundedCornerOverlays = new ArrayList<>(); for (WindowToken token : mTokenMap.values()) { - if (token.mRoundedCornerOverlay) { + if (token.mRoundedCornerOverlay && token.isVisible()) { roundedCornerOverlays.add(token.mSurfaceControl); } } diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java index b7ddbd070460..33cdd2e98113 100644 --- a/services/core/java/com/android/server/wm/InputManagerCallback.java +++ b/services/core/java/com/android/server/wm/InputManagerCallback.java @@ -265,7 +265,7 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal .setContainerLayer() .setName(name) .setCallsite("createSurfaceForGestureMonitor") - .setParent(dc.getOverlayLayer()) + .setParent(dc.getSurfaceControl()) .build(); } } diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index f36dbfa2316e..a4c05eecdb07 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -41,6 +41,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.KeyguardControllerProto.AOD_SHOWING; +import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_GOING_AWAY; import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_PER_DISPLAY; import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_SHOWING; @@ -589,13 +590,12 @@ class KeyguardController { mTopTurnScreenOnActivity = top; } - final boolean isKeyguardSecure = controller.mWindowManager.isKeyguardSecure( - controller.mService.getCurrentUserId()); - if (top.mDismissKeyguardIfInsecure && mKeyguardShowing && !isKeyguardSecure) { + if (top.mDismissKeyguard && mKeyguardShowing) { mKeyguardGoingAway = true; } else if (top.canShowWhenLocked()) { mTopOccludesActivity = top; } + top.mDismissKeyguard = false; // Only the top activity may control occluded, as we can't occlude the Keyguard // if the top app doesn't want to occlude it. @@ -673,6 +673,7 @@ class KeyguardController { proto.write(KeyguardPerDisplayProto.KEYGUARD_SHOWING, mKeyguardShowing); proto.write(KeyguardPerDisplayProto.AOD_SHOWING, mAodShowing); proto.write(KeyguardPerDisplayProto.KEYGUARD_OCCLUDED, mOccluded); + proto.write(KeyguardPerDisplayProto.KEYGUARD_GOING_AWAY, mKeyguardGoingAway); proto.end(token); } } @@ -693,6 +694,7 @@ class KeyguardController { final long token = proto.start(fieldId); proto.write(AOD_SHOWING, default_state.mAodShowing); proto.write(KEYGUARD_SHOWING, default_state.mKeyguardShowing); + proto.write(KEYGUARD_GOING_AWAY, default_state.mKeyguardGoingAway); writeDisplayStatesToProto(proto, KEYGUARD_PER_DISPLAY); proto.end(token); } diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index eca201dc2bda..f840171b29b0 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -203,9 +203,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan final LaunchingState launchingState = mTaskSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent); - if (mCaller != null) { - mCaller.setRunningRecentsAnimation(true); - } + setProcessAnimating(true); mService.deferWindowLayout(); try { @@ -409,15 +407,33 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan if (mWindowManager.mRoot.isLayoutNeeded()) { mWindowManager.mRoot.performSurfacePlacement(); } - if (mCaller != null) { - mCaller.setRunningRecentsAnimation(false); - } + setProcessAnimating(false); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } }); } } + /** Gives the owner of recents animation higher priority. */ + private void setProcessAnimating(boolean animating) { + if (mCaller == null) return; + // Apply the top-app scheduling group to who runs the animation. + mCaller.setRunningRecentsAnimation(animating); + int demoteReasons = mService.mDemoteTopAppReasons; + if (animating) { + demoteReasons |= ActivityTaskManagerService.DEMOTE_TOP_REASON_ANIMATING_RECENTS; + } else { + demoteReasons &= ~ActivityTaskManagerService.DEMOTE_TOP_REASON_ANIMATING_RECENTS; + } + mService.mDemoteTopAppReasons = demoteReasons; + // Make the demotion of the real top app take effect. No need to restore top app state for + // finishing recents because addToStopping -> scheduleIdle -> activityIdleInternal -> + // trimApplications will have a full update. + if (animating && mService.mTopApp != null) { + mService.mTopApp.scheduleUpdateOomAdj(); + } + } + @Override public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode, boolean sendUserLeaveHint) { diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java index 66d02308bf0b..9856ebf7dc2a 100644 --- a/services/core/java/com/android/server/wm/SafeActivityOptions.java +++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.Manifest.permission.CONTROL_KEYGUARD; import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.Manifest.permission.STATUS_BAR_SERVICE; @@ -316,6 +317,20 @@ public class SafeActivityOptions { } } + // Check if the caller is allowed to dismiss keyguard. + final boolean dismissKeyguard = options.getDismissKeyguard(); + if (aInfo != null && dismissKeyguard) { + final int controlKeyguardPerm = ActivityTaskManagerService.checkPermission( + CONTROL_KEYGUARD, callingPid, callingUid); + if (controlKeyguardPerm != PERMISSION_GRANTED) { + final String msg = "Permission Denial: starting " + getIntentString(intent) + + " from " + callerApp + " (pid=" + callingPid + + ", uid=" + callingUid + ") with dismissKeyguard=true"; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + } + // Check permission for remote animations final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter(); if (adapter != null && supervisor.mService.checkPermission( diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 2ef19321d958..f31a3cc9bcb3 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -40,9 +40,11 @@ import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; +import android.os.IBinder; import android.os.Trace; import android.util.Slog; import android.util.proto.ProtoOutputStream; +import android.view.DisplayAddress; import android.view.DisplayInfo; import android.view.Surface; import android.view.Surface.OutOfResourcesException; @@ -102,6 +104,7 @@ class ScreenRotationAnimation { private SurfaceControl mEnterBlackFrameLayer; /** This layer contains the actual screenshot that is to be faded out. */ private SurfaceControl mScreenshotLayer; + private SurfaceControl[] mRoundedCornerOverlay; /** * Only used for screen rotation and not custom animations. Layered behind all other layers * to avoid showing any "empty" spots @@ -151,6 +154,11 @@ class ScreenRotationAnimation { final boolean flipped = delta == Surface.ROTATION_90 || delta == Surface.ROTATION_270; mOriginalWidth = flipped ? height : width; mOriginalHeight = flipped ? width : height; + final int logicalWidth = displayInfo.logicalWidth; + final int logicalHeight = displayInfo.logicalHeight; + final boolean isSizeChanged = + logicalWidth > mOriginalWidth == logicalHeight > mOriginalHeight + && (logicalWidth != mOriginalWidth || logicalHeight != mOriginalHeight); mSurfaceRotationAnimationController = new SurfaceRotationAnimationController(); // Check whether the current screen contains any secure content. @@ -159,18 +167,43 @@ class ScreenRotationAnimation { final SurfaceControl.Transaction t = mService.mTransactionFactory.get(); try { - SurfaceControl.LayerCaptureArgs args = - new SurfaceControl.LayerCaptureArgs.Builder(displayContent.getSurfaceControl()) - .setCaptureSecureLayers(true) - .setAllowProtected(true) - .setSourceCrop(new Rect(0, 0, width, height)) - // Exclude rounded corner overlay from screenshot buffer. Rounded - // corner overlay windows are un-rotated during rotation animation - // for a seamless transition. - .setExcludeLayers(displayContent.findRoundedCornerOverlays()) - .build(); - SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = - SurfaceControl.captureLayers(args); + final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer; + if (isSizeChanged) { + final DisplayAddress address = displayInfo.address; + if (!(address instanceof DisplayAddress.Physical)) { + Slog.e(TAG, "Display does not have a physical address: " + displayId); + return; + } + final DisplayAddress.Physical physicalAddress = + (DisplayAddress.Physical) address; + final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken( + physicalAddress.getPhysicalDisplayId()); + if (displayToken == null) { + Slog.e(TAG, "Display token is null."); + return; + } + // Temporarily not skip screenshot for the rounded corner overlays and screenshot + // the whole display to include the rounded corner overlays. + setSkipScreenshotForRoundedCornerOverlays(false, t); + mRoundedCornerOverlay = displayContent.findRoundedCornerOverlays(); + final SurfaceControl.DisplayCaptureArgs captureArgs = + new SurfaceControl.DisplayCaptureArgs.Builder(displayToken) + .setSourceCrop(new Rect(0, 0, width, height)) + .setAllowProtected(true) + .setCaptureSecureLayers(true) + .build(); + screenshotBuffer = SurfaceControl.captureDisplay(captureArgs); + } else { + SurfaceControl.LayerCaptureArgs captureArgs = + new SurfaceControl.LayerCaptureArgs.Builder( + displayContent.getSurfaceControl()) + .setCaptureSecureLayers(true) + .setAllowProtected(true) + .setSourceCrop(new Rect(0, 0, width, height)) + .build(); + screenshotBuffer = SurfaceControl.captureLayers(captureArgs); + } + if (screenshotBuffer == null) { Slog.w(TAG, "Unable to take screenshot of display " + displayId); return; @@ -232,6 +265,14 @@ class ScreenRotationAnimation { t.show(mScreenshotLayer); t.show(mBackColorSurface); + if (mRoundedCornerOverlay != null) { + for (SurfaceControl sc : mRoundedCornerOverlay) { + if (sc.isValid()) { + t.hide(sc); + } + } + } + } catch (OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate freeze surface", e); } @@ -240,10 +281,7 @@ class ScreenRotationAnimation { // the new logical display size. Currently pending transaction and RWC#mDisplayTransaction // are merged to global transaction, so it can be synced with display change when calling // DisplayManagerInternal#performTraversal(transaction). - final int logicalWidth = displayInfo.logicalWidth; - final int logicalHeight = displayInfo.logicalHeight; - if (logicalWidth > mOriginalWidth == logicalHeight > mOriginalHeight - && (logicalWidth != mOriginalWidth || logicalHeight != mOriginalHeight)) { + if (mScreenshotLayer != null && isSizeChanged) { displayContent.getPendingTransaction().setGeometry(mScreenshotLayer, new Rect(0, 0, mOriginalWidth, mOriginalHeight), new Rect(0, 0, logicalWidth, logicalHeight), Surface.ROTATION_0); @@ -264,6 +302,21 @@ class ScreenRotationAnimation { t.apply(); } + void setSkipScreenshotForRoundedCornerOverlays( + boolean skipScreenshot, SurfaceControl.Transaction t) { + mDisplayContent.forAllWindows(w -> { + if (!w.mToken.mRoundedCornerOverlay || !w.isVisible() || !w.mWinAnimator.hasSurface()) { + return; + } + t.setSkipScreenshot(w.mWinAnimator.mSurfaceController.mSurfaceControl, skipScreenshot); + }, false); + if (!skipScreenshot) { + // Use sync apply to apply the change immediately, so that the next + // SC.captureDisplay can capture the screen decor layers. + t.apply(true /* sync */); + } + } + public void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(STARTED, mStarted); @@ -472,6 +525,19 @@ class ScreenRotationAnimation { } mBackColorSurface = null; } + + if (mRoundedCornerOverlay != null) { + if (mDisplayContent.getRotationAnimation() == null + || mDisplayContent.getRotationAnimation() == this) { + setSkipScreenshotForRoundedCornerOverlays(true, t); + for (SurfaceControl sc : mRoundedCornerOverlay) { + if (sc.isValid()) { + t.show(sc); + } + } + } + mRoundedCornerOverlay = null; + } t.apply(); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 52af39ee64b3..902218621cd0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -8215,7 +8215,7 @@ public class WindowManagerService extends IWindowManager.Stub .setContainerLayer() .setName("IME Handwriting Surface") .setCallsite("getHandwritingSurfaceForDisplay") - .setParent(dc.getOverlayLayer()) + .setParent(dc.getSurfaceControl()) .build(); } } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 40417a4857d3..215bcb0cd8e2 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -1126,6 +1126,13 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio mAtm.mH.sendMessage(m); } + /** Refreshes oom adjustment and process state of this process. */ + void scheduleUpdateOomAdj() { + mAtm.mH.sendMessage(PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo, + mListener, false /* updateServiceConnectionActivities */, + false /* activityChange */, true /* updateOomAdj */)); + } + /** Makes the process have top state before oom-adj is computed from a posted message. */ void addToPendingTop() { mAtm.mAmInternal.addPendingTopUid(mUid, mPid, mThread); diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 18f60b1a9a20..d2e56faa0914 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -368,7 +368,7 @@ class WindowToken extends WindowContainer<WindowState> { super.assignRelativeLayer(t, mDisplayContent.getDefaultTaskDisplayArea().getSplitScreenDividerAnchor(), 1); } else if (mRoundedCornerOverlay) { - super.assignLayer(t, WindowManagerPolicy.SCREEN_DECOR_DISPLAY_OVERLAY_LAYER); + super.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1); } else { super.assignLayer(t, layer); } @@ -378,7 +378,7 @@ class WindowToken extends WindowContainer<WindowState> { SurfaceControl.Builder makeSurface() { final SurfaceControl.Builder builder = super.makeSurface(); if (mRoundedCornerOverlay) { - builder.setParent(getDisplayContent().getOverlayLayer()); + builder.setParent(null); } return builder; } diff --git a/services/tests/servicestests/src/com/android/server/backup/restore/FullRestoreEngineTest.java b/services/tests/servicestests/src/com/android/server/backup/restore/FullRestoreEngineTest.java deleted file mode 100644 index 049c745fc128..000000000000 --- a/services/tests/servicestests/src/com/android/server/backup/restore/FullRestoreEngineTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.backup.restore; - -import static com.google.common.truth.Truth.assertWithMessage; - -import android.app.backup.BackupAgent; -import android.platform.test.annotations.Presubmit; -import android.system.OsConstants; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.backup.FileMetadata; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@Presubmit -@RunWith(AndroidJUnit4.class) -public class FullRestoreEngineTest { - private static final String DEFAULT_PACKAGE_NAME = "package"; - private static final String DEFAULT_DOMAIN_NAME = "domain"; - private static final String NEW_PACKAGE_NAME = "new_package"; - private static final String NEW_DOMAIN_NAME = "new_domain"; - - private FullRestoreEngine mRestoreEngine; - - @Before - public void setUp() { - mRestoreEngine = new FullRestoreEngine(); - } - - @Test - public void shouldSkipReadOnlyDir_skipsAllReadonlyDirsAndTheirChildren() { - // Create the file tree. - TestFile[] testFiles = new TestFile[] { - TestFile.dir("root"), - TestFile.file("root/auth_token"), - TestFile.dir("root/media"), - TestFile.file("root/media/picture1.png"), - TestFile.file("root/push_token.txt"), - TestFile.dir("root/read-only-dir-1").markReadOnly().expectSkipped(), - TestFile.dir("root/read-only-dir-1/writable-subdir").expectSkipped(), - TestFile.file("root/read-only-dir-1/writable-subdir/writable-file").expectSkipped(), - TestFile.dir("root/read-only-dir-1/writable-subdir/read-only-subdir-2") - .markReadOnly().expectSkipped(), - TestFile.file("root/read-only-dir-1/writable-file").expectSkipped(), - TestFile.file("root/random-stuff.txt"), - TestFile.dir("root/database"), - TestFile.file("root/database/users.db"), - TestFile.dir("root/read-only-dir-2").markReadOnly().expectSkipped(), - TestFile.file("root/read-only-dir-2/writable-file-1").expectSkipped(), - TestFile.file("root/read-only-dir-2/writable-file-2").expectSkipped(), - }; - - assertCorrectItemsAreSkipped(testFiles); - } - - @Test - public void shouldSkipReadOnlyDir_onlySkipsChildrenUnderTheSamePackage() { - TestFile[] testFiles = new TestFile[]{ - TestFile.dir("read-only-dir").markReadOnly().expectSkipped(), - TestFile.file("read-only-dir/file").expectSkipped(), - TestFile.file("read-only-dir/file-from-different-package") - .setPackage(NEW_PACKAGE_NAME), - }; - - assertCorrectItemsAreSkipped(testFiles); - } - - @Test - public void shouldSkipReadOnlyDir_onlySkipsChildrenUnderTheSameDomain() { - TestFile[] testFiles = new TestFile[]{ - TestFile.dir("read-only-dir").markReadOnly().expectSkipped(), - TestFile.file("read-only-dir/file").expectSkipped(), - TestFile.file("read-only-dir/file-from-different-domain") - .setDomain(NEW_DOMAIN_NAME), - }; - - assertCorrectItemsAreSkipped(testFiles); - } - - private void assertCorrectItemsAreSkipped(TestFile[] testFiles) { - // Verify all directories marked with .expectSkipped are skipped. - for (TestFile testFile : testFiles) { - boolean actualExcluded = mRestoreEngine.shouldSkipReadOnlyDir(testFile.mMetadata); - boolean expectedExcluded = testFile.mShouldSkip; - assertWithMessage(testFile.mMetadata.path).that(actualExcluded).isEqualTo( - expectedExcluded); - } - } - - private static class TestFile { - private final FileMetadata mMetadata; - private boolean mShouldSkip; - - static TestFile dir(String path) { - return new TestFile(path, BackupAgent.TYPE_DIRECTORY); - } - - static TestFile file(String path) { - return new TestFile(path, BackupAgent.TYPE_FILE); - } - - TestFile markReadOnly() { - mMetadata.mode = 0; - return this; - } - - TestFile expectSkipped() { - mShouldSkip = true; - return this; - } - - TestFile setPackage(String packageName) { - mMetadata.packageName = packageName; - return this; - } - - TestFile setDomain(String domain) { - mMetadata.domain = domain; - return this; - } - - private TestFile(String path, int type) { - FileMetadata metadata = new FileMetadata(); - metadata.path = path; - metadata.type = type; - metadata.packageName = DEFAULT_PACKAGE_NAME; - metadata.domain = DEFAULT_DOMAIN_NAME; - metadata.mode = OsConstants.S_IWUSR; // Mark as writable. - mMetadata = metadata; - } - } -} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java index f40b31a0bc0d..abf992b6c637 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java @@ -415,7 +415,7 @@ public class CoexCoordinatorTest { // Auth was attempted when(mUdfpsClient.getState()) .thenReturn(AuthenticationClient.STATE_STARTED_PAUSED_ATTEMPTED); - verify(mCallback, never()).sendHapticFeedback(); + verify(mCallback).sendHapticFeedback(); verify(mCallback).handleLifecycleAfterAuth(); // Then face rejected. Note that scheduler leaves UDFPS in the CoexCoordinator since @@ -425,7 +425,7 @@ public class CoexCoordinatorTest { LockoutTracker.LOCKOUT_NONE, faceCallback); verify(faceCallback).sendHapticFeedback(); verify(faceCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */); - verify(mCallback, never()).sendHapticFeedback(); + verify(mCallback).sendHapticFeedback(); } @Test diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java index 8391914a0bb6..0df3028805d2 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java @@ -80,6 +80,11 @@ public class UserAwareBiometricSchedulerTest { @Mock private BiometricContext mBiometricContext; + private boolean mShouldFailStopUser = false; + private final StopUserClientShouldFail mStopUserClientShouldFail = + () -> { + return mShouldFailStopUser; + }; private final TestUserStartedCallback mUserStartedCallback = new TestUserStartedCallback(); private final TestUserStoppedCallback mUserStoppedCallback = new TestUserStoppedCallback(); private int mCurrentUserId = UserHandle.USER_NULL; @@ -88,6 +93,7 @@ public class UserAwareBiometricSchedulerTest { @Before public void setUp() { + mShouldFailStopUser = false; mHandler = new Handler(TestableLooper.get(this).getLooper()); mScheduler = new UserAwareBiometricScheduler(TAG, mHandler, @@ -101,7 +107,7 @@ public class UserAwareBiometricSchedulerTest { public StopUserClient<?> getStopUserClient(int userId) { return new TestStopUserClient(mContext, Object::new, mToken, userId, TEST_SENSOR_ID, mBiometricLogger, mBiometricContext, - mUserStoppedCallback); + mUserStoppedCallback, mStopUserClientShouldFail); } @NonNull @@ -240,6 +246,36 @@ public class UserAwareBiometricSchedulerTest { assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(1); } + @Test + public void testStartUser_failsClearsStopUserClient() { + // When a stop user client fails, check that mStopUserClient + // is set to null to prevent the scheduler from getting stuck. + BaseClientMonitor nextClient = mock(BaseClientMonitor.class); + when(nextClient.getTargetUserId()).thenReturn(10); + + mScheduler.scheduleClientMonitor(nextClient); + + waitForIdle(); + verify(nextClient).start(any()); + + // finish first operation + mScheduler.getInternalCallback().onClientFinished(nextClient, true /* success */); + waitForIdle(); + + // schedule second operation but swap out the current operation + // before it runs so that it's not current when it's completion callback runs + nextClient = mock(BaseClientMonitor.class); + when(nextClient.getTargetUserId()).thenReturn(11); + mUserStartedCallback.mAfterStart = () -> mScheduler.mCurrentOperation = null; + mShouldFailStopUser = true; + mScheduler.scheduleClientMonitor(nextClient); + + waitForIdle(); + assertThat(mUserStartedCallback.mStartedUsers).containsExactly(10, 11).inOrder(); + assertThat(mUserStoppedCallback.mNumInvocations).isEqualTo(0); + assertThat(mScheduler.getStopUserClient()).isEqualTo(null); + } + private void waitForIdle() { TestableLooper.get(this).processAllMessages(); } @@ -268,13 +304,19 @@ public class UserAwareBiometricSchedulerTest { } } - private static class TestStopUserClient extends StopUserClient<Object> { + private interface StopUserClientShouldFail { + boolean shouldFail(); + } + + private class TestStopUserClient extends StopUserClient<Object> { + private StopUserClientShouldFail mShouldFailClient; public TestStopUserClient(@NonNull Context context, @NonNull Supplier<Object> lazyDaemon, @Nullable IBinder token, int userId, int sensorId, @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext, - @NonNull UserStoppedCallback callback) { + @NonNull UserStoppedCallback callback, StopUserClientShouldFail shouldFail) { super(context, lazyDaemon, token, userId, sensorId, logger, biometricContext, callback); + mShouldFailClient = shouldFail; } @Override @@ -285,7 +327,14 @@ public class UserAwareBiometricSchedulerTest { @Override public void start(@NonNull ClientMonitorCallback callback) { super.start(callback); - onUserStopped(); + if (mShouldFailClient.shouldFail()) { + getCallback().onClientFinished(this, false /* success */); + // When the above fails, it means that the HAL has died, in this case we + // need to ensure the UserSwitchCallback correctly returns the NULL user handle. + mCurrentUserId = UserHandle.USER_NULL; + } else { + onUserStopped(); + } } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java index 1b19a28a9790..28fb0154a3b8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java @@ -37,13 +37,13 @@ import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; -import android.app.IApplicationThread; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -91,9 +91,15 @@ public class RecentsAnimationTest extends WindowTestsBase { TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); Task recentsStack = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */); + final WindowProcessController wpc = mSystemServicesTestRule.addProcess( + mRecentsComponent.getPackageName(), mRecentsComponent.getPackageName(), + // Use real pid/uid of the test so the corresponding process can be mapped by + // Binder.getCallingPid/Uid. + android.os.Process.myPid(), android.os.Process.myUid()); ActivityRecord recentActivity = new ActivityBuilder(mAtm) .setComponent(mRecentsComponent) .setTask(recentsStack) + .setUseProcess(wpc) .build(); ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build(); topActivity.getRootTask().moveToFront("testRecentsActivityVisiblility"); @@ -106,11 +112,14 @@ public class RecentsAnimationTest extends WindowTestsBase { mRecentsComponent, true /* getRecentsAnimation */); // The launch-behind state should make the recents activity visible. assertTrue(recentActivity.mVisibleRequested); + assertEquals(ActivityTaskManagerService.DEMOTE_TOP_REASON_ANIMATING_RECENTS, + mAtm.mDemoteTopAppReasons); // Simulate the animation is cancelled without changing the stack order. recentsAnimation.onAnimationFinished(REORDER_KEEP_IN_PLACE, false /* sendUserLeaveHint */); // The non-top recents activity should be invisible by the restored launch-behind state. assertFalse(recentActivity.mVisibleRequested); + assertEquals(0, mAtm.mDemoteTopAppReasons); } @Test @@ -138,11 +147,8 @@ public class RecentsAnimationTest extends WindowTestsBase { anyInt() /* startFlags */, any() /* profilerInfo */); // Assume its process is alive because the caller should be the recents service. - WindowProcessController wpc = new WindowProcessController(mAtm, aInfo.applicationInfo, - aInfo.processName, aInfo.applicationInfo.uid, 0 /* userId */, - mock(Object.class) /* owner */, mock(WindowProcessListener.class)); - wpc.setThread(mock(IApplicationThread.class)); - doReturn(wpc).when(mAtm).getProcessController(eq(wpc.mName), eq(wpc.mUid)); + mSystemServicesTestRule.addProcess(aInfo.packageName, aInfo.processName, 12345 /* pid */, + aInfo.applicationInfo.uid); Intent recentsIntent = new Intent().setComponent(mRecentsComponent); // Null animation indicates to preload. diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index dc9a62554fdb..258625c751a3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -43,12 +43,14 @@ import static org.mockito.Mockito.withSettings; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; +import android.app.IApplicationThread; import android.app.usage.UsageStatsManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManagerInternal; import android.database.ContentObserver; @@ -454,8 +456,32 @@ public class SystemServicesTestRule implements TestRule { .spiedInstance(sWakeLock).stubOnly()); } - void setSurfaceFactory(Supplier<Surface> factory) { - mSurfaceFactory = factory; + WindowProcessController addProcess(String pkgName, String procName, int pid, int uid) { + return addProcess(mAtmService, pkgName, procName, pid, uid); + } + + static WindowProcessController addProcess(ActivityTaskManagerService atmService, String pkgName, + String procName, int pid, int uid) { + final ApplicationInfo info = new ApplicationInfo(); + info.uid = uid; + info.packageName = pkgName; + return addProcess(atmService, info, procName, pid); + } + + static WindowProcessController addProcess(ActivityTaskManagerService atmService, + ApplicationInfo info, String procName, int pid) { + final WindowProcessListener mockListener = mock(WindowProcessListener.class, + withSettings().stubOnly()); + final int uid = info.uid; + final WindowProcessController proc = new WindowProcessController(atmService, + info, procName, uid, UserHandle.getUserId(uid), mockListener, mockListener); + proc.setThread(mock(IApplicationThread.class, withSettings().stubOnly())); + atmService.mProcessNames.put(procName, uid, proc); + if (pid > 0) { + proc.setPid(pid); + atmService.mProcessMap.put(pid, proc); + } + return proc; } void cleanupWindowManagerHandlers() { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 20fbda428381..7347f8825ff7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -64,7 +64,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions; -import android.app.IApplicationThread; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -915,13 +914,15 @@ class WindowTestsBase extends SystemServiceTestsBase { */ protected static class ActivityBuilder { static final int DEFAULT_FAKE_UID = 12345; + static final String DEFAULT_PROCESS_NAME = "procName"; + static int sProcNameSeq; private final ActivityTaskManagerService mService; private ComponentName mComponent; private String mTargetActivity; private Task mTask; - private String mProcessName = "name"; + private String mProcessName = DEFAULT_PROCESS_NAME; private String mAffinity; private int mUid = DEFAULT_FAKE_UID; private boolean mCreateTask = false; @@ -1109,6 +1110,9 @@ class WindowTestsBase extends SystemServiceTestsBase { aInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; aInfo.applicationInfo.packageName = mComponent.getPackageName(); aInfo.applicationInfo.uid = mUid; + if (DEFAULT_PROCESS_NAME.equals(mProcessName)) { + mProcessName += ++sProcNameSeq; + } aInfo.processName = mProcessName; aInfo.packageName = mComponent.getPackageName(); aInfo.name = mComponent.getClassName(); @@ -1173,16 +1177,11 @@ class WindowTestsBase extends SystemServiceTestsBase { if (mWpc != null) { wpc = mWpc; } else { - wpc = new WindowProcessController(mService, - aInfo.applicationInfo, mProcessName, mUid, - UserHandle.getUserId(mUid), mock(Object.class), - mock(WindowProcessListener.class)); - wpc.setThread(mock(IApplicationThread.class)); + final WindowProcessController p = mService.getProcessController(mProcessName, mUid); + wpc = p != null ? p : SystemServicesTestRule.addProcess( + mService, aInfo.applicationInfo, mProcessName, 0 /* pid */); } - wpc.setThread(mock(IApplicationThread.class)); activity.setProcess(wpc); - doReturn(wpc).when(mService).getProcessController( - activity.processName, activity.info.applicationInfo.uid); // Resume top activities to make sure all other signals in the system are connected. mService.mRootWindowContainer.resumeFocusedTasksTopActivities(); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 434663bd8167..42d446d058b4 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -46,9 +46,11 @@ import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPH import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED_FROM_RESTART; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECT_UNEXPECTED_CALLBACK; +import static com.android.server.voiceinteraction.SoundTriggerSessionPermissionsDecorator.enforcePermissionForPreflight; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.AppOpsManager; import android.content.ComponentName; import android.content.ContentCaptureOptions; import android.content.Context; @@ -1160,12 +1162,11 @@ final class HotwordDetectionConnection { // TODO: Share this code with SoundTriggerMiddlewarePermission. private void enforcePermissionsForDataDelivery() { Binder.withCleanCallingIdentity(() -> { - // Hack to make sure we show the mic privacy-indicator since the Trusted Hotword - // requirement isn't being enforced for now. Normally, we would note the HOTWORD op here - // instead. - enforcePermissionForDataDelivery(mContext, mVoiceInteractorIdentity, - RECORD_AUDIO, OP_MESSAGE); - + enforcePermissionForPreflight(mContext, mVoiceInteractorIdentity, RECORD_AUDIO); + int hotwordOp = AppOpsManager.strOpToOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD); + mContext.getSystemService(AppOpsManager.class).noteOpNoThrow(hotwordOp, + mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, + mVoiceInteractorIdentity.attributionTag, OP_MESSAGE); enforcePermissionForDataDelivery(mContext, mVoiceInteractorIdentity, CAPTURE_AUDIO_HOTWORD, OP_MESSAGE); }); diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java index 5f7cfd109ec9..23835a7732cf 100644 --- a/telephony/java/android/telephony/DataFailCause.java +++ b/telephony/java/android/telephony/DataFailCause.java @@ -125,6 +125,12 @@ public final class DataFailCause { public static final int UNSUPPORTED_QCI_VALUE = 0x3B; /** Procedure requested by the UE was rejected because the bearer handling is not supported. */ public static final int BEARER_HANDLING_NOT_SUPPORTED = 0x3C; + /** + * This cause is used to report a service or option not available event only when no other + * cause in the service or option not available class applies. + * @hide // TODO: Unhide in U. + */ + public static final int SERVICE_OR_OPTION_NOT_AVAILABLE = 0x3F; /** Max number of Packet Data Protocol (PDP) context reached. */ public static final int ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED = 0x41; /** Unsupported APN in current public land mobile network (PLMN). */ @@ -1142,6 +1148,7 @@ public final class DataFailCause { sFailCauseMap.put(ONLY_NON_IP_ALLOWED, "ONLY_NON_IP_ALLOWED"); sFailCauseMap.put(UNSUPPORTED_QCI_VALUE, "UNSUPPORTED_QCI_VALUE"); sFailCauseMap.put(BEARER_HANDLING_NOT_SUPPORTED, "BEARER_HANDLING_NOT_SUPPORTED"); + sFailCauseMap.put(SERVICE_OR_OPTION_NOT_AVAILABLE, "SERVICE_OR_OPTION_NOT_AVAILABLE"); sFailCauseMap.put(ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED, "ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED"); sFailCauseMap.put(UNSUPPORTED_APN_IN_CURRENT_PLMN, |