diff options
283 files changed, 6223 insertions, 2651 deletions
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 13fc2e6977ea..3c0a724b9ff7 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -511,10 +511,26 @@ public class StatusBarManager { @SystemApi public static final int MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER = 1; + /** + * State indicating that media transfer to this receiver device is succeeded. + * + * @hide + */ + public static final int MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED = 2; + + /** + * State indicating that media transfer to this receiver device is failed. + * + * @hide + */ + public static final int MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_FAILED = 3; + /** @hide */ @IntDef(prefix = {"MEDIA_TRANSFER_RECEIVER_STATE_"}, value = { MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER, MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER, + MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, + MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_FAILED, }) @Retention(RetentionPolicy.SOURCE) public @interface MediaTransferReceiverState {} diff --git a/core/java/android/service/voice/HotwordAudioStream.java b/core/java/android/service/voice/HotwordAudioStream.java index 5442860df007..1dceb7a08c13 100644 --- a/core/java/android/service/voice/HotwordAudioStream.java +++ b/core/java/android/service/voice/HotwordAudioStream.java @@ -37,6 +37,21 @@ import java.util.Objects; public final class HotwordAudioStream implements Parcelable { /** + * Key for int value to be read from {@link #getMetadata()}. The value is read by the system and + * is the length (in bytes) of the byte buffers created to copy bytes in the + * {@link #getAudioStreamParcelFileDescriptor()} written by the {@link HotwordDetectionService}. + * The buffer length should be chosen such that no additional latency is introduced. Typically, + * this should be <em>at least</em> the size of byte chunks written by the + * {@link HotwordDetectionService}. + * + * <p>If no value specified in the metadata for the buffer length, or if the value is less than + * 1, or if it is greater than 65,536, or if it is not an int, the default value of 2,560 will + * be used.</p> + */ + public static final String KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES = + "android.service.voice.key.AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES"; + + /** * The {@link AudioFormat} of the audio stream. */ @NonNull diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 550bf348d1c7..af070238787f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3808,44 +3808,7 @@ public final class ViewRootImpl implements ViewParent, } if (mAdded) { - profileRendering(hasWindowFocus); - if (hasWindowFocus) { - if (mAttachInfo.mThreadedRenderer != null && mSurface.isValid()) { - mFullRedrawNeeded = true; - try { - final Rect surfaceInsets = mWindowAttributes.surfaceInsets; - mAttachInfo.mThreadedRenderer.initializeIfNeeded( - mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets); - } catch (OutOfResourcesException e) { - Log.e(mTag, "OutOfResourcesException locking surface", e); - try { - if (!mWindowSession.outOfMemory(mWindow)) { - Slog.w(mTag, "No processes killed for memory;" - + " killing self"); - Process.killProcess(Process.myPid()); - } - } catch (RemoteException ex) { - } - // Retry in a bit. - mHandler.sendMessageDelayed(mHandler.obtainMessage( - MSG_WINDOW_FOCUS_CHANGED), 500); - return; - } - } - } - - mAttachInfo.mHasWindowFocus = hasWindowFocus; - mImeFocusController.updateImeFocusable(mWindowAttributes, true /* force */); - mImeFocusController.onPreWindowFocus(hasWindowFocus, mWindowAttributes); - - if (mView != null) { - mAttachInfo.mKeyDispatchState.reset(); - mView.dispatchWindowFocusChanged(hasWindowFocus); - mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus); - if (mAttachInfo.mTooltipHost != null) { - mAttachInfo.mTooltipHost.hideTooltip(); - } - } + dispatchFocusEvent(hasWindowFocus); // Note: must be done after the focus change callbacks, // so all of the view state is set up correctly. @@ -3881,6 +3844,45 @@ public final class ViewRootImpl implements ViewParent, } } + private void dispatchFocusEvent(boolean hasWindowFocus) { + profileRendering(hasWindowFocus); + if (hasWindowFocus && mAttachInfo.mThreadedRenderer != null && mSurface.isValid()) { + mFullRedrawNeeded = true; + try { + final Rect surfaceInsets = mWindowAttributes.surfaceInsets; + mAttachInfo.mThreadedRenderer.initializeIfNeeded( + mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets); + } catch (OutOfResourcesException e) { + Log.e(mTag, "OutOfResourcesException locking surface", e); + try { + if (!mWindowSession.outOfMemory(mWindow)) { + Slog.w(mTag, "No processes killed for memory;" + + " killing self"); + Process.killProcess(Process.myPid()); + } + } catch (RemoteException ex) { + } + // Retry in a bit. + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MSG_WINDOW_FOCUS_CHANGED), 500); + return; + } + } + + mAttachInfo.mHasWindowFocus = hasWindowFocus; + mImeFocusController.updateImeFocusable(mWindowAttributes, true /* force */); + mImeFocusController.onPreWindowFocus(hasWindowFocus, mWindowAttributes); + + if (mView != null) { + mAttachInfo.mKeyDispatchState.reset(); + mView.dispatchWindowFocusChanged(hasWindowFocus); + mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus); + if (mAttachInfo.mTooltipHost != null) { + mAttachInfo.mTooltipHost.hideTooltip(); + } + } + } + private void handleWindowTouchModeChanged() { final boolean inTouchMode; synchronized (this) { diff --git a/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl b/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl index 6e409885fa13..46f78e2ee8a2 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl @@ -31,6 +31,8 @@ /** * Called when a voice session window is shown/hidden. + * Caution that there could be duplicated visibility change callbacks, it's up to the listener + * to dedup those events. */ void onVoiceSessionWindowVisibilityChanged(boolean visible); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 1235b602cde9..2dfe89397ea5 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -1522,7 +1522,8 @@ public class LockPatternUtils { STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN, - STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT}) + STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT, + SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED}) @Retention(RetentionPolicy.SOURCE) public @interface StrongAuthFlags {} @@ -1575,11 +1576,18 @@ public class LockPatternUtils { public static final int STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT = 0x80; /** + * Some authentication is required because the trustagent either timed out or was disabled + * manually. + */ + public static final int SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED = 0x100; + + /** * Strong auth flags that do not prevent biometric methods from being accepted as auth. * If any other flags are set, biometric authentication is disabled. */ private static final int ALLOWING_BIOMETRIC = STRONG_AUTH_NOT_REQUIRED - | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; + | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST + | SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED; private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray(); private final H mHandler; diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 9508a95340d0..1934d6e8208e 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1167,8 +1167,8 @@ <string name="no" msgid="5122037903299899715">"Cancel·la"</string> <string name="dialog_alert_title" msgid="651856561974090712">"Atenció"</string> <string name="loading" msgid="3138021523725055037">"S\'està carregant…"</string> - <string name="capital_on" msgid="2770685323900821829">"SÍ"</string> - <string name="capital_off" msgid="7443704171014626777">"NO"</string> + <string name="capital_on" msgid="2770685323900821829">"ACTIVAT"</string> + <string name="capital_off" msgid="7443704171014626777">"DESACTIVAT"</string> <string name="checked" msgid="9179896827054513119">"seleccionat"</string> <string name="not_checked" msgid="7972320087569023342">"no seleccionat"</string> <string name="selected" msgid="6614607926197755875">"seleccionat"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 9d928d20c465..4e5c8f72b0fe 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1167,8 +1167,8 @@ <string name="no" msgid="5122037903299899715">"Cancelar"</string> <string name="dialog_alert_title" msgid="651856561974090712">"Atención"</string> <string name="loading" msgid="3138021523725055037">"Cargando…"</string> - <string name="capital_on" msgid="2770685323900821829">"Sí"</string> - <string name="capital_off" msgid="7443704171014626777">"No"</string> + <string name="capital_on" msgid="2770685323900821829">"ACTIVADO"</string> + <string name="capital_off" msgid="7443704171014626777">"Desactivado"</string> <string name="checked" msgid="9179896827054513119">"activado"</string> <string name="not_checked" msgid="7972320087569023342">"desactivado"</string> <string name="selected" msgid="6614607926197755875">"seleccionado"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index d7d87df02a0b..e60a96e3a4b7 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -565,12 +565,12 @@ <string name="permdesc_manageFingerprint" msgid="2025616816437339865">"Aztarna digitalaren txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei."</string> <string name="permlab_useFingerprint" msgid="1001421069766751922">"erabili hatz-marken hardwarea"</string> <string name="permdesc_useFingerprint" msgid="412463055059323742">"Autentifikatzeko hatz-marken hardwarea erabiltzeko baimena ematen die aplikazioei."</string> - <string name="permlab_audioWrite" msgid="8501705294265669405">"musika-bilduma aldatu"</string> - <string name="permdesc_audioWrite" msgid="8057399517013412431">"Musika-bilduma aldatzeko baimena ematen die aplikazioei."</string> - <string name="permlab_videoWrite" msgid="5940738769586451318">"bideo-bilduma aldatu"</string> - <string name="permdesc_videoWrite" msgid="6124731210613317051">"Bideo-bilduma aldatzeko baimena ematen die aplikazioei."</string> - <string name="permlab_imagesWrite" msgid="1774555086984985578">"argazki-bilduma aldatu"</string> - <string name="permdesc_imagesWrite" msgid="5195054463269193317">"Argazki-bilduma aldatzeko baimena ematen die aplikazioei."</string> + <string name="permlab_audioWrite" msgid="8501705294265669405">"musika bilduma aldatu"</string> + <string name="permdesc_audioWrite" msgid="8057399517013412431">"Musika bilduma aldatzeko baimena ematen die aplikazioei."</string> + <string name="permlab_videoWrite" msgid="5940738769586451318">"bideo bilduma aldatu"</string> + <string name="permdesc_videoWrite" msgid="6124731210613317051">"Bideo bilduma aldatzeko baimena ematen die aplikazioei."</string> + <string name="permlab_imagesWrite" msgid="1774555086984985578">"argazki bilduma aldatu"</string> + <string name="permdesc_imagesWrite" msgid="5195054463269193317">"Argazki bilduma aldatzeko baimena ematen die aplikazioei."</string> <string name="permlab_mediaLocation" msgid="7368098373378598066">"multimedia-edukien bildumako kokapena irakurri"</string> <string name="permdesc_mediaLocation" msgid="597912899423578138">"Multimedia-edukien bildumako kokapena irakurtzeko baimena ematen die aplikazioei."</string> <string name="biometric_app_setting_name" msgid="3339209978734534457">"Erabili sistema biometrikoak"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 04cca86e6076..c2a84607706d 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1167,8 +1167,8 @@ <string name="no" msgid="5122037903299899715">"Annuler"</string> <string name="dialog_alert_title" msgid="651856561974090712">"Attention"</string> <string name="loading" msgid="3138021523725055037">"Chargement…"</string> - <string name="capital_on" msgid="2770685323900821829">"OUI"</string> - <string name="capital_off" msgid="7443704171014626777">"NON"</string> + <string name="capital_on" msgid="2770685323900821829">"ACTIVÉ"</string> + <string name="capital_off" msgid="7443704171014626777">"DÉSACTIVÉ"</string> <string name="checked" msgid="9179896827054513119">"activé"</string> <string name="not_checked" msgid="7972320087569023342">"désactivé"</string> <string name="selected" msgid="6614607926197755875">"sélectionné"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index ec39ba2d7a0b..30426c9b34f2 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1487,7 +1487,7 @@ <string name="accessibility_binding_label" msgid="1974602776545801715">"נגישות"</string> <string name="wallpaper_binding_label" msgid="1197440498000786738">"טפט"</string> <string name="chooser_wallpaper" msgid="3082405680079923708">"שינוי טפט"</string> - <string name="notification_listener_binding_label" msgid="2702165274471499713">"מאזין להתראות"</string> + <string name="notification_listener_binding_label" msgid="2702165274471499713">"האזנה להתראות"</string> <string name="vr_listener_binding_label" msgid="8013112996671206429">"VR ליסנר"</string> <string name="condition_provider_service_binding_label" msgid="8490641013951857673">"ספק תנאי"</string> <string name="notification_ranker_binding_label" msgid="432708245635563763">"שירות של דירוג התראות"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 83efe7194a70..12015ec6d85f 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1486,7 +1486,7 @@ <string name="accessibility_binding_label" msgid="1974602776545801715">"Tillgänglighet"</string> <string name="wallpaper_binding_label" msgid="1197440498000786738">"Bakgrund"</string> <string name="chooser_wallpaper" msgid="3082405680079923708">"Ändra bakgrund"</string> - <string name="notification_listener_binding_label" msgid="2702165274471499713">"Meddelandelyssnare"</string> + <string name="notification_listener_binding_label" msgid="2702165274471499713">"Aviseringslyssnare"</string> <string name="vr_listener_binding_label" msgid="8013112996671206429">"Lyssnare för VR"</string> <string name="condition_provider_service_binding_label" msgid="8490641013951857673">"Leverantör"</string> <string name="notification_ranker_binding_label" msgid="432708245635563763">"Rankningstjänst för aviseringar"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 8db018d6db0c..cc4d15e339dd 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -652,9 +652,9 @@ <string name="face_acquired_recalibrate" msgid="8724013080976469746">"請重新註冊面孔。"</string> <string name="face_acquired_too_different" msgid="2520389515612972889">"無法辨識面孔,請再試一次。"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"請稍為轉換頭部的位置"</string> - <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"請正面望向手機"</string> - <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"請正面望向手機"</string> - <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"請正面望向手機"</string> + <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"正面望向手機"</string> + <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"正面望向手機"</string> + <string name="face_acquired_roll_too_extreme" msgid="8261939882838881194">"正面望向手機"</string> <string name="face_acquired_obscured" msgid="4917643294953326639">"移開遮住面孔的任何物件。"</string> <string name="face_acquired_sensor_dirty" msgid="8968391891086721678">"請清理螢幕頂部,包括黑色列"</string> <!-- no translation found for face_acquired_dark_glasses_detected (5643703296620631986) --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 18c29d196ada..22f42980d858 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4789,11 +4789,11 @@ <integer name="config_defaultPeakRefreshRate">0</integer> <!-- The display uses different gamma curves for different refresh rates. It's hard for panel - vendor to tune the curves to have exact same brightness for different refresh rate. So + vendors to tune the curves to have exact same brightness for different refresh rate. So flicker could be observed at switch time. The issue is worse at the gamma lower end. In addition, human eyes are more sensitive to the flicker at darker environment. To prevent flicker, we only support higher refresh rates if the display brightness is above - a threshold. And the darker environment could have higher threshold. + a threshold. For example, no higher refresh rate if display brightness <= disp0 && ambient brightness <= amb0 || display brightness <= disp1 && ambient brightness <= amb1 --> @@ -4815,13 +4815,12 @@ <integer name="config_defaultRefreshRateInZone">0</integer> <!-- The display uses different gamma curves for different refresh rates. It's hard for panel - vendor to tune the curves to have exact same brightness for different refresh rate. So + vendors to tune the curves to have exact same brightness for different refresh rate. So flicker could be observed at switch time. The issue can be observed on the screen with even full white content at the high brightness. To prevent flickering, we support fixed refresh rates if the display and ambient brightness are equal to or above the provided thresholds. You can define multiple threshold levels as higher brightness environments - may have lower display brightness requirements for the flickering is visible. And the - high brightness environment could have higher threshold. + may have lower display brightness requirements for the flickering is visible. For example, fixed refresh rate if display brightness >= disp0 && ambient brightness >= amb0 || display brightness >= disp1 && ambient brightness >= amb1 --> @@ -5300,6 +5299,10 @@ <!-- Whether using split screen aspect ratio as a default aspect ratio for unresizable apps. --> <bool name="config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled">false</bool> + <!-- Whether the specific behaviour for translucent activities letterboxing is enabled. + TODO(b/255532890) Enable when ignoreOrientationRequest is set --> + <bool name="config_letterboxIsEnabledForTranslucentActivities">false</bool> + <!-- Whether a camera compat controller is enabled to allow the user to apply or revert treatment for stretched issues in camera viewfinder. --> <bool name="config_isCameraCompatControlForStretchedIssuesEnabled">false</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b9259218c2d3..b0f6ae6085e3 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4401,6 +4401,9 @@ <!-- Set to true to make assistant show in front of the dream/screensaver. --> <java-symbol type="bool" name="config_assistantOnTopOfDream"/> + <!-- Set to true to enable letterboxing on translucent activities. --> + <java-symbol type="bool" name="config_letterboxIsEnabledForTranslucentActivities" /> + <java-symbol type="string" name="config_overrideComponentUiPackage" /> <java-symbol type="string" name="notification_channel_network_status" /> diff --git a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java index 4679a9ea6f66..0b7019995acb 100644 --- a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java +++ b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java @@ -19,6 +19,9 @@ package com.android.internal.util; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertFalse; @@ -37,6 +40,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.pm.UserInfo; +import android.os.Looper; import android.os.RemoteException; import android.os.UserManager; import android.provider.Settings; @@ -233,6 +237,45 @@ public class LockPatternUtilsTest { ComponentName.unflattenFromString("com.test/.TestAgent")); } + @Test + public void isBiometricAllowedForUser_afterTrustagentExpired_returnsTrue() + throws RemoteException { + TestStrongAuthTracker tracker = createStrongAuthTracker(); + tracker.changeStrongAuth(SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED); + + assertTrue(tracker.isBiometricAllowedForUser( + /* isStrongBiometric = */ true, + DEMO_USER_ID)); + } + + @Test + public void isBiometricAllowedForUser_afterLockout_returnsFalse() + throws RemoteException { + TestStrongAuthTracker tracker = createStrongAuthTracker(); + tracker.changeStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT); + + assertFalse(tracker.isBiometricAllowedForUser( + /* isStrongBiometric = */ true, + DEMO_USER_ID)); + } + + + private TestStrongAuthTracker createStrongAuthTracker() { + final Context context = new ContextWrapper(InstrumentationRegistry.getTargetContext()); + return new TestStrongAuthTracker(context, Looper.getMainLooper()); + } + + private static class TestStrongAuthTracker extends LockPatternUtils.StrongAuthTracker { + + TestStrongAuthTracker(Context context, Looper looper) { + super(context, looper); + } + + public void changeStrongAuth(@StrongAuthFlags int strongAuthFlags) { + handleStrongAuthRequiredChanged(strongAuthFlags, DEMO_USER_ID); + } + } + private ILockSettings createTestLockSettings() { final Context context = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); mLockPatternUtils = spy(new LockPatternUtils(context)); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java index 7e9c4189dabb..fb0a9db6a20b 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java @@ -41,7 +41,7 @@ public class WindowExtensionsImpl implements WindowExtensions { // TODO(b/241126279) Introduce constants to better version functionality @Override public int getVendorApiLevel() { - return 2; + return 1; } /** diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index 9229fc2ae1e1..bed39fb77400 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -33,8 +33,7 @@ <string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"दिखाएं"</string> <string name="dock_forced_resizable" msgid="1749750436092293116">"ऐप्लिकेशन शायद स्प्लिट स्क्रीन मोड में काम न करे."</string> <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"ऐप विभाजित स्क्रीन का समर्थन नहीं करता है."</string> - <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) --> - <skip /> + <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"इस ऐप्लिकेशन को सिर्फ़ एक विंडो में खोला जा सकता है."</string> <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"हो सकता है कि ऐप प्राइमरी (मुख्य) डिस्प्ले के अलावा बाकी दूसरे डिस्प्ले पर काम न करे."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"प्राइमरी (मुख्य) डिस्प्ले के अलावा बाकी दूसरे डिस्प्ले पर ऐप लॉन्च नहीं किया जा सकता."</string> <string name="accessibility_divider" msgid="703810061635792791">"विभाजित स्क्रीन विभाजक"</string> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java index 214b304df07c..c63419851f7f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java @@ -403,5 +403,10 @@ public class DividerView extends FrameLayout implements View.OnTouchListener { } return true; } + + @Override + public boolean onDoubleTapEvent(@NonNull MotionEvent e) { + return true; + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java index c836b95ffab8..a9d3c9f154cd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java @@ -74,7 +74,8 @@ public class SplitDecorManager extends WindowlessWindowManager { private boolean mShown; private boolean mIsResizing; - private final Rect mBounds = new Rect(); + private final Rect mOldBounds = new Rect(); + private final Rect mResizingBounds = new Rect(); private final Rect mTempRect = new Rect(); private ValueAnimator mFadeAnimator; @@ -158,6 +159,8 @@ public class SplitDecorManager extends WindowlessWindowManager { mResizingIconView = null; mIsResizing = false; mShown = false; + mOldBounds.setEmpty(); + mResizingBounds.setEmpty(); } /** Showing resizing hint. */ @@ -170,13 +173,14 @@ public class SplitDecorManager extends WindowlessWindowManager { if (!mIsResizing) { mIsResizing = true; - mBounds.set(newBounds); + mOldBounds.set(newBounds); } + mResizingBounds.set(newBounds); mOffsetX = offsetX; mOffsetY = offsetY; final boolean show = - newBounds.width() > mBounds.width() || newBounds.height() > mBounds.height(); + newBounds.width() > mOldBounds.width() || newBounds.height() > mOldBounds.height(); final boolean update = show != mShown; if (update && mFadeAnimator != null && mFadeAnimator.isRunning()) { // If we need to animate and animator still running, cancel it before we ensure both @@ -193,8 +197,8 @@ public class SplitDecorManager extends WindowlessWindowManager { if (mGapBackgroundLeash == null && !immediately) { final boolean isLandscape = newBounds.height() == sideBounds.height(); - final int left = isLandscape ? mBounds.width() : 0; - final int top = isLandscape ? 0 : mBounds.height(); + final int left = isLandscape ? mOldBounds.width() : 0; + final int top = isLandscape ? 0 : mOldBounds.height(); mGapBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash, GAP_BACKGROUND_SURFACE_NAME, mSurfaceSession); // Fill up another side bounds area. @@ -272,6 +276,8 @@ public class SplitDecorManager extends WindowlessWindowManager { mIsResizing = false; mOffsetX = 0; mOffsetY = 0; + mOldBounds.setEmpty(); + mResizingBounds.setEmpty(); if (mFadeAnimator != null && mFadeAnimator.isRunning()) { if (!mShown) { // If fade-out animation is running, just add release callback to it. @@ -303,8 +309,8 @@ public class SplitDecorManager extends WindowlessWindowManager { /** Screenshot host leash and attach on it if meet some conditions */ public void screenshotIfNeeded(SurfaceControl.Transaction t) { - if (!mShown && mIsResizing) { - mTempRect.set(mBounds); + if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) { + mTempRect.set(mOldBounds); mTempRect.offsetTo(0, 0); mScreenshot = ScreenshotUtils.takeScreenshot(t, mHostLeash, mTempRect, Integer.MAX_VALUE - 1); @@ -315,7 +321,7 @@ public class SplitDecorManager extends WindowlessWindowManager { public void setScreenshotIfNeeded(SurfaceControl screenshot, SurfaceControl.Transaction t) { if (screenshot == null || !screenshot.isValid()) return; - if (!mShown && mIsResizing) { + if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) { mScreenshot = screenshot; t.reparent(screenshot, mHostLeash); t.setLayer(screenshot, Integer.MAX_VALUE - 1); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java index 62bf5172e106..d93a9012c8f1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java @@ -240,7 +240,7 @@ public class DragAndDropPolicy { // Update launch options for the split side we are targeting. position = leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT; // Add some data for logging splitscreen once it is invoked - mSplitScreen.logOnDroppedToSplit(position, mLoggerSessionId); + mSplitScreen.onDroppedToSplit(position, mLoggerSessionId); } final ClipDescription description = data.getDescription(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java index e7ec15e70c11..89538cb394d4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java @@ -16,9 +16,6 @@ package com.android.wm.shell.splitscreen; -import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; -import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES; - import android.content.Context; import android.view.SurfaceSession; import android.window.WindowContainerToken; @@ -34,8 +31,6 @@ import com.android.wm.shell.common.SyncTransactionQueue; * @see StageCoordinator */ class MainStage extends StageTaskListener { - private static final String TAG = MainStage.class.getSimpleName(); - private boolean mIsActive = false; MainStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId, @@ -52,15 +47,8 @@ class MainStage extends StageTaskListener { void activate(WindowContainerTransaction wct, boolean includingTopTask) { if (mIsActive) return; - final WindowContainerToken rootToken = mRootTaskInfo.token; if (includingTopTask) { - wct.reparentTasks( - null /* currentParent */, - rootToken, - CONTROLLED_WINDOWING_MODES, - CONTROLLED_ACTIVITY_TYPES, - true /* onTop */, - true /* reparentTopOnly */); + reparentTopTask(wct); } mIsActive = true; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index b26bc9cd7f9c..ef70d9bd84ee 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -121,7 +121,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, public static final int EXIT_REASON_SCREEN_LOCKED = 7; public static final int EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP = 8; public static final int EXIT_REASON_CHILD_TASK_ENTER_PIP = 9; - public static final int EXIT_REASON_FULLSCREEN_SHORTCUT = 10; + public static final int EXIT_REASON_RECREATE_SPLIT = 10; + public static final int EXIT_REASON_FULLSCREEN_SHORTCUT = 11; @IntDef(value = { EXIT_REASON_UNKNOWN, EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW, @@ -133,6 +134,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, EXIT_REASON_SCREEN_LOCKED, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP, EXIT_REASON_CHILD_TASK_ENTER_PIP, + EXIT_REASON_RECREATE_SPLIT, EXIT_REASON_FULLSCREEN_SHORTCUT, }) @Retention(RetentionPolicy.SOURCE) @@ -470,7 +472,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, */ public void startShortcut(String packageName, String shortcutId, @SplitPosition int position, @Nullable Bundle options, UserHandle user, @NonNull InstanceId instanceId) { - mStageCoordinator.getLogger().enterRequested(instanceId, ENTER_REASON_LAUNCHER); + mStageCoordinator.onRequestToSplit(instanceId, ENTER_REASON_LAUNCHER); startShortcut(packageName, shortcutId, position, options, user); } @@ -518,7 +520,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, */ public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options, @NonNull InstanceId instanceId) { - mStageCoordinator.getLogger().enterRequested(instanceId, ENTER_REASON_LAUNCHER); + mStageCoordinator.onRequestToSplit(instanceId, ENTER_REASON_LAUNCHER); startIntent(intent, fillInIntent, position, options); } @@ -784,10 +786,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, return splitTasksLayer; } /** - * Sets drag info to be logged when splitscreen is entered. + * Drop callback when splitscreen is entered. */ - public void logOnDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) { - mStageCoordinator.logOnDroppedToSplit(position, dragSessionId); + public void onDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) { + mStageCoordinator.onDroppedToSplit(position, dragSessionId); } /** @@ -815,6 +817,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, return "APP_DOES_NOT_SUPPORT_MULTIWINDOW"; case EXIT_REASON_CHILD_TASK_ENTER_PIP: return "CHILD_TASK_ENTER_PIP"; + case EXIT_REASON_RECREATE_SPLIT: + return "RECREATE_SPLIT"; default: return "unknown reason, reason int = " + exitReason; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java index 1016e1bcd66f..5483fa5d29f6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java @@ -21,9 +21,11 @@ import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED_ import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__UNKNOWN_ENTER; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED; +import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__CHILD_TASK_ENTER_PIP; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT; +import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED; @@ -37,9 +39,11 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASO import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_UNKNOWN; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED; +import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT; +import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RECREATE_SPLIT; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ROOT_TASK_VANISHED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED; @@ -182,6 +186,10 @@ public class SplitscreenEventLogger { return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED; case EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP: return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP; + case EXIT_REASON_CHILD_TASK_ENTER_PIP: + return SPLITSCREEN_UICHANGED__EXIT_REASON__CHILD_TASK_ENTER_PIP; + case EXIT_REASON_RECREATE_SPLIT: + return SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT; case EXIT_REASON_FULLSCREEN_SHORTCUT: return SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT; case EXIT_REASON_UNKNOWN: diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index da8dc8733ef5..717ae91f74c5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -49,10 +49,11 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASO import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_MULTI_INSTANCE; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED; -import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER; +import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT; +import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RECREATE_SPLIT; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ROOT_TASK_VANISHED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP; @@ -199,7 +200,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // and exit, since exit itself can trigger a number of changes that update the stages. private boolean mShouldUpdateRecents; private boolean mExitSplitScreenOnHide; - private boolean mIsDividerRemoteAnimating; + private boolean mIsSplitEntering; + private boolean mIsDropEntering; private boolean mIsExiting; /** The target stage to dismiss to when unlock after folded. */ @@ -347,10 +349,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mSplitTransitions; } - boolean isSplitScreenVisible() { + public boolean isSplitScreenVisible() { return mSideStageListener.mVisible && mMainStageListener.mVisible; } + public boolean isSplitActive() { + return mMainStage.isActive(); + } + @StageType int getStageOfTask(int taskId) { if (mMainStage.containsTask(taskId)) { @@ -373,11 +379,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, targetStage = mSideStage; sideStagePosition = stagePosition; } else { - if (mMainStage.isActive()) { + if (isSplitScreenVisible()) { // If the split screen is activated, retrieves target stage based on position. targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage; sideStagePosition = mSideStagePosition; } else { + // Exit split if it running background. + exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT); + targetStage = mSideStage; sideStagePosition = stagePosition; } @@ -673,6 +682,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent, @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) { + if (!isSplitScreenVisible()) { + exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT); + } + // Init divider first to make divider leash for remote animation target. mSplitLayout.init(); mSplitLayout.setDivideRatio(splitRatio); @@ -685,11 +698,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Set false to avoid record new bounds with old task still on top; mShouldUpdateRecents = false; - mIsDividerRemoteAnimating = true; + mIsSplitEntering = true; final WindowContainerTransaction evictWct = new WindowContainerTransaction(); - prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct); - prepareEvictChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, evictWct); + if (isSplitScreenVisible()) { + mMainStage.evictAllChildren(evictWct); + mSideStage.evictAllChildren(evictWct); + } IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() { @Override @@ -769,7 +784,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private void onRemoteAnimationFinishedOrCancelled(boolean cancel, WindowContainerTransaction evictWct) { - mIsDividerRemoteAnimating = false; + mIsSplitEntering = false; mShouldUpdateRecents = true; // If any stage has no child after animation finished, it means that split will display // nothing, such status will happen if task and intent is same app but not support @@ -781,6 +796,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitUnsupportedToast.show(); } else { mSyncQueue.queue(evictWct); + mSyncQueue.runInSync(t -> { + updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); + }); } } @@ -815,7 +833,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, switch (stage) { case STAGE_TYPE_UNDEFINED: { if (position != SPLIT_POSITION_UNDEFINED) { - if (mMainStage.isActive()) { + if (isSplitScreenVisible()) { // Use the stage of the specified position options = resolveStartStage( position == mSideStagePosition ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN, @@ -1045,14 +1063,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } }); mShouldUpdateRecents = false; - mIsDividerRemoteAnimating = false; + mIsSplitEntering = false; mSplitLayout.getInvisibleBounds(mTempRect1); if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) { mSideStage.removeAllTasks(wct, false /* toTop */); mMainStage.deactivate(wct, false /* toTop */); wct.reorder(mRootTaskInfo.token, false /* onTop */); - wct.setForceTranslucent(mRootTaskInfo.token, true); wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1); onTransitionAnimationComplete(); } else { @@ -1064,6 +1081,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, wct.setSmallestScreenWidthDp(childrenToTop.mRootTaskInfo.token, SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); } + wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token, + false /* reparentLeafTaskIfRelaunch */); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { t.setWindowCrop(mMainStage.mRootLeash, null) @@ -1082,7 +1101,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mMainStage.deactivate(finishedWCT, childrenToTop == mMainStage /* toTop */); mSideStage.removeAllTasks(finishedWCT, childrenToTop == mSideStage /* toTop */); finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */); - finishedWCT.setForceTranslucent(mRootTaskInfo.token, true); finishedWCT.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1); mSyncQueue.queue(finishedWCT); mSyncQueue.runInSync(at -> { @@ -1374,7 +1392,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, && !ENABLE_SHELL_TRANSITIONS) { // Clear the divider remote animating flag as the divider will be re-rendered to apply // the new rotation config. - mIsDividerRemoteAnimating = false; + mIsSplitEntering = false; mSplitLayout.update(null /* t */); onLayoutSizeChanged(mSplitLayout); } @@ -1423,6 +1441,36 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, }); } + void onChildTaskAppeared(StageListenerImpl stageListener, int taskId) { + if (stageListener == mSideStageListener && !isSplitScreenVisible() && isSplitActive() + && !mIsSplitEntering) { + // Handle entring split case here if split already running background. + if (mIsDropEntering) { + mSplitLayout.resetDividerPosition(); + } else { + mSplitLayout.setDividerAtBorder(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT); + } + final WindowContainerTransaction wct = new WindowContainerTransaction(); + mMainStage.reparentTopTask(wct); + mMainStage.evictAllChildren(wct); + mSideStage.evictOtherChildren(wct, taskId); + updateWindowBounds(mSplitLayout, wct); + wct.reorder(mRootTaskInfo.token, true); + wct.setForceTranslucent(mRootTaskInfo.token, false); + + mSyncQueue.queue(wct); + mSyncQueue.runInSync(t -> { + if (mIsDropEntering) { + updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); + mIsDropEntering = false; + } else { + mShowDecorImmediately = true; + mSplitLayout.flingDividerToCenter(); + } + }); + } + } + private void onRootTaskVanished() { final WindowContainerTransaction wct = new WindowContainerTransaction(); if (mRootTaskInfo != null) { @@ -1441,20 +1489,22 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return; } + final WindowContainerTransaction wct = new WindowContainerTransaction(); if (!mainStageVisible) { + wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token, + true /* setReparentLeafTaskIfRelaunch */); + wct.setForceTranslucent(mRootTaskInfo.token, true); // Both stages are not visible, check if it needs to dismiss split screen. - if (mExitSplitScreenOnHide - // Don't dismiss split screen when both stages are not visible due to sleeping - // display. - || (!mMainStage.mRootTaskInfo.isSleeping - && !mSideStage.mRootTaskInfo.isSleeping)) { + if (mExitSplitScreenOnHide) { exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RETURN_HOME); } + } else { + wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token, + false /* setReparentLeafTaskIfRelaunch */); + wct.setForceTranslucent(mRootTaskInfo.token, false); } - + mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { - t.setVisibility(mSideStage.mRootLeash, sideStageVisible) - .setVisibility(mMainStage.mRootLeash, mainStageVisible); setDividerVisibility(mainStageVisible, t); }); } @@ -1479,7 +1529,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mDividerVisible = visible; sendSplitVisibilityChanged(); - if (mIsDividerRemoteAnimating) { + if (mIsSplitEntering) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, " Skip animating divider bar due to it's remote animating."); return; @@ -1499,7 +1549,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, " Skip animating divider bar due to divider leash not ready."); return; } - if (mIsDividerRemoteAnimating) { + if (mIsSplitEntering) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, " Skip animating divider bar due to it's remote animating."); return; @@ -1555,26 +1605,21 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (!hasChildren && !mIsExiting && mMainStage.isActive()) { if (isSideStage && mMainStageListener.mVisible) { // Exit to main stage if side stage no longer has children. - if (ENABLE_SHELL_TRANSITIONS) { - exitSplitScreen(mMainStage, EXIT_REASON_APP_FINISHED); - } else { - mSplitLayout.flingDividerToDismiss( - mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT, - EXIT_REASON_APP_FINISHED); - } + mSplitLayout.flingDividerToDismiss( + mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT, + EXIT_REASON_APP_FINISHED); } else if (!isSideStage && mSideStageListener.mVisible) { // Exit to side stage if main stage no longer has children. - if (ENABLE_SHELL_TRANSITIONS) { - exitSplitScreen(mSideStage, EXIT_REASON_APP_FINISHED); - } else { - mSplitLayout.flingDividerToDismiss( - mSideStagePosition != SPLIT_POSITION_BOTTOM_OR_RIGHT, - EXIT_REASON_APP_FINISHED); - } + mSplitLayout.flingDividerToDismiss( + mSideStagePosition != SPLIT_POSITION_BOTTOM_OR_RIGHT, + EXIT_REASON_APP_FINISHED); + } else if (!isSplitScreenVisible() && !mIsSplitEntering) { + exitSplitScreen(null /* childrenToTop */, EXIT_REASON_APP_FINISHED); } } else if (isSideStage && hasChildren && !mMainStage.isActive()) { - final WindowContainerTransaction wct = new WindowContainerTransaction(); mSplitLayout.init(); + + final WindowContainerTransaction wct = new WindowContainerTransaction(); if (mLogger.isEnterRequestedByDrag()) { prepareEnterSplitScreen(wct); } else { @@ -1589,8 +1634,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { - if (mLogger.isEnterRequestedByDrag()) { + if (mIsDropEntering) { updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); + mIsDropEntering = false; } else { mShowDecorImmediately = true; mSplitLayout.flingDividerToCenter(); @@ -1945,10 +1991,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } - public boolean isSplitActive() { - return mMainStage.isActive(); - } - @Override public void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t, IBinder mergeTarget, @@ -2304,11 +2346,29 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, /** * Sets drag info to be logged when splitscreen is next entered. */ - public void logOnDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) { + public void onDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) { + if (!isSplitScreenVisible()) { + mIsDropEntering = true; + } + if (!isSplitScreenVisible()) { + // If split running background, exit split first. + exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT); + } mLogger.enterRequestedByDrag(position, dragSessionId); } /** + * Sets info to be logged when splitscreen is next entered. + */ + public void onRequestToSplit(InstanceId sessionId, int enterReason) { + if (!isSplitScreenVisible()) { + // If split running background, exit split first. + exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT); + } + mLogger.enterRequested(sessionId, enterReason); + } + + /** * Logs the exit of splitscreen. */ private void logExit(@ExitReason int exitReason) { @@ -2343,6 +2403,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } @Override + public void onChildTaskAppeared(int taskId) { + StageCoordinator.this.onChildTaskAppeared(this, taskId); + } + + @Override public void onStatusChanged(boolean visible, boolean hasChildren) { if (!mHasRootTask) return; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 8a52c8750ba6..a841b7f96d3c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.RemoteAnimationTarget.MODE_OPENING; import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; +import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES; import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; @@ -69,6 +70,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { public interface StageListenerCallbacks { void onRootTaskAppeared(); + void onChildTaskAppeared(int taskId); + void onStatusChanged(boolean visible, boolean hasChildren); void onChildTaskStatusChanged(int taskId, boolean present, boolean visible); @@ -185,6 +188,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { // Status is managed/synchronized by the transition lifecycle. return; } + mCallbacks.onChildTaskAppeared(taskId); sendStatusChanged(); } else { throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo @@ -338,6 +342,14 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } } + void evictOtherChildren(WindowContainerTransaction wct, int taskId) { + for (int i = mChildrenTaskInfo.size() - 1; i >= 0; i--) { + final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.valueAt(i); + if (taskId == taskInfo.taskId) continue; + wct.reparent(taskInfo.token, null /* parent */, false /* onTop */); + } + } + void evictNonOpeningChildren(RemoteAnimationTarget[] apps, WindowContainerTransaction wct) { final SparseArray<ActivityManager.RunningTaskInfo> toBeEvict = mChildrenTaskInfo.clone(); for (int i = 0; i < apps.length; i++) { @@ -360,6 +372,12 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } } + void reparentTopTask(WindowContainerTransaction wct) { + wct.reparentTasks(null /* currentParent */, mRootTaskInfo.token, + CONTROLLED_WINDOWING_MODES, CONTROLLED_ACTIVITY_TYPES, + true /* onTop */, true /* reparentTopOnly */); + } + void resetBounds(WindowContainerTransaction wct) { wct.setBounds(mRootTaskInfo.token, null); wct.setAppBounds(mRootTaskInfo.token, null); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index 3cba92956f95..a2d7bc43653a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -111,7 +111,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler { @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { - if (mPipHandler.requestHasPipEnter(request) && mSplitHandler.isSplitActive()) { + if (mPipHandler.requestHasPipEnter(request) && mSplitHandler.isSplitScreenVisible()) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a PiP-enter request while " + "Split-Screen is active, so treat it as Mixed."); if (request.getRemoteTransition() != null) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java index afefd5dc6344..42e2b3fadf19 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java @@ -46,6 +46,7 @@ import android.window.WindowContainerTransaction; import androidx.annotation.Nullable; +import com.android.internal.annotations.VisibleForTesting; import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; @@ -56,7 +57,6 @@ import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; import com.android.wm.shell.transition.Transitions; import java.util.Optional; -import java.util.function.Supplier; /** * View model for the window decoration with a caption and shadows. Works with @@ -66,7 +66,6 @@ import java.util.function.Supplier; public class CaptionWindowDecorViewModel implements WindowDecorViewModel { private static final String TAG = "CaptionViewModel"; private final CaptionWindowDecoration.Factory mCaptionWindowDecorFactory; - private final Supplier<InputManager> mInputManagerSupplier; private final ActivityTaskManager mActivityTaskManager; private final ShellTaskOrganizer mTaskOrganizer; private final Context mContext; @@ -82,7 +81,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>(); private final DragStartListenerImpl mDragStartListener = new DragStartListenerImpl(); - private EventReceiverFactory mEventReceiverFactory = new EventReceiverFactory(); + private InputMonitorFactory mInputMonitorFactory; public CaptionWindowDecorViewModel( Context context, @@ -101,10 +100,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { syncQueue, desktopModeController, new CaptionWindowDecoration.Factory(), - InputManager::getInstance); + new InputMonitorFactory()); } - public CaptionWindowDecorViewModel( + @VisibleForTesting + CaptionWindowDecorViewModel( Context context, Handler mainHandler, Choreographer mainChoreographer, @@ -113,8 +113,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { SyncTransactionQueue syncQueue, Optional<DesktopModeController> desktopModeController, CaptionWindowDecoration.Factory captionWindowDecorFactory, - Supplier<InputManager> inputManagerSupplier) { - + InputMonitorFactory inputMonitorFactory) { mContext = context; mMainHandler = mainHandler; mMainChoreographer = mainChoreographer; @@ -125,11 +124,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { mDesktopModeController = desktopModeController; mCaptionWindowDecorFactory = captionWindowDecorFactory; - mInputManagerSupplier = inputManagerSupplier; - } - - void setEventReceiverFactory(EventReceiverFactory eventReceiverFactory) { - mEventReceiverFactory = eventReceiverFactory; + mInputMonitorFactory = inputMonitorFactory; } @Override @@ -205,7 +200,6 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { decoration.close(); int displayId = taskInfo.displayId; if (mEventReceiversByDisplay.contains(displayId)) { - EventReceiver eventReceiver = mEventReceiversByDisplay.get(displayId); removeTaskFromEventReceiver(displayId); } } @@ -408,12 +402,6 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { } } - class EventReceiverFactory { - EventReceiver create(InputMonitor inputMonitor, InputChannel channel, Looper looper) { - return new EventReceiver(inputMonitor, channel, looper); - } - } - /** * Handle MotionEvents relevant to focused task's caption that don't directly touch it * @@ -500,11 +488,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { } private void createInputChannel(int displayId) { - InputManager inputManager = mInputManagerSupplier.get(); + InputManager inputManager = InputManager.getInstance(); InputMonitor inputMonitor = - inputManager.monitorGestureInput("caption-touch", mContext.getDisplayId()); - EventReceiver eventReceiver = mEventReceiverFactory.create( - inputMonitor, inputMonitor.getInputChannel(), Looper.myLooper()); + mInputMonitorFactory.create(inputManager, mContext); + EventReceiver eventReceiver = new EventReceiver(inputMonitor, + inputMonitor.getInputChannel(), Looper.myLooper()); mEventReceiversByDisplay.put(displayId, eventReceiver); } @@ -562,4 +550,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { mWindowDecorByTaskId.get(taskId).closeHandleMenu(); } } + + static class InputMonitorFactory { + InputMonitor create(InputManager inputManager, Context context) { + return inputManager.monitorGestureInput("caption-touch", context.getDisplayId()); + } + } } + + diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index 92154968855f..7f85988d1377 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -33,6 +33,7 @@ import android.view.View; import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.WindowlessWindowManager; +import android.window.TaskConstants; import android.window.WindowContainerTransaction; import com.android.wm.shell.ShellTaskOrganizer; @@ -195,7 +196,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> .setParent(mTaskSurface) .build(); - startT.setTrustedOverlay(mDecorationContainerSurface, true); + startT.setTrustedOverlay(mDecorationContainerSurface, true) + .setLayer(mDecorationContainerSurface, + TaskConstants.TASK_CHILD_LAYER_WINDOW_DECORATIONS); } final Rect taskBounds = taskConfig.windowConfiguration.getBounds(); @@ -213,8 +216,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> outResult.mDecorContainerOffsetX, outResult.mDecorContainerOffsetY) .setWindowCrop(mDecorationContainerSurface, outResult.mWidth, outResult.mHeight) - // TODO(b/244455401): Change the z-order when it's better organized - .setLayer(mDecorationContainerSurface, mTaskInfo.numActivities + 1) .show(mDecorationContainerSurface); // TaskBackgroundSurface @@ -225,6 +226,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> .setEffectLayer() .setParent(mTaskSurface) .build(); + + startT.setLayer(mTaskBackgroundSurface, TaskConstants.TASK_CHILD_LAYER_TASK_BACKGROUND); } float shadowRadius = loadDimension(resources, params.mShadowRadiusId); @@ -236,8 +239,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> taskBounds.height()) .setShadowRadius(mTaskBackgroundSurface, shadowRadius) .setColor(mTaskBackgroundSurface, mTmpColor) - // TODO(b/244455401): Change the z-order when it's better organized - .setLayer(mTaskBackgroundSurface, -1) .show(mTaskBackgroundSurface); // CaptionContainerSurface, CaptionWindowManager diff --git a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml index 59d9104fb5ba..fac04614d945 100644 --- a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml +++ b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml @@ -19,6 +19,8 @@ xmlns:tools="http://schemas.android.com/tools" package="com.android.wm.shell.tests"> + <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> + <application android:debuggable="true" android:largeHeap="true"> <uses-library android:name="android.test.mock" /> <uses-library android:name="android.test.runner" /> diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModelTests.java index ad6fcedd3166..0dbf30d69f75 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModelTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModelTests.java @@ -21,14 +21,15 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; +import android.hardware.display.DisplayManager; +import android.hardware.display.VirtualDisplay; import android.hardware.input.InputManager; import android.os.Handler; import android.os.Looper; @@ -37,9 +38,9 @@ import android.view.Display; import android.view.InputChannel; import android.view.InputMonitor; import android.view.SurfaceControl; +import android.view.SurfaceView; import androidx.test.filters.SmallTest; -import androidx.test.rule.GrantPermissionRule; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; @@ -55,37 +56,28 @@ import org.mockito.Mock; import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.function.Supplier; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** Tests of {@link CaptionWindowDecorViewModel} */ @SmallTest public class CaptionWindowDecorViewModelTests extends ShellTestCase { - @Mock private CaptionWindowDecoration mCaptionWindowDecoration; + private static final String TAG = "CaptionWindowDecorViewModelTests"; + + @Mock private CaptionWindowDecoration mCaptionWindowDecoration; @Mock private CaptionWindowDecoration.Factory mCaptionWindowDecorFactory; @Mock private Handler mMainHandler; - @Mock private Choreographer mMainChoreographer; - @Mock private ShellTaskOrganizer mTaskOrganizer; - @Mock private DisplayController mDisplayController; - @Mock private SyncTransactionQueue mSyncQueue; - @Mock private DesktopModeController mDesktopModeController; - @Mock private InputMonitor mInputMonitor; - - @Mock private InputChannel mInputChannel; - - @Mock private CaptionWindowDecorViewModel.EventReceiverFactory mEventReceiverFactory; - - @Mock private CaptionWindowDecorViewModel.EventReceiver mEventReceiver; - @Mock private InputManager mInputManager; + @Mock private CaptionWindowDecorViewModel.InputMonitorFactory mMockInputMonitorFactory; private final List<InputManager> mMockInputManagers = new ArrayList<>(); private CaptionWindowDecorViewModel mCaptionWindowDecorViewModel; @@ -104,44 +96,46 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase { mSyncQueue, Optional.of(mDesktopModeController), mCaptionWindowDecorFactory, - new MockObjectSupplier<>(mMockInputManagers, () -> mock(InputManager.class))); - mCaptionWindowDecorViewModel.setEventReceiverFactory(mEventReceiverFactory); + mMockInputMonitorFactory + ); doReturn(mCaptionWindowDecoration) .when(mCaptionWindowDecorFactory) .create(any(), any(), any(), any(), any(), any(), any(), any()); - when(mInputManager.monitorGestureInput(any(), anyInt())).thenReturn(mInputMonitor); - when(mEventReceiverFactory.create(any(), any(), any())).thenReturn(mEventReceiver); - when(mInputMonitor.getInputChannel()).thenReturn(mInputChannel); + when(mMockInputMonitorFactory.create(any(), any())).thenReturn(mInputMonitor); + // InputChannel cannot be mocked because it passes to InputEventReceiver. + final InputChannel[] inputChannels = InputChannel.openInputChannelPair(TAG); + inputChannels[0].dispose(); + when(mInputMonitor.getInputChannel()).thenReturn(inputChannels[1]); } @Test public void testDeleteCaptionOnChangeTransitionWhenNecessary() throws Exception { - Looper.prepare(); final int taskId = 1; final ActivityManager.RunningTaskInfo taskInfo = - createTaskInfo(taskId, WINDOWING_MODE_FREEFORM); + createTaskInfo(taskId, Display.DEFAULT_DISPLAY, WINDOWING_MODE_FREEFORM); SurfaceControl surfaceControl = mock(SurfaceControl.class); - final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); - final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); - GrantPermissionRule.grant(android.Manifest.permission.MONITOR_INPUT); + runOnMainThread(() -> { + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + + mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT); - mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT); + taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED); + taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); + mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT); + }); verify(mCaptionWindowDecorFactory) .create( - mContext, - mDisplayController, - mTaskOrganizer, - taskInfo, - surfaceControl, - mMainHandler, - mMainChoreographer, - mSyncQueue); - - taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED); - taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); - mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT); + mContext, + mDisplayController, + mTaskOrganizer, + taskInfo, + surfaceControl, + mMainHandler, + mMainChoreographer, + mSyncQueue); verify(mCaptionWindowDecoration).close(); } @@ -149,70 +143,105 @@ public class CaptionWindowDecorViewModelTests extends ShellTestCase { public void testCreateCaptionOnChangeTransitionWhenNecessary() throws Exception { final int taskId = 1; final ActivityManager.RunningTaskInfo taskInfo = - createTaskInfo(taskId, WINDOWING_MODE_UNDEFINED); + createTaskInfo(taskId, Display.DEFAULT_DISPLAY, WINDOWING_MODE_UNDEFINED); SurfaceControl surfaceControl = mock(SurfaceControl.class); - final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); - final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); - taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); + runOnMainThread(() -> { + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED); + + mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT); - mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT); + taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); + taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD); - verify(mCaptionWindowDecorFactory, never()) + mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT); + }); + verify(mCaptionWindowDecorFactory, times(1)) .create( - mContext, - mDisplayController, - mTaskOrganizer, - taskInfo, - surfaceControl, - mMainHandler, - mMainChoreographer, - mSyncQueue); - - taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); + mContext, + mDisplayController, + mTaskOrganizer, + taskInfo, + surfaceControl, + mMainHandler, + mMainChoreographer, + mSyncQueue); + } + + @Test + public void testCreateAndDisposeEventReceiver() throws Exception { + final int taskId = 1; + final ActivityManager.RunningTaskInfo taskInfo = + createTaskInfo(taskId, Display.DEFAULT_DISPLAY, WINDOWING_MODE_FREEFORM); taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD); + runOnMainThread(() -> { + SurfaceControl surfaceControl = mock(SurfaceControl.class); + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); - mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT); + mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT); - verify(mCaptionWindowDecorFactory) - .create( - mContext, - mDisplayController, - mTaskOrganizer, - taskInfo, - surfaceControl, - mMainHandler, - mMainChoreographer, - mSyncQueue); + mCaptionWindowDecorViewModel.destroyWindowDecoration(taskInfo); + }); + verify(mMockInputMonitorFactory).create(any(), any()); + verify(mInputMonitor).dispose(); } - private static ActivityManager.RunningTaskInfo createTaskInfo(int taskId, int windowingMode) { + @Test + public void testEventReceiversOnMultipleDisplays() throws Exception { + runOnMainThread(() -> { + SurfaceView surfaceView = new SurfaceView(mContext); + final DisplayManager mDm = mContext.getSystemService(DisplayManager.class); + final VirtualDisplay secondaryDisplay = mDm.createVirtualDisplay( + "testEventReceiversOnMultipleDisplays", /*width=*/ 400, /*height=*/ 400, + /*densityDpi=*/ 320, surfaceView.getHolder().getSurface(), + DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY); + int secondaryDisplayId = secondaryDisplay.getDisplay().getDisplayId(); + + final int taskId = 1; + final ActivityManager.RunningTaskInfo taskInfo = + createTaskInfo(taskId, Display.DEFAULT_DISPLAY, WINDOWING_MODE_FREEFORM); + final ActivityManager.RunningTaskInfo secondTaskInfo = + createTaskInfo(taskId + 1, secondaryDisplayId, WINDOWING_MODE_FREEFORM); + final ActivityManager.RunningTaskInfo thirdTaskInfo = + createTaskInfo(taskId + 2, secondaryDisplayId, WINDOWING_MODE_FREEFORM); + + SurfaceControl surfaceControl = mock(SurfaceControl.class); + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + + mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT); + mCaptionWindowDecorViewModel.onTaskOpening(secondTaskInfo, surfaceControl, + startT, finishT); + mCaptionWindowDecorViewModel.onTaskOpening(thirdTaskInfo, surfaceControl, + startT, finishT); + mCaptionWindowDecorViewModel.destroyWindowDecoration(thirdTaskInfo); + mCaptionWindowDecorViewModel.destroyWindowDecoration(taskInfo); + }); + verify(mMockInputMonitorFactory, times(2)).create(any(), any()); + verify(mInputMonitor, times(1)).dispose(); + } + + private void runOnMainThread(Runnable r) throws Exception { + final Handler mainHandler = new Handler(Looper.getMainLooper()); + final CountDownLatch latch = new CountDownLatch(1); + mainHandler.post(() -> { + r.run(); + latch.countDown(); + }); + latch.await(20, TimeUnit.MILLISECONDS); + } + + private static ActivityManager.RunningTaskInfo createTaskInfo(int taskId, + int displayId, int windowingMode) { ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() - .setDisplayId(Display.DEFAULT_DISPLAY) + .setDisplayId(displayId) .setVisible(true) .build(); taskInfo.taskId = taskId; taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode); return taskInfo; } - - private static class MockObjectSupplier<T> implements Supplier<T> { - private final List<T> mObjects; - private final Supplier<T> mDefaultSupplier; - private int mNumOfCalls = 0; - - private MockObjectSupplier(List<T> objects, Supplier<T> defaultSupplier) { - mObjects = objects; - mDefaultSupplier = defaultSupplier; - } - - @Override - public T get() { - final T mock = - mNumOfCalls < mObjects.size() ? mObjects.get(mNumOfCalls) - : mDefaultSupplier.get(); - ++mNumOfCalls; - return mock; - } - } } diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 77b8b4fe09ef..90ff2c695059 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -477,7 +477,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string> - <string name="power_charging_limited" msgid="6732738149313642521">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje pauzirano"</string> + <string name="power_charging_limited" msgid="6732738149313642521">"<xliff:g id="LEVEL">%1$s</xliff:g> - Punjenje je pauzirano"</string> <string name="power_charging_future_paused" msgid="6829683663982987290">"<xliff:g id="LEVEL">%1$s</xliff:g> – Punjenje do <xliff:g id="DOCK_DEFENDER_THRESHOLD">%2$s</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 66e30f970e94..0bed0569ac36 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -477,8 +477,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> okusele kuze kugcwale"</string> <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> okusele kuze kugcwale"</string> - <!-- no translation found for power_charging_limited (6732738149313642521) --> - <skip /> + <string name="power_charging_limited" msgid="6732738149313642521">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ukushaja kumiswe isikhashana"</string> <string name="power_charging_future_paused" msgid="6829683663982987290">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ishaja ku-<xliff:g id="DOCK_DEFENDER_THRESHOLD">%2$s</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string> diff --git a/packages/SoundPicker/res/values-te/strings.xml b/packages/SoundPicker/res/values-te/strings.xml index feaf4c83b51e..2d03ac0e844c 100644 --- a/packages/SoundPicker/res/values-te/strings.xml +++ b/packages/SoundPicker/res/values-te/strings.xml @@ -19,9 +19,9 @@ <string name="ringtone_default" msgid="798836092118824500">"ఆటోమేటిక్ రింగ్టోన్"</string> <string name="notification_sound_default" msgid="8133121186242636840">"నోటిఫికేషన్ ఆటోమేటిక్ సౌండ్"</string> <string name="alarm_sound_default" msgid="4787646764557462649">"అలారం ఆటోమేటిక్ సౌండ్"</string> - <string name="add_ringtone_text" msgid="6642389991738337529">"రింగ్టోన్ను జోడించు"</string> - <string name="add_alarm_text" msgid="3545497316166999225">"అలారాన్ని జోడించు"</string> - <string name="add_notification_text" msgid="4431129543300614788">"నోటిఫికేషన్ని జోడించు"</string> + <string name="add_ringtone_text" msgid="6642389991738337529">"రింగ్టోన్ను జోడించండి"</string> + <string name="add_alarm_text" msgid="3545497316166999225">"అలారాన్ని జోడించండి"</string> + <string name="add_notification_text" msgid="4431129543300614788">"నోటిఫికేషన్ని జోడించండి"</string> <string name="delete_ringtone_text" msgid="201443984070732499">"తొలగించండి"</string> <string name="unable_to_add_ringtone" msgid="4583511263449467326">"అనుకూల రింగ్టోన్ను జోడించలేకపోయింది"</string> <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"అనుకూల రింగ్టోన్ను తొలగించలేకపోయింది"</string> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index be56c8942479..4f08a30ed630 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -411,6 +411,7 @@ <service android:name=".screenshot.ScreenshotCrossProfileService" android:permission="com.android.systemui.permission.SELF" + android:process=":screenshot_cross_profile" android:exported="false" /> <service android:name=".screenrecord.RecordingService" /> 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 ebabdf571dfd..fe349f21e36e 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -49,12 +49,12 @@ private const val TAG = "ActivityLaunchAnimator" */ class ActivityLaunchAnimator( /** The animator used when animating a View into an app. */ - private val launchAnimator: LaunchAnimator = LaunchAnimator(TIMINGS, INTERPOLATORS), + private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR, /** The animator used when animating a Dialog into an app. */ // TODO(b/218989950): Remove this animator and instead set the duration of the dim fade out to // TIMINGS.contentBeforeFadeOutDuration. - private val dialogToAppAnimator: LaunchAnimator = LaunchAnimator(DIALOG_TIMINGS, INTERPOLATORS) + private val dialogToAppAnimator: LaunchAnimator = DEFAULT_DIALOG_TO_APP_ANIMATOR ) { companion object { /** The timings when animating a View into an app. */ @@ -85,6 +85,9 @@ class ActivityLaunchAnimator( contentAfterFadeInInterpolator = PathInterpolator(0f, 0f, 0.6f, 1f) ) + private val DEFAULT_LAUNCH_ANIMATOR = LaunchAnimator(TIMINGS, INTERPOLATORS) + private val DEFAULT_DIALOG_TO_APP_ANIMATOR = LaunchAnimator(DIALOG_TIMINGS, INTERPOLATORS) + /** Durations & interpolators for the navigation bar fading in & out. */ private const val ANIMATION_DURATION_NAV_FADE_IN = 266L private const val ANIMATION_DURATION_NAV_FADE_OUT = 133L @@ -117,6 +120,22 @@ class ActivityLaunchAnimator( /** The set of [Listener] that should be notified of any animation started by this animator. */ private val listeners = LinkedHashSet<Listener>() + /** Top-level listener that can be used to notify all registered [listeners]. */ + private val lifecycleListener = + object : Listener { + override fun onLaunchAnimationStart() { + listeners.forEach { it.onLaunchAnimationStart() } + } + + override fun onLaunchAnimationEnd() { + listeners.forEach { it.onLaunchAnimationEnd() } + } + + override fun onLaunchAnimationProgress(linearProgress: Float) { + listeners.forEach { it.onLaunchAnimationProgress(linearProgress) } + } + } + /** * Start an intent and animate the opening window. The intent will be started by running * [intentStarter], which should use the provided [RemoteAnimationAdapter] and return the launch @@ -156,7 +175,7 @@ class ActivityLaunchAnimator( ?: throw IllegalStateException( "ActivityLaunchAnimator.callback must be set before using this animator" ) - val runner = Runner(controller) + val runner = createRunner(controller) val hideKeyguardWithAnimation = callback.isOnKeyguard() && !showOverLockscreen // Pass the RemoteAnimationAdapter to the intent starter only if we are not hiding the @@ -256,7 +275,18 @@ class ActivityLaunchAnimator( } /** Create a new animation [Runner] controlled by [controller]. */ - @VisibleForTesting fun createRunner(controller: Controller): Runner = Runner(controller) + @VisibleForTesting + fun createRunner(controller: Controller): Runner { + // Make sure we use the modified timings when animating a dialog into an app. + val launchAnimator = + if (controller.isDialogLaunch) { + dialogToAppAnimator + } else { + launchAnimator + } + + return Runner(controller, callback!!, launchAnimator, lifecycleListener) + } interface PendingIntentStarter { /** @@ -353,14 +383,20 @@ class ActivityLaunchAnimator( * this if the animation was already started, i.e. if [onLaunchAnimationStart] was called * before the cancellation. * - * If this launch animation affected the occlusion state of the keyguard, WM will provide - * us with [newKeyguardOccludedState] so that we can set the occluded state appropriately. + * If this launch animation affected the occlusion state of the keyguard, WM will provide us + * with [newKeyguardOccludedState] so that we can set the occluded state appropriately. */ fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean? = null) {} } - @VisibleForTesting - inner class Runner(private val controller: Controller) : IRemoteAnimationRunner.Stub() { + class Runner( + private val controller: Controller, + private val callback: Callback, + /** The animator to use to animate the window launch. */ + private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR, + /** Listener for animation lifecycle events. */ + private val listener: Listener? = null + ) : IRemoteAnimationRunner.Stub() { private val launchContainer = controller.launchContainer private val context = launchContainer.context private val transactionApplierView = @@ -448,18 +484,9 @@ class ActivityLaunchAnimator( left = windowBounds.left, right = windowBounds.right ) - val callback = this@ActivityLaunchAnimator.callback!! val windowBackgroundColor = window.taskInfo?.let { callback.getBackgroundColor(it) } ?: window.backgroundColor - // Make sure we use the modified timings when animating a dialog into an app. - val launchAnimator = - if (controller.isDialogLaunch) { - dialogToAppAnimator - } else { - launchAnimator - } - // TODO(b/184121838): We should somehow get the top and bottom radius of the window // instead of recomputing isExpandingFullyAbove here. val isExpandingFullyAbove = @@ -483,12 +510,12 @@ class ActivityLaunchAnimator( val controller = object : Controller by delegate { override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { - listeners.forEach { it.onLaunchAnimationStart() } + listener?.onLaunchAnimationStart() delegate.onLaunchAnimationStart(isExpandingFullyAbove) } override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) { - listeners.forEach { it.onLaunchAnimationEnd() } + listener?.onLaunchAnimationEnd() iCallback?.invoke() delegate.onLaunchAnimationEnd(isExpandingFullyAbove) } @@ -505,7 +532,7 @@ class ActivityLaunchAnimator( } navigationBar?.let { applyStateToNavigationBar(it, state, linearProgress) } - listeners.forEach { it.onLaunchAnimationProgress(linearProgress) } + listener?.onLaunchAnimationProgress(linearProgress) delegate.onLaunchAnimationProgress(state, progress, linearProgress) } } diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt index c540f0f7d557..e138ef8a1ea8 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt @@ -20,6 +20,7 @@ import android.graphics.Rect import android.icu.text.NumberFormat import android.util.TypedValue import android.view.LayoutInflater +import android.view.View import android.widget.FrameLayout import androidx.annotation.VisibleForTesting import com.android.systemui.customization.R @@ -151,9 +152,15 @@ class DefaultClockController( view: AnimatableClockView, ) : DefaultClockFaceController(view) { override fun recomputePadding(targetRegion: Rect?) { - // Ignore Target Region until top padding fixed in aod + // We center the view within the targetRegion instead of within the parent + // view by computing the difference and adding that to the padding. + val parent = view.parent + val yDiff = + if (targetRegion != null && parent is View && parent.isLaidOut()) + targetRegion.centerY() - parent.height / 2f + else 0f val lp = view.getLayoutParams() as FrameLayout.LayoutParams - lp.topMargin = (-0.5f * view.bottom).toInt() + lp.topMargin = (-0.5f * view.bottom + yDiff).toInt() view.setLayoutParams(lp) } diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardQuickAffordancePreviewConstants.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardQuickAffordancePreviewConstants.kt new file mode 100644 index 000000000000..18e8a962dc70 --- /dev/null +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardQuickAffordancePreviewConstants.kt @@ -0,0 +1,24 @@ +/* + * 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.shared.quickaffordance.shared.model + +object KeyguardQuickAffordancePreviewConstants { + const val MESSAGE_ID_SLOT_SELECTED = 1337 + const val KEY_SLOT_ID = "slot_id" + const val KEY_INITIALLY_SELECTED_SLOT_ID = "initially_selected_slot_id" +} diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index 218c5cc9b7fe..b49afeef09f3 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -35,7 +35,6 @@ android:visibility="invisible" /> <FrameLayout android:id="@+id/lockscreen_clock_view_large" - android:layout_marginTop="@dimen/keyguard_large_clock_top_margin" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml index e64b586a3e6f..8497ff094c03 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml @@ -27,6 +27,7 @@ android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" + android:paddingTop="@dimen/keyguard_lock_padding" android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent from this view when bouncer is shown --> diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml index 20d32f187d2e..12f96739071c 100644 --- a/packages/SystemUI/res-keyguard/values-in/strings.xml +++ b/packages/SystemUI/res-keyguard/values-in/strings.xml @@ -84,7 +84,7 @@ <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Perangkat dikunci oleh admin"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Perangkat dikunci secara manual"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Tidak dikenali"</string> - <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Untuk pakai Face Unlock, beri akses kamera di Setelan"</string> + <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Untuk pakai Buka dengan Wajah, beri akses kamera di Setelan"</string> <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Masukkan PIN SIM. Tersisa # percobaan lagi sebelum Anda harus menghubungi operator untuk membuka kunci perangkat.}other{Masukkan PIN SIM. Tersisa # percobaan lagi.}}"</string> <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{SIM kini dinonaktifkan. Masukkan kode PUK untuk melanjutkan. Tersisa # percobaan lagi sebelum SIM tidak dapat digunakan secara permanen. Hubungi operator untuk mengetahui detailnya.}other{SIM kini dinonaktifkan. Masukkan kode PUK untuk melanjutkan. Tersisa # percobaan lagi sebelum SIM tidak dapat digunakan secara permanen. Hubungi operator untuk mengetahui detailnya.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Default"</string> diff --git a/packages/SystemUI/res/drawable/dream_aqi_badge_bg.xml b/packages/SystemUI/res/drawable/controls_panel_background.xml index 1992c7733bd3..9092877fc6fa 100644 --- a/packages/SystemUI/res/drawable/dream_aqi_badge_bg.xml +++ b/packages/SystemUI/res/drawable/controls_panel_background.xml @@ -1,3 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2022 The Android Open Source Project ~ @@ -12,9 +13,10 @@ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. + ~ --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> - <solid android:color="@color/dream_overlay_aqi_unknown" /> - <corners android:radius="@dimen/dream_aqi_badge_corner_radius" /> + <solid android:color="#1F1F1F" /> + <corners android:radius="@dimen/notification_corner_radius" /> </shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml index 41123c84ded1..18fcebbb65a0 100644 --- a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml +++ b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml @@ -16,13 +16,53 @@ * limitations under the License. */ --> -<shape +<selector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - 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> + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + + <item android:state_selected="true"> + <layer-list> + <item + android:left="3dp" + android:top="3dp" + android:right="3dp" + android:bottom="3dp"> + <shape android:shape="oval"> + <solid android:color="?androidprv:attr/colorSurface"/> + <size + android:width="@dimen/keyguard_affordance_width" + android:height="@dimen/keyguard_affordance_height"/> + </shape> + </item> + + <item> + <shape android:shape="oval"> + <stroke + android:color="@color/control_primary_text" + android:width="2dp"/> + <size + android:width="@dimen/keyguard_affordance_width" + android:height="@dimen/keyguard_affordance_height"/> + </shape> + </item> + </layer-list> + </item> + + <item> + <layer-list> + <item + android:left="3dp" + android:top="3dp" + android:right="3dp" + android:bottom="3dp"> + <shape android:shape="oval"> + <solid android:color="?androidprv:attr/colorSurface"/> + <size + android:width="@dimen/keyguard_affordance_width" + android:height="@dimen/keyguard_affordance_height"/> + </shape> + </item> + </layer-list> + </item> + +</selector> diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml index 9efad2269463..ee3adba00fe5 100644 --- a/packages/SystemUI/res/layout/controls_with_favorites.xml +++ b/packages/SystemUI/res/layout/controls_with_favorites.xml @@ -90,7 +90,7 @@ android:layout_weight="1" android:layout_marginLeft="@dimen/global_actions_side_margin" android:layout_marginRight="@dimen/global_actions_side_margin" - android:background="#ff0000" + android:background="@drawable/controls_panel_background" android:padding="@dimen/global_actions_side_margin" android:visibility="gone" /> diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_aqi.xml b/packages/SystemUI/res/layout/dream_overlay_complication_aqi.xml deleted file mode 100644 index fcebb8d3f6c6..000000000000 --- a/packages/SystemUI/res/layout/dream_overlay_complication_aqi.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. - --> - -<TextView - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/aqi_view" - style="@style/clock_subtitle" - android:visibility="gone" - android:background="@drawable/dream_aqi_badge_bg" - android:paddingHorizontal="@dimen/dream_aqi_badge_padding_horizontal" - android:paddingVertical="@dimen/dream_aqi_badge_padding_vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content"/>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index eb2f12a82a9b..fe6aebca7e21 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Kennisgewings onderbreek deur Moenie Steur Nie"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Begin nou"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Geen kennisgewings nie"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Geen nuwe kennisgewings nie"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ontsluit om ouer kennisgewings te sien"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Hierdie toestel word deur jou ouer bestuur"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Jou organisasie besit hierdie toestel en kan netwerkverkeer monitor"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> besit hierdie toestel en kan netwerkverkeer monitor"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Hou op uitsaai"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Beskikbare toestelle vir oudio-uitsette."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Hoe uitsaai werk"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Saai uit"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Mense in jou omtrek met versoenbare Bluetooth-toestelle kan na die media luister wat jy uitsaai"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera en mikrofoon is af"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# kennisgewing}other{# kennisgewings}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Neem notas"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Uitsaai"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Hou op om <xliff:g id="APP_NAME">%1$s</xliff:g> uit te saai?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"As jy <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitsaai of die uitvoer verander, sal jou huidige uitsending stop"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Saai <xliff:g id="SWITCHAPP">%1$s</xliff:g> uit"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Verander uitvoer"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Onbekend"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EE. d MMM."</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Maak <xliff:g id="APPNAME">%1$s</xliff:g> oop"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Draai om na voorste skerm vir ’n beter selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gebruik die agterste kamera vir ’n breër foto met ’n hoër resolusie."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Hierdie skerm sal afskakel"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index c6919ce4f15a..93d63791a710 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -998,7 +998,6 @@ <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ያሰራጩ"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"ውፅዓትን ይቀይሩ"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"ያልታወቀ"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE፣ MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ይክፈቱ"</string> @@ -1014,4 +1013,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ለተሻለ የራስ ፎቶ ወደፊት ማሳያ ይገልበጥ?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ከፍተኛ ጥራት ላለው ሰፊ ፎቶ የኋለኛውን ካሜራ ይጠቀሙ።"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ይህ ማያ ገጽ ይጠፋል"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index af80419a9269..dad19abb1d54 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"تم إيقاف الإشعارات مؤقتًا وفقًا لإعداد \"عدم الإزعاج\""</string> <string name="media_projection_action_text" msgid="3634906766918186440">"البدء الآن"</string> <string name="empty_shade_text" msgid="8935967157319717412">"ليس هناك أي اشعارات"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"ما مِن إشعارات جديدة"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"افتَح قفل الشاشة لعرض الإشعارات الأقدم."</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"يتولّى أحد الوالدين إدارة هذا الجهاز."</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"تملك مؤسستك هذا الجهاز ويمكنها تتبّع حركة بيانات الشبكة."</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"تملك مؤسسة <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> هذا الجهاز ويمكنها تتبّع حركة بيانات الشبكة"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"إيقاف البث"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"الأجهزة المتاحة لإخراج الصوت"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"مستوى الصوت"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"كيفية عمل البث"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"البث"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"يمكن للأشخاص القريبين منك الذين لديهم أجهزة متوافقة تتضمّن بلوتوث الاستماع إلى الوسائط التي تبثها."</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"الكاميرا والميكروفون غير مفعّلين."</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{إشعار واحد}zero{# إشعار}two{إشعاران}few{# إشعارات}many{# إشعارًا}other{# إشعار}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>، <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"تدوين الملاحظات"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"البث"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"هل تريد إيقاف بث تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>؟"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"إذا أجريت بث تطبيق <xliff:g id="SWITCHAPP">%1$s</xliff:g> أو غيَّرت جهاز الإخراج، سيتوقَف البث الحالي."</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"بث تطبيق <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"تغيير جهاز الإخراج"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"غير معروف"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE، d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"فتح \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"أتريد استخدام الكاميرا الأمامية لصورة ذاتية أفضل؟"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"استخدِم الكاميرا الخلفية لالتقاط صورة أعرض وبدرجة دقة أعلى."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* سيتم إطفاء هذه الشاشة."</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 20bd1d43697c..9c8aed6dc1eb 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"অসুবিধা নিদিব-ই জাননী পজ কৰিছে"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"এতিয়াই আৰম্ভ কৰক"</string> <string name="empty_shade_text" msgid="8935967157319717412">"কোনো জাননী নাই"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"কোনো নতুন জাননী নাই"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"পুৰণি জাননী চবলৈ আনলক কৰক"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"এই ডিভাইচটো আপোনাৰ অভিভাৱকে পৰিচালনা কৰে"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"এই ডিভাইচটোৰ গৰাকী আপোনাৰ প্ৰতিষ্ঠান আৰু ই নেটৱৰ্কৰ ট্ৰেফিক নিৰীক্ষণ কৰিব পাৰে"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"এই ডিভাইচটোৰ গৰাকী <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> আৰু এইটোৱে নেটৱৰ্কৰ ট্ৰেফিক নিৰীক্ষণ কৰিব পাৰে"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"কাষ্ট বন্ধ কৰক"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"অডিঅ\' আউটপুটৰ বাবে উপলব্ধ ডিভাইচ।"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ভলিউম"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"সম্প্ৰচাৰ কৰাটোৱে কেনেকৈ কাম কৰে"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"সম্প্ৰচাৰ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"সমিল ব্লুটুথ ডিভাইচৰ সৈতে আপোনাৰ নিকটৱৰ্তী স্থানত থকা লোকসকলে আপুনি সম্প্ৰচাৰ কৰা মিডিয়াটো শুনিব পাৰে"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"কেমেৰা আৰু মাইক অফ হৈ আছে"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# টা জাননী}one{# টা জাননী}other{# টা জাননী}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"টোকাগ্ৰহণ"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"সম্প্ৰচাৰণ"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ সম্প্ৰচাৰ কৰা বন্ধ কৰিবনে?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"যদি আপুনি <xliff:g id="SWITCHAPP">%1$s</xliff:g>ৰ সম্প্ৰচাৰ কৰে অথবা আউটপুট সলনি কৰে, তেন্তে, আপোনাৰ বৰ্তমানৰ সম্প্ৰচাৰ বন্ধ হৈ যাব"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> সম্প্ৰচাৰ কৰক"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"আউটপুট সলনি কৰক"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"অজ্ঞাত"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> খোলক"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"উন্নত ছেল্ফিৰ বাবে সন্মুখৰ ডিছপ্লে’ লুটিয়াই দিবনে?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"অধিক ৰিজ’লিউশ্বনৰ বহল ফট’ৰ বাবে পিছফালে থকা কেমেৰাটো ব্যৱহাৰ কৰক।"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ই স্ক্ৰীনখন অফ হ’ব"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 3b4451230486..8870b6167055 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bildirişlər \"Narahat Etməyin\" rejimi tərəfindən dayandırıldı"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"İndi başlayın"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Heç bir bildiriş yoxdur"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Yeni bildiriş yoxdur"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Köhnə bildirişləri görmək üçün kilidi açın"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu cihaz valideyniniz tərəfindən idarə olunur"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Təşkilatınız bu cihazın sahibidir və şəbəkə trafikinə nəzarət edə bilər"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> bu cihazın sahibidir və şəbəkə trafikinə nəzarət edə bilər"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Yayımı dayandırın"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Audio çıxış üçün əlçatan cihazlar."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Səs"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayım necə işləyir"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Yayım"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Uyğun Bluetooth cihazları olan yaxınlığınızdakı insanlar yayımladığınız medianı dinləyə bilər"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera və mikrofon deaktivdir"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# bildiriş}other{# bildiriş}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Qeyd tutma"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Yayım"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinin yayımlanması dayandırılsın?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> tətbiqini yayımlasanız və ya nəticəni dəyişsəniz, cari yayımınız dayandırılacaq"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> tətbiqini yayımlayın"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Nəticəni dəyişdirin"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Naməlum"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"HHH, AAA g"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"s:dd"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"ss:dd"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> tətbiqini açın"</string> @@ -1013,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Daha yaxşı selfi üçün ön displeyə çevrilsin?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Daha yüksək ayırdetmə dəqiqliyi ilə daha geniş şəkil üçün arxaya baxan kameradan istifadə edin."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Bu ekran deaktiv ediləcək"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Qatlana bilən cihaz açılır"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Qatlana bilən cihaz fırladılır"</string> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index c7e609583a20..35cbed93d906 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zaustavi prebacivanje"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dostupni uređaji za audio izlaz."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Zvuk"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcioniše emitovanje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emitovanje"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ljudi u blizini sa kompatibilnim Bluetooth uređajima mogu da slušaju medijski sadržaj koji emitujete"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera i mikrofon su isključeni"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obaveštenje}one{# obaveštenje}few{# obaveštenja}other{# obaveštenja}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Pravljenje beležaka"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Emitovanje"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Želite da zaustavite emitovanje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ako emitujete aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promenite izlaz, aktuelno emitovanje će se zaustaviti"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Emitujte aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Promenite izlaz"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Nepoznato"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"DDD, d. MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"s:min"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"č:min"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvorite: <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Želite da obrnete na prednji ekran za bolji selfi?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Koristite zadnju kameru da biste snimili širu sliku sa višom rezolucijom."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ovaj ekran će se isključiti"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 39453c8ace06..c653c7a4857c 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -723,7 +723,7 @@ <string name="instant_apps_title" msgid="8942706782103036910">"Праграма \"<xliff:g id="APP">%1$s</xliff:g>\" запушчана"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Праграма адкрыта без усталёўкі."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"Праграма адкрыта без усталёўкі. Націсніце, каб даведацца больш."</string> - <string name="app_info" msgid="5153758994129963243">"Звесткі пра праграму"</string> + <string name="app_info" msgid="5153758994129963243">"Звесткі аб праграме"</string> <string name="go_to_web" msgid="636673528981366511">"Перайсці ў браўзер"</string> <string name="mobile_data" msgid="4564407557775397216">"Маб. перадача даных"</string> <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string> @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Спыніць трансляцыю"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Даступныя прылады для вываду аўдыя."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Гучнасць"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як адбываецца трансляцыя"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляцыя"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Людзі паблізу, у якіх ёсць прылады з Bluetooth, змогуць праслухваць мультымедыйнае змесціва, якое вы трансліруеце"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера і мікрафон выключаны"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# апавяшчэнне}one{# апавяшчэнне}few{# апавяшчэнні}many{# апавяшчэнняў}other{# апавяшчэння}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Стварэнне нататак"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Перадача даных"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Спыніць трансляцыю праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Пры пераключэнні на праграму \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\" ці змяненні вываду бягучая трансляцыя спыняецца"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Трансляцыя праграмы \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\""</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Змяненне вываду"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Невядома"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Адкрыць праграму \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Пераключыць на пярэднюю камеру для лепшага сэлфі?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Каб зрабіць шырэйшае фота з больш высокай раздзяляльнасцю, скарыстайце заднюю камеру."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Гэты экран будзе выключаны"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 4b50df1e4d4e..cd2ad4d1c590 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Известията са поставени на пауза от режима „Не безпокойте“"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Стартиране сега"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Няма известия"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Няма нови известия"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Отключете за достъп до по-стари известия"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Това устройство се управлява от родителя ви"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Организацията ви притежава това устройство и може да наблюдава трафика в мрежата"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> притежава това устройство и може да наблюдава трафика в мрежата"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Спиране на предаването"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Налични устройства за аудиоизход."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Сила на звука"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работи предаването"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Предаване"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Хората в близост със съвместими устройства с Bluetooth могат да слушат мултимедията, която предавате"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камерата и микрофонът са изключени"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# известие}other{# известия}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Водене на бележки"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Излъчване"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Да се спре ли предаването на <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ако предавате <xliff:g id="SWITCHAPP">%1$s</xliff:g> или промените изхода, текущото ви предаване ще бъде прекратено"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Предаване на <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Промяна на изхода"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Неизвестно"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Отваряне на <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Да се ползва ли предната камера за по-добро селфи?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Използвайте задната камера за по-широка снимка с по-висока разделителна способност."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Този екран ще се изключи"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 6b66d92cfa7e..4d5e2a3f4945 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"কাস্ট করা বন্ধ করুন"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"অডিও আউটপুটের জন্য উপলভ্য ডিভাইস।"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ভলিউম"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ব্রডকাস্ট কীভাবে কাজ করে"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"সম্প্রচার করুন"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"আশপাশে লোকজন যাদের মানানসই ব্লুটুথ ডিভাইস আছে, তারা আপনার ব্রডকাস্ট করা মিডিয়া শুনতে পারবেন"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ক্যামেরা ও মাইক্রোফোন বন্ধ আছে"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{#টি বিজ্ঞপ্তি}one{#টি বিজ্ঞপ্তি}other{#টি বিজ্ঞপ্তি}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ব্রডকাস্ট করা হচ্ছে"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> সম্প্রচার বন্ধ করবেন?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"আপনি <xliff:g id="SWITCHAPP">%1$s</xliff:g> সম্প্রচার করলে বা আউটপুট পরিবর্তন করলে, আপনার বর্তমান সম্প্রচার বন্ধ হয়ে যাবে"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> সম্প্রচার করুন"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"আউটপুট পরিবর্তন করুন"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"অজানা"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> খুলুন"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"আরও ভাল সেলফির জন্য সামনের ক্যামেরায় পাল্টাতে চান?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"আরও ভাল রেজোলিউশন সহ আরও বেশি ওয়াইড ছবির জন্য ব্যাক-ক্যামেরা ব্যবহার করুন।"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ এই স্ক্রিন বন্ধ হয়ে যাবে"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 0b2c514824f6..cb4b2a563d31 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -72,7 +72,7 @@ <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock je onemogućen"</string> <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslao/la sliku"</string> <string name="screenshot_saving_title" msgid="2298349784913287333">"Spašavanje snimka ekrana..."</string> - <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Spremanje snimke zaslona na poslovni profil…"</string> + <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Pohranjivanje snimka ekrana na radni profil…"</string> <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Nije moguće sačuvati snimak ekrana"</string> <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Morate otključati uređaj da možete sačuvati snimak ekrana"</string> @@ -393,8 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Obavještenja su pauzirana načinom rada Ne ometaj"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Započni odmah"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nema obavještenja"</string> - <string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obavijesti"</string> - <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte za starije obavijesti"</string> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obavještenja"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte da vidite starija obavještenja"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja tvoj roditelj"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizacija je vlasnik ovog uređaja i može nadzirati mrežni saobraćaj"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> upravlja ovim uređajem i može nadzirati mrežni saobraćaj"</string> @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zaustavi emitiranje"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dostupni uređaji za audio izlaz."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Jačina zvuka"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcionira emitiranje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emitirajte"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u vašoj blizini s kompatibilnim Bluetooth uređajima mogu slušati medijske sadržaje koje emitirate"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera i mikrofon su isključeni"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obavještenje}one{# obavještenje}few{# obavještenja}other{# obavještenja}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Pisanje bilješki"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Emitiranje"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Zaustaviti emitiranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ako emitirate aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promijenite izlaz, trenutno emitiranje će se zaustaviti"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Emitiraj aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Promijeni izlaz"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Nepoznato"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"DDD, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvori aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Obrnuti na prednji ekran radi boljeg selfija?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Koristite stražnju kameru za širu fotografiju veće rezolucije."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ekran će se isključiti"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rasklopljen sklopivi uređaj"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Okretanje sklopivog uređaja sa svih strana"</string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 75739386a5e5..68fa2dcff6f6 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificacions pausades pel mode No molestis"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Comença ara"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No hi ha cap notificació"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"No hi ha cap notificació nova"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloq. per veure notificacions antigues"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Els teus pares gestionen aquest dispositiu"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"La teva organització és propietària del dispositiu i és possible que supervisi el trànsit de xarxa"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> és propietària d\'aquest dispositiu i és possible que supervisi el trànsit de xarxa"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Atura l\'emissió"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispositius disponibles per a la sortida d\'àudio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volum"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Com funciona l\'emissió"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emet"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les persones properes amb dispositius Bluetooth compatibles poden escoltar el contingut multimèdia que emets"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Càmera i micròfon desactivats"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificació}many{# notifications}other{# notificacions}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Presa de notes"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"S\'està emetent"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vols deixar d\'emetre <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si emets <xliff:g id="SWITCHAPP">%1$s</xliff:g> o canvies la sortida, l\'emissió actual s\'aturarà"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Emet <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Canvia la sortida"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Desconeguda"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"hh:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Obre <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Girar a pantalla frontal per fer millors selfies?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilitza la càmera posterior per obtenir una foto més àmplia amb una resolució més alta."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Aquesta pantalla s\'apagarà"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index d3a0e6eaf7f1..6eb360bc9fb9 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Oznámení jsou pozastavena režimem Nerušit"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Spustit"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Žádná oznámení"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Žádná nová oznámení"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Starší oznámení se zobrazí po odemknutí"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zařízení spravuje rodič"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Toto zařízení vlastní vaše organizace, která může sledovat síťový provoz"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Toto zařízení spravuje organizace <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, která může sledovat síťový provoz"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zastavit odesílání"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dostupná zařízení pro zvukový výstup."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Hlasitost"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak vysílání funguje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Vysílání"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lidé ve vašem okolí s kompatibilními zařízeními Bluetooth mohou poslouchat média, která vysíláte"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotoaparát a mikrofon jsou vypnuté"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# oznámení}few{# oznámení}many{# oznámení}other{# oznámení}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g> <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Poznámky"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Vysílání"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Zastavit vysílání v aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Pokud budete vysílat v aplikaci <xliff:g id="SWITCHAPP">%1$s</xliff:g> nebo změníte výstup, aktuální vysílání se zastaví"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Vysílat v aplikaci <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Změna výstupu"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Neznámé"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE d. MMMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"H:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otevřít <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Otočit na přední fotoaparát pro lepší selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Pomocí zadního fotoaparátu pořiďte širší fotku s vyšším rozlišením."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Tato obrazovka se vypne"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index a252779e9268..3ba90870e93c 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifikationer er sat på pause af Forstyr ikke"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Start nu"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ingen notifikationer"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Ingen nye notifikationer"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Lås op for at se ældre notifikationer"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Denne enhed administreres af din forælder"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Din organisation ejer denne enhed og overvåger muligvis netværkstrafikken"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ejer denne enhed og overvåger muligvis netværkstrafikken"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop med at caste"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Enheder, der er tilgængelige for lydoutput."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Lydstyrke"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Sådan fungerer udsendelser"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Udsendelse"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i nærheden, som har kompatible Bluetooth-enheder, kan lytte til det medie, du udsender"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera og mikrofon er slået fra"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifikation}one{# notifikation}other{# notifikationer}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Notetagning"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Udsender"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Stop udsendelsen <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Hvis du udsender <xliff:g id="SWITCHAPP">%1$s</xliff:g> eller skifter output, stopper din aktuelle udsendelse"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Udsend <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Skift output"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Ukendt"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE d. MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"tt.mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk.mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Åbn <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vil du bruge frontkameraet for at få bedre selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Brug bagsidekameraet for at få et bredere billede med højere opløsning."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ *Denne skærm slukkes"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index af723248f703..c2d868c9b874 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Benachrichtigungen durch „Bitte nicht stören“ pausiert"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Jetzt starten"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Keine Benachrichtigungen"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Keine neuen Benachrichtigungen"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Für ältere Benachrichtigungen entsperren"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dieses Gerät wird von deinen Eltern verwaltet"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Deine Organisation verwaltet dieses Gerät und kann den Netzwerkverkehr überwachen"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ist der Eigentümer dieses Geräts und kann den Netzwerkverkehr überwachen"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Streaming beenden"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Für die Audioausgabe verfügbare Geräte."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Lautstärke"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Funktionsweise von Nachrichten an alle"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Nachricht an alle"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personen, die in der Nähe sind und kompatible Bluetooth-Geräten haben, können sich die Medien anhören, die du per Nachricht an alle sendest"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera und Mikrofon ausgeschaltet"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# Benachrichtigung}other{# Benachrichtigungen}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Notizen machen"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Übertragung läuft"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> nicht mehr streamen?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Wenn du <xliff:g id="SWITCHAPP">%1$s</xliff:g> streamst oder die Ausgabe änderst, wird dein aktueller Stream beendet"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> streamen"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Ausgabe ändern"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Unbekannt"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d. MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> öffnen"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Für ein besseres Selfie Frontbildschirm verwenden?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Verwende die Rückkamera, um Fotos mit einem weiteren Blickwinkel und höherer Auflösung aufzunehmen."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Dieses Display wird dann ausgeschaltet"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 3cbba755beab..fd694885f0f0 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Οι ειδοποιήσεις τέθηκαν σε παύση από τη λειτουργία \"Μην ενοχλείτε\""</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Έναρξη τώρα"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Δεν υπάρχουν ειδοποιήσεις"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Δεν υπάρχουν νέες ειδοποιήσεις"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ξεκλειδώστε για εμφάνιση παλαιότ. ειδοπ."</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Αυτή η συσκευή είναι διαχειριζόμενη από τον γονέα σου"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ο οργανισμός σας κατέχει αυτήν τη συσκευή και μπορεί να παρακολουθεί την επισκεψιμότητα δικτύου."</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Ο οργανισμός <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> κατέχει αυτήν τη συσκευή και μπορεί να παρακολουθεί την επισκεψιμότητα δικτύου."</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Διακοπή μετάδοσης"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Διαθέσιμες συσκευές για έξοδο ήχου."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Ένταση ήχου"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Πώς λειτουργεί η μετάδοση"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Μετάδοση"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Οι άνθρωποι με συμβατές συσκευές Bluetooth που βρίσκονται κοντά σας μπορούν να ακούσουν το μέσο που μεταδίδετε."</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Η κάμερα και το μικρόφωνο έχουν απενεργοποιηθεί"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ειδοποίηση}other{# ειδοποιήσεις}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Δημιουργία σημειώσεων"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Μετάδοση"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Διακοπή μετάδοσης με την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Εάν κάνετε μετάδοση με την εφαρμογή <xliff:g id="SWITCHAPP">%1$s</xliff:g> ή αλλάξετε την έξοδο, η τρέχουσα μετάδοση θα σταματήσει"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Μετάδοση με την εφαρμογή <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Αλλαγή εξόδου"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Άγνωστο"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"ΗΗΗ, ΜΜΜ η"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"ώ:λλ"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:λλ"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Άνοιγμα <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Αναστροφή στην μπροστ. οθόνη για καλύτερη selfie;"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Χρησιμοποιήστε την πίσω κάμερα για να βγάλετε μια φωτογραφία με μεγαλύτερο εύρος και υψηλότερη ανάλυση."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Αυτή η οθόνη θα απενεργοποιηθεί"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Αναδιπλούμενη συσκευή που ξεδιπλώνει"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Αναδιπλούμενη συσκευή που διπλώνει"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 212c879e45ec..244865b79111 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Available devices for audio output."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Broadcasting"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Change output"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Unknown"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Flip to front display for a better selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use the rear-facing camera for a wider photo with higher resolution."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index f87dd7f65d8b..5cc99f97c172 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -993,7 +993,6 @@ <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Change output"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Unknown"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1009,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Flip to front display for a better selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use the rear-facing camera for a wider photo with higher resolution."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 212c879e45ec..244865b79111 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Available devices for audio output."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Broadcasting"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Change output"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Unknown"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Flip to front display for a better selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use the rear-facing camera for a wider photo with higher resolution."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 212c879e45ec..244865b79111 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stop casting"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Available devices for audio output."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Broadcasting"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Change output"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Unknown"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Flip to front display for a better selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use the rear-facing camera for a wider photo with higher resolution."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 1152e1e175af..cb79d1134512 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -993,7 +993,6 @@ <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Change output"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Unknown"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1009,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Flip to front display for a better selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use the rear-facing camera for a wider photo with higher resolution."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930">""<b>"✱ This screen will turn off"</b>""</string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 609a0154fc8b..b91d1d62b398 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Detener transmisión"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispositivos disponibles para salida de audio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volumen"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la transmisión"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmisión"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que transmites"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"La cámara y el micrófono están apagados"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}many{# notificaciones}other{# notificaciones}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Tomar notas"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmitiendo"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"¿Quieres dejar de transmitir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si transmites <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambias la salida, tu transmisión actual se detendrá"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Transmitir <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Cambia la salida"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Desconocido"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d de MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"¿Cambiar a pantalla frontal para mejores selfies?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Usa la cámara trasera para tomar una foto más amplia y con mejor resolución."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta pantalla se apagará"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 3225c670dac6..e30b0e9fb804 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificaciones pausadas por el modo No molestar"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Empezar ahora"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No hay notificaciones"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"No hay notificaciones nuevas"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notif. anteriores"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo lo gestionan tu padre o tu madre"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"El dispositivo pertenece a tu organización, que puede monitorizar su tráfico de red"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"El dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, que puede monitorizar su tráfico de red"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Dejar de enviar contenido"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispositivos disponibles para la salida de audio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volumen"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la emisión"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emisión"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que emites"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"La cámara y el micrófono están desactivados"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}many{# notificaciones}other{# notificaciones}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Tomar notas"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Emitiendo"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"¿Dejar de emitir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si emites <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambias la salida, tu emisión actual se detendrá"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Emitir <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Cambiar salida"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Desconocido"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"¿Usar pantalla frontal para hacer mejores selfies?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Usa la cámara trasera para hacer una foto más amplia y con mayor resolución."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta pantalla se apagará"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 1677590c1e7b..cd1445b5b4df 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Režiim Mitte segada peatas märguanded"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Alusta kohe"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Märguandeid pole"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Uusi märguandeid ei ole"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Uute märguannete nägemiseks avage"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Seda seadet haldab sinu vanem"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Teie organisatsioon on selle seadme omanik ja võib jälgida võrguliiklust"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> on selle seadme omanik ja võib jälgida võrguliiklust"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Lõpeta ülekanne"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Saadaolevad seadmed heli esitamiseks."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Helitugevus"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kuidas ülekandmine toimib?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Ülekanne"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Teie läheduses olevad inimesed, kellel on ühilduvad Bluetooth-seadmed, saavad kuulata teie ülekantavat meediat"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kaamera ja mikrofon on välja lülitatud"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# märguanne}other{# märguannet}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Märkmete tegemine"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Edastamine"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Kas peatada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> ülekandmine?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Kui kannate rakendust <xliff:g id="SWITCHAPP">%1$s</xliff:g> üle või muudate väljundit, peatatakse teie praegune ülekanne"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Rakenduse <xliff:g id="SWITCHAPP">%1$s</xliff:g> ülekandmine"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Väljundi muutmine"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Tundmatu"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d. MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ava <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Kas kasutada parema selfi jaoks esikaamerat?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Kasutage tagakülje kaamerat, et jäädvustada suurema eraldusvõimega laiem foto."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ See ekraan lülitatakse välja"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 8f5b88a85eac..f9508d17106d 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -529,8 +529,8 @@ <string name="notification_automatic_title" msgid="3745465364578762652">"Automatikoa"</string> <string name="notification_channel_summary_low" msgid="4860617986908931158">"Ez du tonurik jotzen edo dar-dar egiten"</string> <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Ez du tonurik jotzen edo dar-dar egiten, eta elkarrizketen atalaren behealdean agertzen da"</string> - <string name="notification_channel_summary_default" msgid="3282930979307248890">"Tonua jo edo dar-dar egin dezake, telefonoaren ezarpenen arabera"</string> - <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Tonua jo edo dar-dar egin dezake, telefonoaren ezarpenen arabera. Modu lehenetsian, <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioko elkarrizketak burbuila gisa agertzen dira."</string> + <string name="notification_channel_summary_default" msgid="3282930979307248890">"Tonua joko du, edo dar-dar egingo, telefonoaren ezarpenen arabera"</string> + <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Tonua joko du, edo dar-dar egingo, telefonoaren ezarpenen arabera. Modu lehenetsian, <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioko elkarrizketak burbuila gisa agertzen dira."</string> <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Ezarri sistemak zehaztu dezala jakinarazpen honek soinua edo dardara egin behar duen ala ez"</string> <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"Lehenetsi gisa ezarri da <b>egoera:</b>"</string> <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"Soinurik gabeko modura aldatu da <b>egoera:</b>"</string> @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Gelditu igorpena"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Audio-irteerarako gailu erabilgarriak."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Bolumena"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%% <xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Nola funtzionatzen dute iragarpenek?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Iragarri"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Bluetooth bidezko gailu bateragarriak dituzten inguruko pertsonek iragartzen ari zaren multimedia-edukia entzun dezakete"</string> @@ -948,7 +947,7 @@ <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Ezin izan da konektatu sarera"</string> <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Oraingoz ez da automatikoki konektatuko wifira"</string> <string name="see_all_networks" msgid="3773666844913168122">"Ikusi guztiak"</string> - <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Sarea aldatzeko, deskonektatu Ethernet-a"</string> + <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Sarea aldatzeko, deskonektatu Etherneta"</string> <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Gailuaren funtzionamendua hobetzeko, aplikazioek eta zerbitzuek wifi-sareak bilatzen jarraituko dute, baita wifi-konexioa desaktibatuta dagoenean ere. Aukera hori aldatzeko, joan wifi-sareen bilaketaren ezarpenetara. "<annotation id="link">"Aldatu"</annotation></string> <string name="turn_off_airplane_mode" msgid="8425587763226548579">"Desaktibatu hegaldi modua"</string> <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioak lauza hau gehitu nahi du Ezarpen bizkorrak menuan:"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera eta mikrofonoa desaktibatuta daude"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# jakinarazpen}other{# jakinarazpen}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Oharrak idaztea"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Igortzen"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren audioa igortzeari utzi nahi diozu?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> aplikazioaren audioa igortzen baduzu, edo audio-irteera aldatzen baduzu, une hartako igorpena eten egingo da"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Igorri <xliff:g id="SWITCHAPP">%1$s</xliff:g> aplikazioaren audioa"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Aldatu audio-irteera"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Ezezaguna"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ireki <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Telefonoa irauli nahi duzu autoargazki hobeak ateratzeko?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Erabili atzeko kamera kalitate handiagoko argazki zabalago bat ateratzeko."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Pantaila itzali egingo da"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 0e8f2564e57b..bb195ce9d659 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"اعلانها توسط «مزاحم نشوید» موقتاً متوقف شدند"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"اکنون شروع کنید"</string> <string name="empty_shade_text" msgid="8935967157319717412">"اعلانی موجود نیست"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"اعلان جدیدی وجود ندارد"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"برای دیدن اعلانهای قبلی قفل را باز کنید"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"این دستگاه را ولیتان مدیریت میکند"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"مالک این دستگاه سازمان شما است و ممکن است ترافیک شبکه را پایش کند"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"مالک این دستگاه <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> است و ممکن است ترافیک شبکه را پایش کند"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"توقف پخش محتوا"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"دستگاههای دردسترس برای خروجی صدا."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"میزان صدا"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"همهفرتستی چطور کار میکند"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"همهفرستی"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"افرادی که در اطرافتان دستگاههای Bluetooth سازگار دارند میتوانند به رسانهای که همهفرستی میکنید گوش کنند"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"دوربین و میکروفون خاموش هستند"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# اعلان}one{# اعلان}other{# اعلان}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>، <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"یادداشتبرداری"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"همهفرستی"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"همهفرستی <xliff:g id="APP_NAME">%1$s</xliff:g> متوقف شود؟"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"اگر <xliff:g id="SWITCHAPP">%1$s</xliff:g> را همهفرستی کنید یا خروجی را تغییر دهید، همهفرستی کنونی متوقف خواهد شد"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"همهفرستی <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"تغییر خروجی"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"نامشخص"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"باز کردن <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"برای خویشگرفت بهتر، از نمایشگر جلو استفاده شود؟"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"برای عکسی عریضتر با وضوح بالاتر، از دوربین عقب استفاده کنید."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ این صفحهنمایش خاموش خواهد شد"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 46770602ddc3..0783c15871e9 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Älä häiritse ‑tila keskeytti ilmoitukset"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Aloita nyt"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ei ilmoituksia"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Ei uusia ilmoituksia"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Avaa lukitus uusia ilmoituksia varten"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Vanhempasi ylläpitää tätä laitetta"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisaatiosi omistaa laitteen ja voi valvoa verkkoliikennettä"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa laitteen ja voi valvoa verkkoliikennettä"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Lopeta striimaus"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Käytettävissä olevat audiolaitteet"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Äänenvoimakkuus"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Miten lähetys toimii"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Lähetys"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lähistöllä olevat ihmiset, joilla on yhteensopiva Bluetooth-laite, voivat kuunnella lähettämääsi mediaa"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera ja mikrofoni ovat pois päältä"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ilmoitus}other{# ilmoitusta}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Muistiinpanojen tekeminen"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Lähettää"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Lopetetaanko <xliff:g id="APP_NAME">%1$s</xliff:g>-sovelluksen lähettäminen?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jos lähetät <xliff:g id="SWITCHAPP">%1$s</xliff:g>-sovellusta tai muutat ulostuloa, nykyinen lähetyksesi loppuu"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Lähetä <xliff:g id="SWITCHAPP">%1$s</xliff:g>-sovellusta"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Muuta ulostuloa"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Tuntematon"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"VKP, KKK p"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Avaa <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Käännä etunäytölle, jotta saat paremman selfien?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Voit ottaa laajemman kuvan korkeammalla resoluutiolla, kun käytät takakameraa."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Tämä näyttö sammutetaan"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index d61c1989adc9..15a57b0a1b23 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Les notifications sont suspendues par le mode Ne pas déranger"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Commencer"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Aucune notification"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Aucune nouvelle notification"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Déverr. pour voir les anciennes notif."</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Cet appareil est géré par ton parent"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Votre organisation possède cet appareil et peut contrôler le trafic réseau"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> possède cet appareil et peut contrôler le trafic réseau"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Arrêter la diffusion"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Appareils disponibles pour la sortie audio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement de la diffusion"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Diffusion"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité disposant d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"L\'appareil photo et le micro sont désactivés"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}many{# de notifications}other{# notifications}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Prise de note"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Diffusion en cours…"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si vous diffusez <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou changez la sortie, votre diffusion actuelle s\'arrêtera"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Diffuser <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Changer la sortie"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Inconnue"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ouvrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Retourner l\'écran pour un meilleur égoportrait?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilisez l\'appareil photo arrière pour une photo plus large avec une résolution supérieure."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Cet écran va s\'éteindre"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index c0eef80fbb80..a1c6e36b5a25 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifications suspendues par le mode Ne pas déranger"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Commencer"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Aucune notification"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Aucune nouvelle notification"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Déverrouiller pour voir anciennes notifications"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Cet appareil est géré par tes parents"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Cet appareil appartient à votre organisation, qui peut contrôler votre trafic réseau"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, qui peut contrôler votre trafic réseau"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Arrêter la diffusion"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Appareils disponibles pour la sortie audio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement des annonces"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Annonce"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité équipées d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Appareil photo et micro désactivés"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}many{# notifications}other{# notifications}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Prendre des notes"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Diffusion…"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Si vous diffusez <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou que vous modifiez le résultat, votre annonce actuelle s\'arrêtera"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Diffuser <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Modifier le résultat"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Inconnue"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM j"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"hh:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ouvrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Passer à l\'écran frontal pour un meilleur selfie ?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilisez la caméra arrière pour prendre une photo plus large avec une résolution supérieure."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Cet écran sera désactivé"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 3b828cd46989..60d2e0a3ee2f 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"O modo Non molestar puxo en pausa as notificacións"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Non hai notificacións"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Non hai notificacións novas"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificacións"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"O teu pai ou nai xestiona este dispositivo"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"A túa organización é propietaria deste dispositivo e pode controlar o tráfico de rede"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é a organización propietaria deste dispositivo e pode controlar o tráfico de rede"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Deter emisión"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispositivos dispoñibles para a saída de audio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funcionan as difusións?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Difusión"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As persoas que estean preto de ti e que dispoñan de dispositivos Bluetooth compatibles poden escoitar o contido multimedia que difundas"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A cámara e o micrófono están desactivados"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}other{# notificacións}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Toma de notas"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Difusión"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Queres deixar de emitir contido a través de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se emites contido a través de <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou cambias de saída, a emisión en curso deterase"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Emitir contido a través de <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Cambiar de saída"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Descoñecida"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Usar a cámara dianteira para unha autofoto mellor?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Usa a cámara traseira para sacar unha foto máis ampla e con maior resolución."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Desactivarase esta pantalla"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 075be84fc308..d9572efc160f 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"કાસ્ટ કરવાનું રોકો"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ઑડિયો આઉટપુટ માટે ઉપલબ્ધ ડિવાઇસ."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"વૉલ્યૂમ"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"બ્રોડકાસ્ટ પ્રક્રિયાની કામ કરવાની રીત"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"બ્રોડકાસ્ટ કરો"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"સુસંગત બ્લૂટૂથ ડિવાઇસ ધરાવતા નજીકના લોકો તમે જે મીડિયા બ્રોડકાસ્ટ કરી રહ્યાં છો તે સાંભળી શકે છે"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"કૅમેરા અને માઇક બંધ છે"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# નોટિફિકેશન}one{# નોટિફિકેશન}other{# નોટિફિકેશન}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"નોંધ લેવી"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"બ્રૉડકાસ્ટ કરી રહ્યાં છે"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> બ્રોડકાસ્ટ કરવાનું રોકીએ?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"જો તમે <xliff:g id="SWITCHAPP">%1$s</xliff:g> બ્રોડકાસ્ટ કરો અથવા આઉટપુટ બદલો, તો તમારું હાલનું બ્રોડકાસ્ટ બંધ થઈ જશે"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> બ્રોડકાસ્ટ કરો"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"આઉટપુટ બદલો"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"અજાણ"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ખોલો"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"બહેતર સેલ્ફી લેવા ફ્રન્ટ ડિસ્પ્લે પર ફ્લિપ કરીએ?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"વધુ ઉચ્ચ રિઝોલ્યુશનવાળો વિશાળ ફોટો લેવા માટે પાછલા કૅમેરાનો ઉપયોગ કરો."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ આ સ્ક્રીન બંધ થઈ જશે"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml b/packages/SystemUI/res/values-h411dp/dimens.xml index f05922fb395c..6b21353d0e55 100644 --- a/packages/SystemUI/res/layout/dream_overlay_complication_weather.xml +++ b/packages/SystemUI/res/values-h411dp/dimens.xml @@ -13,10 +13,7 @@ ~ 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. ---> -<TextView - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/weather_view" - style="@style/clock_subtitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> + --> +<resources> + <dimen name="volume_row_slider_height">137dp</dimen> +</resources> diff --git a/packages/SystemUI/res/values-h700dp/dimens.xml b/packages/SystemUI/res/values-h700dp/dimens.xml index 055308f17776..39777ab56847 100644 --- a/packages/SystemUI/res/values-h700dp/dimens.xml +++ b/packages/SystemUI/res/values-h700dp/dimens.xml @@ -17,4 +17,5 @@ <resources> <!-- Margin above the ambient indication container --> <dimen name="ambient_indication_container_margin_top">15dp</dimen> -</resources>
\ No newline at end of file + <dimen name="volume_row_slider_height">177dp</dimen> +</resources> diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml b/packages/SystemUI/res/values-h841dp/dimens.xml index efbdd1af3644..412da199f6b6 100644 --- a/packages/SystemUI/res/layout/dream_overlay_complication_clock_date.xml +++ b/packages/SystemUI/res/values-h841dp/dimens.xml @@ -13,12 +13,7 @@ ~ 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. ---> -<TextClock - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/date_view" - style="@style/clock_subtitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:format12Hour="@string/dream_date_complication_date_format" - android:format24Hour="@string/dream_date_complication_date_format"/> + --> +<resources> + <dimen name="volume_row_slider_height">237dp</dimen> +</resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 4179828606d0..6f34cff12d17 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'परेशान न करें\' सुविधा के ज़रिए कुछ समय के लिए सूचनाएं दिखाना रोक दिया गया है"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"अभी शुरू करें"</string> <string name="empty_shade_text" msgid="8935967157319717412">"कोई सूचना नहीं है"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"कोई नई सूचना नहीं है"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"पुरानी सूचाएं देखने के लिए अनलॉक करें"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"इस डिवाइस का प्रबंधन आपके अभिभावक करते हैं"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है. आपका संगठन, नेटवर्क के ट्रैफ़िक की निगरानी कर सकता है"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"इस डिवाइस का मालिकाना हक <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> के पास है. आपका संगठन, नेटवर्क के ट्रैफ़िक की निगरानी कर सकता है"</string> @@ -502,8 +500,7 @@ <string name="wallet_error_generic" msgid="257704570182963611">"आपके कार्ड की जानकारी पाने में कोई समस्या हुई है. कृपया बाद में कोशिश करें"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन की सेटिंग"</string> <string name="qr_code_scanner_title" msgid="1938155688725760702">"क्यूआर कोड स्कैनर"</string> - <!-- no translation found for qr_code_scanner_updating_secondary_label (8344598017007876352) --> - <skip /> + <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"अपडेट हो रहा है"</string> <string name="status_bar_work" msgid="5238641949837091056">"वर्क प्रोफ़ाइल"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"हवाई जहाज़ मोड"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"आपको <xliff:g id="WHEN">%1$s</xliff:g> पर अपना अगला अलार्म नहीं सुनाई देगा"</string> @@ -875,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्टिंग करना रोकें"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ऑडियो आउटपुट के लिए उपलब्ध डिवाइस."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"वॉल्यूम"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ब्रॉडकास्ट करने की सुविधा कैसे काम करती है"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ब्रॉडकास्ट करें"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"आपके आस-पास मौजूद लोग, ब्रॉडकास्ट किए जा रहे मीडिया को सुन सकते हैं. हालांकि, इसके लिए उनके पास ऐसे ब्लूटूथ डिवाइस होने चाहिए जिन पर मीडिया चलाया जा सके"</string> @@ -990,35 +986,30 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"कैमरा और माइक बंद हैं"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# सूचना}one{# सूचना}other{# सूचनाएं}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"नोट बनाएं"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ब्रॉडकास्ट ऐप्लिकेशन"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर ब्रॉडकास्ट करना रोकें?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> पर ब्रॉडकास्ट शुरू करने पर या आउटपुट बदलने पर, आपका मौजूदा ब्रॉडकास्ट बंद हो जाएगा"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> पर ब्रॉडकास्ट करें"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"आउटपुट बदलें"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"कोई जानकारी नहीं"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> - <!-- no translation found for keyguard_affordance_enablement_dialog_action_template (8164857863036314664) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_message (2790910660524887941) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_wallet_instruction_1 (8439655049139819278) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_wallet_instruction_2 (4321089250629477835) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_qr_scanner_instruction (5355839079232119791) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_home_instruction_1 (8438311171750568633) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_home_instruction_2 (8308525385889021652) --> - <skip /> + <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> खोलें"</string> + <string name="keyguard_affordance_enablement_dialog_message" msgid="2790910660524887941">"<xliff:g id="APPNAME">%1$s</xliff:g> ऐप्लिकेशन को शॉर्टकट के तौर पर जोड़ने के लिए, पक्का करें कि"</string> + <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ऐप्लिकेशन को सेट अप किया गया है"</string> + <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet में कम से कम एक कार्ड जोड़ा गया है"</string> + <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• कैमरा ऐप्लिकेशन इंस्टॉल किया गया है"</string> + <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• ऐप्लिकेशन को सेट अप किया गया है"</string> + <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• कम से कम एक डिवाइस उपलब्ध है"</string> <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द करें"</string> <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"कैमरा अभी स्विच करें"</string> <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"बेहतर सेल्फ़ी के लिए फ़ोन को अनफ़ोल्ड करें"</string> <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"बेहतर सेल्फ़ी के लिए फ़्रंट डिसप्ले पर स्विच करें?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"वाइड ऐंगल में हाई रिज़ॉल्यूशन वाली फ़ोटो लेने के लिए, पीछे का कैमरा इस्तेमाल करें."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ यह स्क्रीन बंद हो जाएगी"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index ba83e9ae35c7..7e7a0d9e343d 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zaustavi emitiranje"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dostupni uređaji za audioizlaz."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Glasnoća"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako emitiranje funkcionira"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Emitiranje"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u blizini s kompatibilnim Bluetooth uređajima mogu slušati medije koje emitirate"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotoaparat i mikrofon su isključeni"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obavijest}one{# obavijest}few{# obavijesti}other{# obavijesti}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Pisanje bilježaka"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Emitiranje"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Zaustaviti emitiranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ako emitirate aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promijenite izlaz, vaše će se trenutačno emitiranje zaustaviti"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Emitiranje aplikacije <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Promjena izlaza"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Nepoznato"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE., d. MMM."</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvorite <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Prebaciti na prednji zaslon za bolji selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Upotrijebite stražnji fotoaparat za širu fotografiju s višom razlučivošću."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ovaj će se zaslon isključiti"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rasklopljen sklopivi uređaj"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Okretanje sklopivog uređaja sa svih strana"</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 759668af988b..9624acd79847 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Átküldés leállítása"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Rendelkezésre álló eszközök a hangkimenethez."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Hangerő"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"A közvetítés működése"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Közvetítés"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"A közelben tartózkodó, kompatibilis Bluetooth-eszközzel rendelkező személyek meghallgathatják az Ön közvetített médiatartalmait"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A kamera és a mikrofon ki vannak kapcsolva"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# értesítés}other{# értesítés}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Jegyzetelés"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Sugárzás"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Leállítja a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> közvetítését?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"A(z) <xliff:g id="SWITCHAPP">%1$s</xliff:g> közvetítése vagy a kimenet módosítása esetén a jelenlegi közvetítés leáll"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> közvetítése"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Kimenet módosítása"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Ismeretlen"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, HHH n"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"ó:pp"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"óó:pp"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> megnyitása"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Átfordítja az előlapi kijelzőre a jobb szelfiért?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Használja az előlapi kamerát, hogy nagyobb felbontású, szélesebb fotót készíthessen"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ A képernyő kikapcsol"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index c7e9b9faaaec..61357e51c351 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Ծանուցումները չեն ցուցադրվի «Չանհանգստացնել» ռեժիմում"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Սկսել հիմա"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ծանուցումներ չկան"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Նոր ծանուցումներ չկան"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ապակողպեք՝ տեսնելու հին ծանուցումները"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Այս սարքը կառավարում է ձեր ծնողը"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ձեր կազմակերպությունը այս սարքի սեփականատերն է և կարող է վերահսկել ցանցային թրաֆիկը"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"«<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>» կազմակերպությունը այս սարքի սեփականատերն է և կարող է վերահսկել ցանցային թրաֆիկը"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Կանգնեցնել հեռարձակումը"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Հասանելի սարքեր ձայնի արտածման համար։"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Ձայնի ուժգնություն"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ինչպես է աշխատում հեռարձակումը"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Հեռարձակում"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ձեր մոտակայքում գտնվող՝ համատեղելի Bluetooth սարքերով մարդիկ կարող են լսել մեդիա ֆայլերը, որոնք դուք հեռարձակում եք։"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Տեսախցիկը և խոսափողն անջատված են"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ծանուցում}one{# ծանուցում}other{# ծանուցում}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Նշումների ստեղծում"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Հեռարձակում"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Կանգնեցնել <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի հեռարձակումը"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Եթե հեռարձակեք <xliff:g id="SWITCHAPP">%1$s</xliff:g> հավելվածը կամ փոխեք աուդիո ելքը, ձեր ընթացիկ հեռարձակումը կկանգնեցվի։"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Հեռարձակել <xliff:g id="SWITCHAPP">%1$s</xliff:g> հավելվածը"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Փոխել աուդիո ելքը"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Անհայտ"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Բացել <xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Հեռախոսը էկրանով դեպի ձե՞զ շրջեցիք"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Օգտագործեք հետևի տեսախցիկը՝ ավելի բարձր լուծաչափով և ավելի լայն լուսանկար ստանալու համար։"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Այս էկրանը կանջատվի"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index a17483fb8cbe..84ae4d44d4a2 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Hentikan transmisi"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Perangkat yang tersedia untuk output audio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cara kerja siaran"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Siaran"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Orang di dekat Anda dengan perangkat Bluetooth yang kompatibel dapat mendengarkan media yang sedang Anda siarkan"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera dan mikrofon nonaktif"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifikasi}other{# notifikasi}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Pembuatan catatan"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Menyiarkan"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Hentikan siaran <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jika Anda menyiarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g> atau mengubah output, siaran saat ini akan dihentikan"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Siarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Ubah output"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Tidak diketahui"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Buka <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Gunakan layar depan untuk selfie yang lebih baik?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gunakan kamera belakang untuk foto dengan resolusi lebih tinggi dan lebih lebar."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Layar ini akan dinonaktifkan"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 40f459498208..85f7b721fc3a 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Hlé gert á tilkynningum þar sem stillt er á „Ónáðið ekki“"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Byrja núna"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Engar tilkynningar"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Engar nýjar tilkynningar"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Taktu úr lás til að sjá eldri tilkynningar"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Foreldri þitt stjórnar þessu tæki"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Fyrirtækið þitt á þetta tæki og fylgist hugsanlega með netumferð"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> á þetta tæki og fylgist hugsanlega með netumferð"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stöðva útsendingu"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Tæki í boði fyrir hljóðúttak."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Hljóðstyrkur"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Svona virkar útsending"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Útsending"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Fólk nálægt þér með samhæf Bluetooth-tæki getur hlustað á efnið sem þú sendir út"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Slökkt á myndavél og hljóðnema"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# tilkynning}one{# tilkynning}other{# tilkynningar}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Glósugerð"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Útsending í gangi"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Hætta að senda út <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ef þú sendir út <xliff:g id="SWITCHAPP">%1$s</xliff:g> eða skiptir um úttak lýkur yfirstandandi útsendingu"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Senda út <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Skipta um úttak"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Óþekkt"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"k:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Opna <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Snúa á framskjá til að ná betri sjálfsmynd?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Notaðu aftari myndavélina til að ná víðara sjónarhorni með meiri upplausn."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Slökkt verður á þessum skjá"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 6d3e4249fac9..0ca503df4ae0 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifiche messe in pausa in base alla modalità Non disturbare"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Avvia adesso"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nessuna notifica"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Nessuna nuova notifica"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Sblocca per notifiche meno recenti"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Questo dispositivo è gestito dai tuoi genitori"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Questo dispositivo appartiene alla tua organizzazione, che potrebbe monitorare il traffico di rete"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Questo dispositivo appartiene a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, che potrebbe monitorare il traffico di rete"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Interrompi trasmissione"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispositivi disponibili per l\'uscita audio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Come funziona la trasmissione"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Annuncio"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Le persone vicine a te che hanno dispositivi Bluetooth compatibili possono ascoltare i contenuti multimediali che stai trasmettendo"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotocamera e microfono non attivi"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifica}many{# notifiche}other{# notifiche}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Aggiunta di note"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Trasmissione in corso…"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vuoi interrompere la trasmissione dell\'app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se trasmetti l\'app <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambi l\'uscita, la trasmissione attuale viene interrotta"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Trasmetti l\'app <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Cambia uscita"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Unknown"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM g"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Apri <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Girare su display frontale per un selfie migliore?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilizza la fotocamera posteriore per una foto più ampia con maggiore risoluzione."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Questo schermo verrà disattivato"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 37796692bb2f..5df872b350c7 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"עצירת ההעברה (casting)"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"מכשירים זמינים לפלט אודיו."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"עוצמת הקול"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"הסבר על שידורים"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"שידור"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"אנשים בקרבת מקום עם מכשירי Bluetooth תואמים יכולים להאזין למדיה שמשודרת על ידך"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"המצלמה והמיקרופון כבויים"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{התראה אחת}one{# התראות}two{# התראות}other{# התראות}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"כתיבת הערות"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"שידור"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"האם להפסיק לשדר את התוכן מאפליקציית <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"אם משדרים את התוכן מאפליקציית <xliff:g id="SWITCHAPP">%1$s</xliff:g> או משנים את הפלט, השידור הנוכחי יפסיק לפעול"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"שידור תוכן מאפליקציית <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"שינוי הפלט"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"לא ידוע"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"יום EEE, d בMMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"פתיחת <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"להפוך למסך הקדמי כדי לצלם תמונת סלפי טובה יותר?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"במצלמה האחורית אפשר לצלם תמונה רחבה יותר ברזולוציה גבוהה יותר."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ המסך יכבה"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 41cdd1be3bb2..f15540cc28ef 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"キャストを停止"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"音声出力ができるデバイスです。"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"音量"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ブロードキャストの仕組み"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ブロードキャスト"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Bluetooth 対応デバイスを持っている付近のユーザーは、あなたがブロードキャストしているメディアを聴けます"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"カメラとマイクが OFF です"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 件の通知}other{# 件の通知}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>、<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"メモ"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ブロードキャスト"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> のブロードキャストを停止しますか?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> をブロードキャストしたり、出力を変更したりすると、現在のブロードキャストが停止します。"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> をブロードキャスト"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"出力を変更"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"不明"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> を開く"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"前面ディスプレイに切り替えて綺麗に撮りましょう"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"高解像度で広い範囲を撮影するには、背面カメラを使用してください。"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱この画面は OFF になります"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 8ab76d6daabc..0626dd62d931 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ტრანსლირების შეწყვეტა"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ხელმისაწვდომი მოწყობილობები გამომავალი აუდიოსთვის."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ხმა"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ტრანსლირების მუშაობის პრინციპი"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ტრანსლაცია"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"თქვენთან ახლოს მყოფ ხალხს თავსებადი Bluetooth მოწყობილობით შეუძლიათ თქვენ მიერ ტრანსლირებული მედიის მოსმენა"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"კამერა და მიკროფონი გამორთულია"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# შეტყობინება}other{# შეტყობინება}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"შენიშვნების ჩაწერა"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"იწყებთ მაუწყებლობას"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"გსურთ <xliff:g id="APP_NAME">%1$s</xliff:g>-ის ტრანსლაციის შეჩერება?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g>-ის ტრანსლაციის შემთხვევაში ან აუდიოს გამოსასვლელის შეცვლისას, მიმდინარე ტრანსლაცია შეჩერდება"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g>-ის ტრანსლაცია"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"აუდიოს გამოსასვლელის შეცვლა"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"უცნობი"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"დდდ, თთთ თ"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"სთ:წთ"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"სთ:წთ"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> აპის გახსნა"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"გადააბრუნეთ წინა ეკრანზე უკეთესი სელფის მისაღებად?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"გამოიყენეთ უკანა კამერა უფრო ფართო ფოტოს გადასაღებად მაღალი გარჩევადობით."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ეს ეკრანი გამოირთვება"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index ad984b3aec3c..1692bd4c392c 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Хабарландырулар Мазаламау режимінде кідіртілді"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Қазір бастау"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Хабарландырулар жоқ"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Жаңа хабарландырулар жоқ"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Ескі хабарландырулар үшін құлыпты ашыңыз"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Бұл құрылғыны ата-анаңыз басқарады."</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ұйымыңыз осы құрылғыны басқарады және желі трафигін бақылауы мүмкін."</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> осы құрылғыны басқарады және желі трафигін бақылауы мүмкін."</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Трансляцияны тоқтату"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Аудио шығыс үшін қолжетімді құрылғылар бар."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Дыбыс деңгейі"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Тарату қалай жүзеге асады"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Тарату"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Үйлесімді Bluetooth құрылғылары бар маңайдағы адамдар сіз таратып жатқан медиамазмұнды тыңдай алады."</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера мен микрофон өшірулі"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# хабарландыру}other{# хабарландыру}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Ескертпе жазу"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Таратуда"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын таратуды тоқтатасыз ба?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> қолданбасын таратсаңыз немесе аудио шығысын өзгертсеңіз, қазіргі тарату сеансы тоқтайды."</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> қолданбасын тарату"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Аудио шығысын өзгерту"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Белгісіз"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"d MMM EEEE"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ашу"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Жақсырақ селфи үшін алдыңғы экранға ауысасыз ба?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Ажыратымдылығы жоғары кеңірек фотосурет түсіру үшін артқы камераны пайдаланыңыз."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Бұл экран өшіріледі."</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 13bd2c3b211f..9158663983c7 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"ការជូនដំណឹងបានផ្អាកដោយមុខងារកុំរំខាន"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"ចាប់ផ្ដើមឥឡូវ"</string> <string name="empty_shade_text" msgid="8935967157319717412">"គ្មានការជូនដំណឹង"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"គ្មានការជូនដំណឹងថ្មីៗទេ"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ដោះសោដើម្បីមើលការជូនដំណឹងចាស់ៗ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ឧបករណ៍នេះស្ថិតក្រោមការគ្រប់គ្រងរបស់មាតាបិតាអ្នក"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ស្ថាប័នរបស់អ្នកជាម្ចាស់ឧបករណ៍នេះ ហើយអាចនឹងតាមដានចរាចរណ៍បណ្តាញ"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ជាម្ចាស់ឧបករណ៍នេះ ហើយអាចនឹងតាមដានចរាចរណ៍បណ្តាញ"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"បញ្ឈប់ការភ្ជាប់"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ឧបករណ៍ដែលអាចប្រើបានសម្រាប់ឧបករណ៍បញ្ចេញសំឡេង។"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"កម្រិតសំឡេង"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"របៀបដែលការផ្សាយដំណើរការ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ការផ្សាយ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"មនុស្សនៅជិតអ្នកដែលមានឧបករណ៍ប៊្លូធូសត្រូវគ្នាអាចស្តាប់មេឌៀដែលអ្នកកំពុងផ្សាយបាន"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"កាមេរ៉ា និងមីក្រូហ្វូនត្រូវបានបិទ"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{ការជូនដំណឹង #}other{ការជូនដំណឹង #}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"ការកត់ត្រា"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ការផ្សាយ"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"បញ្ឈប់ការផ្សាយ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ប្រសិនបើអ្នកផ្សាយ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ឬប្ដូរឧបករណ៍បញ្ចេញសំឡេង ការផ្សាយបច្ចុប្បន្នរបស់អ្នកនឹងបញ្ឈប់"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"ការផ្សាយ <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"ប្ដូរឧបករណ៍បញ្ចេញសំឡេង"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"មិនស្គាល់"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"បើក <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ត្រឡប់ទៅផ្ទាំងអេក្រង់ខាងមុខ ដើម្បីថតសែលហ្វីកាន់តែបានល្អឬ?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ប្រើកាមេរ៉ាខាងក្រោយ ដើម្បីទទួលបានរូបថតកាន់តែធំជាមួយនឹងកម្រិតគុណភាពកាន់តែខ្ពស់។"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ អេក្រង់នេះនឹងបិទ"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 106b78b09086..abfa865390c3 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಎನ್ನುವ ಮೂಲಕ ಅಧಿಸೂಚನೆಗಳನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"ಈಗ ಪ್ರಾರಂಭಿಸಿ"</string> <string name="empty_shade_text" msgid="8935967157319717412">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"ಯಾವುದೇ ಹೊಸ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ಹಳೆಯ ಅಧಿಸೂಚನೆಗಳನ್ನು ನೋಡಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ಈ ಸಾಧನವನ್ನು ನಿಮ್ಮ ಪೋಷಕರು ನಿರ್ವಹಿಸುತ್ತಿದ್ದಾರೆ"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಸಾಧನದ ಮಾಲೀಕತ್ವವನ್ನು ಹೊಂದಿದೆ ಮತ್ತು ಅದು ನೆಟ್ವರ್ಕ್ ಟ್ರಾಫಿಕ್ನ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಈ ಸಾಧನದ ಮಾಲೀಕತ್ವವನ್ನು ಹೊಂದಿದೆ ಮತ್ತು ಅದು ನೆಟ್ವರ್ಕ್ ಟ್ರಾಫಿಕ್ನ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ಬಿತ್ತರಿಸುವುದನ್ನು ನಿಲ್ಲಿಸಿ"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ಆಡಿಯೋ ಔಟ್ಪುಟ್ಗಾಗಿ ಲಭ್ಯವಿರುವ ಸಾಧನಗಳು."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ವಾಲ್ಯೂಮ್"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ಪ್ರಸಾರವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ಪ್ರಸಾರ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ಹೊಂದಾಣಿಕೆಯಾಗುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಹೊಂದಿರುವ ಸಮೀಪದಲ್ಲಿರುವ ಜನರು ನೀವು ಪ್ರಸಾರ ಮಾಡುತ್ತಿರುವ ಮಾಧ್ಯಮವನ್ನು ಆಲಿಸಬಹುದು"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ ಆಫ್ ಆಗಿದೆ"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ಅಧಿಸೂಚನೆ}one{# ಅಧಿಸೂಚನೆಗಳು}other{# ಅಧಿಸೂಚನೆಗಳು}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"ಟಿಪ್ಪಣಿಗಳನ್ನು ಬರೆದುಕೊಳ್ಳುವುದು"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ಪ್ರಸಾರ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಪ್ರಸಾರವನ್ನು ನಿಲ್ಲಿಸಬೇಕೆ?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ನೀವು <xliff:g id="SWITCHAPP">%1$s</xliff:g> ಅನ್ನು ಪ್ರಸಾರ ಮಾಡಿದರೆ ಅಥವಾ ಔಟ್ಪುಟ್ ಅನ್ನು ಬದಲಾಯಿಸಿದರೆ, ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಪ್ರಸಾರವು ಸ್ಥಗಿತಗೊಳ್ಳುತ್ತದೆ"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ಅನ್ನು ಪ್ರಸಾರ ಮಾಡಿ"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"ಔಟ್ಪುಟ್ ಅನ್ನು ಬದಲಾಯಿಸಿ"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"ಅಪರಿಚಿತ"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ಉತ್ತಮ ಸೆಲ್ಫೀಗಾಗಿ ಮುಂಭಾಗದ ಕ್ಯಾಮರಾಗೆ ಫ್ಲಿಪ್ ಮಾಡಬೇಕೆ?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ಹೆಚ್ಚಿನ ರೆಸಲ್ಯೂಷನ್ ಹೊಂದಿರುವ ವಿಶಾಲವಾದ ಫೋಟೋಗಾಗಿ ಹಿಂಭಾಗದ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಿ."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ಈ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index dbca672b0043..d1ca240bc60e 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"방해 금지 모드로 알림이 일시중지됨"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"시작하기"</string> <string name="empty_shade_text" msgid="8935967157319717412">"알림 없음"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"새로운 알림 없음"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"잠금 해제하여 이전 알림 보기"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"부모님이 관리하는 기기입니다."</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"내 조직에서 이 기기를 소유하며 네트워크 트래픽을 모니터링할 수 있습니다."</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>에서 이 기기를 소유하며 네트워크 트래픽을 모니터링할 수 있습니다."</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"전송 중지"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"오디오 출력에 사용 가능한 기기입니다."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"볼륨"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"브로드캐스팅 작동 원리"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"브로드캐스트"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"호환되는 블루투스 기기를 가진 근처의 사용자가 내가 브로드캐스트 중인 미디어를 수신 대기할 수 있습니다."</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"카메라 및 마이크가 사용 중지되었습니다."</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{알림 #개}other{알림 #개}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"메모"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"방송 중"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> 방송을 중지하시겠습니까?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> 앱을 방송하거나 출력을 변경하면 기존 방송이 중단됩니다"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> 방송"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"출력 변경"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"알 수 없음"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"MMM d일 EEE"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> 열기"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"전면 디스플레이가 보이도록 뒤집어서 더 나은 셀카를 찍어보세요"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"후면 카메라를 통해 넓은 각도로 해상도가 높은 사진을 찍어보세요."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 이 화면이 꺼집니다."</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 8460e32bc73f..93092ce0643d 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\"Тынчымды алба\" режиминде билдирмелер тындырылды"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Азыр баштоо"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Билдирме жок"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Жаңы билдирмелер жок"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Билдирмелерди көрүү үчүн кулпуну ачыңыз"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Бул түзмөктү ата-энең башкарат"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Бул түзмөк уюмуңузга таандык. Уюмуңуз тармактын трафигин көзөмөлдөй алат"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Бул түзмөк <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> уюмуна таандык. Уюм тармактын трафигин көзөмөлдөй алат"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Тышкы экранга чыгарууну токтотуу"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Аудио чыгаруу үчүн жеткиликтүү түзмөктөр."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Үндүн катуулугу"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Кабарлоо кантип иштейт"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Кабарлоо"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Шайкеш Bluetooth түзмөктөрү болгон жакын жердеги кишилер кабарлап жаткан медиаңызды уга алышат"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера жана микрофон өчүк"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# билдирме}other{# билдирме}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Эскертме жазуу"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Кеңири таратуу"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда кабарлоо токтотулсунбу?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Эгер <xliff:g id="SWITCHAPP">%1$s</xliff:g> колдонмосунда кабарласаңыз же аудионун чыгуусун өзгөртсөңүз, учурдагы кабарлоо токтотулат"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> колдонмосунда кабарлоо"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Аудионун чыгуусун өзгөртүү"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Белгисиз"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ачуу"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Жакшы селфи тартуу үчүн маңдайкы экранга которосузбу?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Кең жана жогорку дааналыктагы сүрөттү тартуу үчүн негизги камераны колдонуңуз."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Бул экран өчөт"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 126161319889..906c72308cda 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ຢຸດການສົ່ງສັນຍານ"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ອຸປະກອນທີ່ສາມາດໃຊ້ໄດ້ສຳລັບເອົ້າພຸດສຽງ."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ລະດັບສຽງ"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ການອອກອາກາດເຮັດວຽກແນວໃດ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ອອກອາກາດ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ຄົນທີ່ຢູ່ໃກ້ທ່ານທີ່ມີອຸປະກອນ Bluetooth ທີ່ເຂົ້າກັນໄດ້ຈະສາມາດຟັງມີເດຍທີ່ທ່ານກຳລັງອອກອາກາດຢູ່ໄດ້"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ປິດກ້ອງຖ່າຍຮູບ ແລະ ໄມແລ້ວ"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ການແຈ້ງເຕືອນ}other{# ການແຈ້ງເຕືອນ}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"ການຈົດບັນທຶກ"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ກຳລັງອອກອາກາດ"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"ຢຸດການອອກອາກາດ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ຫາກທ່ານອອກອາກາດ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ຫຼື ປ່ຽນເອົ້າພຸດ, ການອອກອາກາດປັດຈຸບັນຂອງທ່ານຈະຢຸດ"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"ອອກອາກາດ <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"ປ່ຽນເອົ້າພຸດ"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"ບໍ່ຮູ້ຈັກ"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"ຊມ:ນທ"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"ຊມ:ນທ"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"ເປີດ <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ປີ້ນເປັນຈໍສະແດງຜົນດ້ານໜ້າເພື່ອການຖ່າຍເຊວຟີທີ່ດີຂຶ້ນບໍ?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ໃຊ້ກ້ອງຫຼັງເພື່ອການຖ່າຍຮູບທີ່ກວ້າງຂຶ້ນດ້ວຍຄວາມລະອຽດສູງຂຶ້ນ."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ໜ້າຈໍນີ້ຈະປິດ"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 8db0454162bf..789b2b94345b 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Pranešimai pristabdyti naudojant netrukdymo režimą"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Pradėti dabar"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nėra įspėjimų"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Naujų pranešimų nėra"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Atrakinę matykite senesnius pranešimus"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Šį įrenginį tvarko vienas iš tavo tėvų"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Šis įrenginys priklauso jūsų organizacijai ir ji gali stebėti tinklo srautą"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Šis įrenginys priklauso „<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>“ ir ji gali stebėti tinklo srautą"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Sustabdyti perdavimą"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Pasiekiami garso išvesties įrenginiai."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Garsumas"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kaip veikia transliacija"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transliacija"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Netoliese esantys žmonės, turintys suderinamus „Bluetooth“ įrenginius, gali klausyti jūsų transliuojamos medijos"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Vaizdo kamera ir mikrofonas išjungti"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# pranešimas}one{# pranešimas}few{# pranešimai}many{# pranešimo}other{# pranešimų}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Užrašų kūrimas"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transliavimas"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Sustabdyti „<xliff:g id="APP_NAME">%1$s</xliff:g>“ transliaciją?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jei transliuosite „<xliff:g id="SWITCHAPP">%1$s</xliff:g>“ arba pakeisite išvestį, dabartinė transliacija bus sustabdyta"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Transliuoti „<xliff:g id="SWITCHAPP">%1$s</xliff:g>“"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Keisti išvestį"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Nežinoma"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Atidaryti „<xliff:g id="APPNAME">%1$s</xliff:g>“"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Užfiksuoti geresnę asmenukę įjungus priekinį rodinį?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Naudokite galinį fotoaparatą, kad nuotrauka būtų platesnė ir didesnės skyros."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Šis ekranas išsijungs"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 3698c3a9968a..dbdbf71b2ce4 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -180,10 +180,10 @@ <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lidmašīnas režīms."</string> <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ieslēgts"</string> <string name="accessibility_battery_level" msgid="5143715405241138822">"Akumulators: <xliff:g id="NUMBER">%d</xliff:g> procenti"</string> - <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>%% procenti, <xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>%%, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Notiek akumulatora uzlāde, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string> - <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%d</xliff:g>%% procenti, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string> - <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>%% procenti, <xliff:g id="TIME">%2$s</xliff:g>, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string> + <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%d</xliff:g>%%, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string> + <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>%%, <xliff:g id="TIME">%2$s</xliff:g>, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string> <string name="accessibility_overflow_action" msgid="8555835828182509104">"Skatīt visus paziņojumus"</string> <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletaips ir iespējots."</string> <string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zvana signāls — vibrācija."</string> @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Paziņojumi pārtraukti, izmantojot iestatījumu “Netraucēt”"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Sākt tūlīt"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nav paziņojumu"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Nav jaunu paziņojumu"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Atbloķējiet vecāku paziņojumu skatīšanai"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Šo ierīci pārvalda viens no jūsu vecākiem."</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Šī ierīce pieder jūsu organizācijai, un jūsu organizācija var uzraudzīt tīkla datplūsmu."</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Šī ierīce pieder organizācijai<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, un šī organizācija var uzraudzīt tīkla datplūsmu."</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Apturēt apraidi"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Audio izvadei pieejamās ierīces."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Skaļums"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kā darbojas apraide"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Apraide"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Tuvumā esošās personas ar saderīgām Bluetooth ierīcēm var klausīties jūsu apraidīto multivides saturu."</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera un mikrofons ir izslēgti"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# paziņojums}zero{# paziņojumu}one{# paziņojums}other{# paziņojumi}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Piezīmju pierakstīšana"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Notiek apraidīšana"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vai apturēt lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> apraidīšanu?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ja sāksiet lietotnes <xliff:g id="SWITCHAPP">%1$s</xliff:g> apraidīšanu vai mainīsiet izvadi, pašreizējā apraide tiks apturēta"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Lietotnes <xliff:g id="SWITCHAPP">%1$s</xliff:g> apraide"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Izvades maiņa"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Nezināms"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d. MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"hh:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Atvērt lietotni <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vai apvērst uz priekšējo kameru labākai pašbildei?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Lai uzņemtu platāku fotoattēlu ar augstāku izšķirtspēju, izmantojiet aizmugurējo kameru."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Šis ekrāns tiks izslēgts."</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index e8b779714b1b..2d35cdb7609e 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Сопри со емитување"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Достапни уреди за аудиоизлез."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Јачина на звук"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционира емитувањето"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Емитување"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Луѓето во ваша близина со компатибилни уреди со Bluetooth може да ги слушаат аудиозаписите што ги емитувате"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камерата и микрофонот се исклучени"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# известување}one{# известување}other{# известувања}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Фаќање белешки"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Емитување"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Да се прекине емитувањето на <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ако емитувате на <xliff:g id="SWITCHAPP">%1$s</xliff:g> или го промените излезот, тековното емитување ќе запре"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Емитување на <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Променете излез"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Непознато"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Отворете ја <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Да се префрли на предниот екран за подобро селфи?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Користете ја задната камера за поширока фотографија со повисока резолуција."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Екранов ќе се исклучи"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 1a6d70f39fd6..409b578ef2e6 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'ശല്യപ്പെടുത്തരുത്\' വഴി അറിയിപ്പുകൾ താൽക്കാലികമായി നിർത്തി"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"ഇപ്പോൾ ആരംഭിക്കുക"</string> <string name="empty_shade_text" msgid="8935967157319717412">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"പുതിയ അറിയിപ്പുകളൊന്നുമില്ല"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"പഴയ അറിയിപ്പുകൾ കാണാൻ അൺലോക്ക് ചെയ്യുക"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ഈ ഉപകരണം മാനേജ് ചെയ്യുന്നത് നിങ്ങളുടെ രക്ഷിതാവാണ്"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റെ ഉടമസ്ഥതയിലായതിനാൽ നെറ്റ്വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിച്ചേക്കാം"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"ഈ ഉപകരണം <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> എന്ന സ്ഥാപനത്തിന്റെ ഉടമസ്ഥതയിലായതിനാൽ നെറ്റ്വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിച്ചേക്കാം"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"കാസ്റ്റ് ചെയ്യുന്നത് നിർത്തുക"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ഓഡിയോ ഔട്ട്പുട്ടിന് ലഭ്യമായ ഉപകരണങ്ങൾ."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"വോളിയം"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ബ്രോഡ്കാസ്റ്റ് എങ്ങനെയാണ് പ്രവർത്തിക്കുന്നത്"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ബ്രോഡ്കാസ്റ്റ്"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"അനുയോജ്യമായ Bluetooth ഉപകരണങ്ങളോടെ സമീപമുള്ള ആളുകൾക്ക് നിങ്ങൾ ബ്രോഡ്കാസ്റ്റ് ചെയ്യുന്ന മീഡിയ കേൾക്കാനാകും"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ക്യാമറയും മൈക്കും ഓഫാണ്"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# അറിയിപ്പ്}other{# അറിയിപ്പുകൾ}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"കുറിപ്പ് രേഖപ്പെടുത്തൽ"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"പ്രക്ഷേപണം ചെയ്യുന്നു"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബ്രോഡ്കാസ്റ്റ് ചെയ്യുന്നത് അവസാനിപ്പിക്കണോ?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"നിങ്ങൾ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ബ്രോഡ്കാസ്റ്റ് ചെയ്യുകയോ ഔട്ട്പുട്ട് മാറ്റുകയോ ചെയ്താൽ നിങ്ങളുടെ നിലവിലുള്ള ബ്രോഡ്കാസ്റ്റ് അവസാനിക്കും"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ബ്രോഡ്കാസ്റ്റ് ചെയ്യുക"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"ഔട്ട്പുട്ട് മാറ്റുക"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"അജ്ഞാതം"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> തുറക്കുക"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"മികച്ച സെൽഫിക്ക് ഫ്രണ്ട് ഡിസ്പ്ലേയിലേക്ക് മാറണോ?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ഉയർന്ന റെസല്യൂഷൻ ഉള്ള, വീതി കൂടിയ ഫോട്ടോയ്ക്ക്, പിൻഭാഗത്തെ ക്യാമറ ഉപയോഗിക്കുക."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ഈ സ്ക്രീൻ ഓഫാകും"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 1e1efcfeb510..8c3a70ff057e 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Дамжуулахыг зогсоох"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Аудио гаралт хийх боломжтой төхөөрөмжүүд."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Дууны түвшин"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Нэвтрүүлэлт хэрхэн ажилладаг вэ?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Нэвтрүүлэлт"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Тохиромжтой Bluetooth төхөөрөмжүүдтэй таны ойролцоох хүмүүс таны нэвтрүүлж буй медиаг сонсох боломжтой"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камер болон микрофон унтраалттай байна"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# мэдэгдэл}other{# мэдэгдэл}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Тэмдэглэл хөтлөх"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Нэвтрүүлэлт"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г нэвтрүүлэхээ зогсоох уу?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Хэрэв та <xliff:g id="SWITCHAPP">%1$s</xliff:g>-г нэвтрүүлсэн эсвэл гаралтыг өөрчилсөн бол таны одоогийн нэвтрүүлэлтийг зогсооно"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g>-г нэвтрүүлэх"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Гаралтыг өөрчлөх"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Тодорхойгүй"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"MMM d EEE"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g>-г нээх"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Сайн сельфи авахаар урд талын дэлгэц рүү хөнтрөх үү?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Илүү өндөр нягтаршилтай илүү өргөн зураг авахын тулд арын камерыг ашиглана уу."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Энэ дэлгэц унтарна"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 9e4144793fe5..658305710d6a 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"व्यत्यय आणून नकाद्वारे सूचना थांबवल्या"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"आता सुरू करा"</string> <string name="empty_shade_text" msgid="8935967157319717412">"सूचना नाहीत"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"नवीन सूचना नाहीत"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"जुन्या सूचना पहाण्यासाठी अनलॉक करा"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"हे डिव्हाइस तुमच्या पालकाने व्यवस्थापित केले आहे"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"तुमच्या संस्थेकडे या डिव्हाइसची मालकी आहे आणि ती नेटवर्क ट्रॅफिकचे परीक्षण करू शकते"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> च्या मालकीचे आहे आणि ती नेटवर्क ट्रॅफिकचे परीक्षण करू शकते"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्ट करणे थांबवा"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ऑडिओ आउटपुटसाठी उपलब्ध डिव्हाइस."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"व्हॉल्यूम"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ब्रॉडकास्टिंग कसे काम करते"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ब्रॉडकास्ट करा"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"कंपॅटिबल ब्लूटूथ डिव्हाइस असलेले तुमच्या जवळपासचे लोक हे तुम्ही ब्रॉडकास्ट करत असलेला मीडिया ऐकू शकतात"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"कॅमेरा आणि माइक बंद आहेत"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# सूचना}other{# सूचना}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"नोटटेकिंग"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ब्रॉडकास्ट करत आहे"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> चे प्रसारण थांबवायचे आहे का?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"तुम्ही <xliff:g id="SWITCHAPP">%1$s</xliff:g> चे प्रसारण केल्यास किंवा आउटपुट बदलल्यास, तुमचे सध्याचे प्रसारण बंद होईल"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> चे प्रसारण करा"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"आउटपूट बदला"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"अज्ञात"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> उघडा"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"आणखी चांगल्या सेल्फीसाठी फ्रंट डिस्प्ले वापरायचा का?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"उच्च रेझोल्यूशन असलेल्या विस्तृत फोटोसाठी रीअर कॅमेरा वापरा."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ही स्क्रीन बंद होईल"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index fbfee35b2b5f..014011247ee8 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Berhenti menghantar"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Peranti tersedia untuk audio output."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Kelantangan"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cara siaran berfungsi"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Siarkan"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Orang berdekatan anda dengan peranti Bluetooth yang serasi boleh mendengar media yang sedang anda siarkan"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera dan mikrofon dimatikan"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# pemberitahuan}other{# pemberitahuan}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Pengambilan nota"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Menyiarkan"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Hentikan siaran <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jika anda siarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g> atau tukarkan output, siaran semasa anda akan berhenti"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Siarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Tukar output"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Tidak diketahui"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Buka <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Balikkan ke paparan depan utk swafoto lebih baik?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gunakan kamera menghadap belakang untuk mendapatkan foto yang lebih luas dengan resolusi yang lebih tinggi."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Skrin ini akan dimatikan"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 3b4fd221410c..164d662f969b 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -874,8 +874,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ကာစ် ရပ်ရန်"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"အသံအထွက်အတွက် ရရှိနိုင်သောစက်များ။"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"အသံအတိုးအကျယ်"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ထုတ်လွှင့်မှုဆောင်ရွက်ပုံ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ထုတ်လွှင့်ခြင်း"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"အနီးရှိတွဲသုံးနိုင်သော ဘလူးတုသ်သုံးစက် အသုံးပြုသူများက သင်ထုတ်လွှင့်နေသော မီဒီယာကို နားဆင်နိုင်သည်"</string> @@ -989,15 +988,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ကင်မရာနှင့် မိုက် ပိတ်ထားသည်"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{အကြောင်းကြားချက် # ခု}other{အကြောင်းကြားချက် # ခု}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>၊ <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"မှတ်စုလိုက်ခြင်း"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ထုတ်လွှင့်ခြင်း"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ထုတ်လွှင့်ခြင်းကို ရပ်မလား။"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ကို ထုတ်လွှင့်သောအခါ (သို့) အထွက်ကို ပြောင်းသောအခါ သင့်လက်ရှိထုတ်လွှင့်ခြင်း ရပ်သွားမည်"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ထုတ်လွှင့်ခြင်း"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"အထွက်ကို ပြောင်းခြင်း"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"မသိ"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE၊ MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ဖွင့်ရန်"</string> @@ -1013,4 +1010,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ပိုကောင်းသော ဆယ်လ်ဖီအတွက် ဖန်သားပြင်ကိုလှည့်မလား။"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ပုံရိပ်ပြတ်သားကိန်း ပိုမြင့်ပြီး မြင်ကွင်းပိုကျယ်သည့် ဓာတ်ပုံအတွက် နောက်ဘက်ကင်မရာကို အသုံးပြုပါ။"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ဤဖန်သားပြင်ကို ပိတ်လိုက်မည်"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 79b886d946c1..6288a15b1d4e 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Varsler er satt på pause av «Ikke forstyrr»"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Start nå"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ingen varsler"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Ingen nye varsler"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Lås opp for å se eldre varsler"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Denne enheten administreres av forelderen din"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisasjonen din eier denne enheten og kan overvåke nettverkstrafikken"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> eier denne enheten og kan overvåke nettverkstrafikken"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Stopp castingen"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Tilgjengelige enheter for lydutgang."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volum"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Slik fungerer kringkasting"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Kringkasting"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Folk i nærheten med kompatible Bluetooth-enheter kan lytte til mediene du kringkaster"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera og mikrofon er av"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# varsel}other{# varsler}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Notatskriving"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Kringkaster"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vil du stoppe kringkastingen av <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Hvis du kringkaster <xliff:g id="SWITCHAPP">%1$s</xliff:g> eller endrer utgangen, stopper den nåværende kringkastingen din"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Kringkast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Endre utgang"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Ukjent"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE d. MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Åpne <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vil du bytte til frontskjermen for bedre selfier?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Bruk det bakovervendte kameraet for å ta bredere bilder med høyere oppløsning."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Denne skjermen slås av"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index aecb12abc644..563d6082cf9d 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"बाधा नपुऱ्याउनुहोस् नामक मोडमार्फत पज पारिएका सूचनाहरू"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"अहिले न"</string> <string name="empty_shade_text" msgid="8935967157319717412">"कुनै सूचनाहरू छैनन्"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"कुनै पनि नयाँ सूचना छैन"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"पुराना सूचनाहरू हेर्न अनलक गर्नुहोस्"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"यो डिभाइस तपाईंका अभिभावक व्यवस्थापन गर्नुहुन्छ"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"यो डिभाइस तपाईंको सङ्गठनको स्वामित्वमा छ र उक्त सङ्गठनले यसको नेटवर्क ट्राफिक अनुगमन गर्न सक्छ"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"यो डिभाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> को स्वामित्वमा छ र उक्त सङ्गठनले यसको नेटवर्क ट्राफिक अनुगमन गर्न सक्छ"</string> @@ -502,8 +500,7 @@ <string name="wallet_error_generic" msgid="257704570182963611">"तपाईंका कार्डहरू प्राप्त गर्ने क्रममा समस्या भयो, कृपया पछि फेरि प्रयास गर्नुहोस्"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लक स्क्रिनसम्बन्धी सेटिङ"</string> <string name="qr_code_scanner_title" msgid="1938155688725760702">"QR कोड स्क्यानर"</string> - <!-- no translation found for qr_code_scanner_updating_secondary_label (8344598017007876352) --> - <skip /> + <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"अपडेट गरिँदै छ"</string> <string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाइल"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"हवाइजहाज मोड"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"तपाईँले आफ्नो अर्को अलार्म <xliff:g id="WHEN">%1$s</xliff:g> सुन्नुहुने छैन"</string> @@ -875,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्ट गर्न छाड्नुहोस्"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"अडियो आउटपुटका लागि उपलब्ध डिभाइसहरू।"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"भोल्युम"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"प्रसारण गर्ने सुविधाले कसरी काम गर्छ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"प्रसारण"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"कम्प्याटिबल ब्लुटुथ डिभाइस भएका नजिकैका मान्छेहरू तपाईंले प्रसारण गरिरहनुभएको मिडिया सुन्न सक्छन्"</string> @@ -990,35 +986,30 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"क्यामेरा र माइक अफ छन्"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# वटा सूचना}other{# वटा सूचनाहरू}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"टिपोट गर्ने कार्य"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"प्रसारण गरिँदै छ"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ब्रोडकास्ट गर्न छाड्ने हो?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"तपाईंले <xliff:g id="SWITCHAPP">%1$s</xliff:g> ब्रोडकास्ट गर्नुभयो वा आउटपुट परिवर्तन गर्नुभयो भने तपाईंको हालको ब्रोडकास्ट रोकिने छ"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ब्रोडकास्ट गर्नुहोस्"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"आउटपुट परिवर्तन गर्नुहोस्"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"अज्ञात"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> - <!-- no translation found for keyguard_affordance_enablement_dialog_action_template (8164857863036314664) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_message (2790910660524887941) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_wallet_instruction_1 (8439655049139819278) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_wallet_instruction_2 (4321089250629477835) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_qr_scanner_instruction (5355839079232119791) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_home_instruction_1 (8438311171750568633) --> - <skip /> - <!-- no translation found for keyguard_affordance_enablement_dialog_home_instruction_2 (8308525385889021652) --> - <skip /> + <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> खोल्नुहोस्"</string> + <string name="keyguard_affordance_enablement_dialog_message" msgid="2790910660524887941">"<xliff:g id="APPNAME">%1$s</xliff:g> एपलाई सर्टकटका रूपमा हाल्न, निम्न कुराको सुनिश्चित गर्नुहोस्:"</string> + <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• एप सेटअप गरिएको छ"</string> + <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet मा कम्तीमा एउटा कार्ड हालिएको छ"</string> + <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• क्यामेरा एप इन्स्टल गरिएको छ"</string> + <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• एप सेटअप गरिएको छ"</string> + <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• कम्तीमा एउटा डिभाइस उपलब्ध छ"</string> <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द गर्नुहोस्"</string> <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"अहिले नै फ्लिप गर्नुहोस्"</string> <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"अझ राम्रो सेल्फी खिच्न फोन अनफोल्ड गर्नुहोस्"</string> <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"अझ राम्रो सेल्फी खिच्न फ्लिप गरी अगाडिपट्टिको डिस्प्ले प्रयोग गर्ने हो?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"अझ बढी रिजोल्युसन भएको फराकिलो फोटो खिच्न पछाडिपट्टिको क्यामेरा प्रयोग गर्नुहोस्।"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ यो स्क्रिन अफ हुने छ"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 37a119320d60..ee73a6fcc9cb 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Casten stoppen"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Beschikbare apparaten voor audio-uitvoer."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Hoe uitzenden werkt"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Uitzending"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Mensen bij jou in de buurt met geschikte bluetooth-apparaten kunnen luisteren naar de media die je uitzendt"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera en microfoon staan uit"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# melding}other{# meldingen}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Aantekeningen maken"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Uitzending"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Uitzending van <xliff:g id="APP_NAME">%1$s</xliff:g> stopzetten?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Als je <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitzendt of de uitvoer wijzigt, wordt je huidige uitzending gestopt"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> uitzenden"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Uitvoer wijzigen"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Onbekend"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE d mmm"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"u:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> openen"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Omkeren naar scherm voorkant voor een betere selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gebruik de camera aan de achterzijde voor een bredere foto met hogere resolutie."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Dit scherm gaat uit"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index ecb863d514d6..455f1f9f8374 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ବିକଳ୍ପ ଦ୍ୱାରା ବିଜ୍ଞପ୍ତି ପଜ୍ ହୋଇଛି"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"ବର୍ତ୍ତମାନ ଆରମ୍ଭ କରନ୍ତୁ"</string> <string name="empty_shade_text" msgid="8935967157319717412">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"କୌଣସି ନୂଆ ବିଜ୍ଞପ୍ତି ନାହିଁ"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ପୁରୁଣା ବିଜ୍ଞପ୍ତି ଦେଖିବାକୁ ଅନଲକ କରନ୍ତୁ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ଏହି ଡିଭାଇସ୍ ଆପଣଙ୍କ ବାପାମାଙ୍କ ଦ୍ୱାରା ପରିଚାଳିତ"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ଏହି ଡିଭାଇସର ମାଲିକାନା ଆପଣଙ୍କ ସଂସ୍ଥା ପାଖରେ ଅଛି ଏବଂ ଏହା ନେଟୱାର୍କ ଟ୍ରାଫିକର ନିରୀକ୍ଷଣ କରିପାରେ"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"ଏହି ଡିଭାଇସଟି <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ର ଅଟେ ଏବଂ ଏହା ନେଟୱାର୍କ ଟ୍ରାଫିକକୁ ନିରୀକ୍ଷଣ କରିପାରେ"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"କାଷ୍ଟ କରିବା ବନ୍ଦ କରନ୍ତୁ"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ଅଡିଓ ଆଉଟପୁଟ ପାଇଁ ଉପଲବ୍ଧ ଡିଭାଇସଗୁଡ଼ିକ।"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ଭଲ୍ୟୁମ"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ବ୍ରଡକାଷ୍ଟିଂ କିପରି କାମ କରେ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ବ୍ରଡକାଷ୍ଟ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ଆପଣଙ୍କ ଆଖପାଖର କମ୍ପାଟିବଲ ବ୍ଲୁଟୁଥ ଡିଭାଇସ ଥିବା ଲୋକମାନେ ଆପଣ ବ୍ରଡକାଷ୍ଟ କରୁଥିବା ମିଡିଆ ଶୁଣିପାରିବେ"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"କ୍ୟାମେରା ଏବଂ ମାଇକ ବନ୍ଦ ଅଛି"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{#ଟି ବିଜ୍ଞପ୍ତି}other{#ଟି ବିଜ୍ଞପ୍ତି}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"ନୋଟଟେକିଂ"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ବ୍ରଡକାଷ୍ଟ କରୁଛି"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରିବା ବନ୍ଦ କରିବେ?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ଯଦି ଆପଣ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରନ୍ତି କିମ୍ବା ଆଉଟପୁଟ ବଦଳାନ୍ତି, ତେବେ ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ବ୍ରଡକାଷ୍ଟ ବନ୍ଦ ହୋଇଯିବ"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରନ୍ତୁ"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"ଆଉଟପୁଟ ବଦଳାନ୍ତୁ"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"ଅଜଣା"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ଖୋଲନ୍ତୁ"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ଏକ ଉନ୍ନତ ସେଲ୍ଫି ପାଇଁ ସାମ୍ନା ଡିସପ୍ଲେକୁ ଫ୍ଲିପ କରିବେ?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ଉଚ୍ଚ ରିଜୋଲ୍ୟୁସନ ସହ ଅଧିକ ଚଉଡ଼ାର ଏକ ଫଟୋ ନେବା ପାଇଁ ପଛ-ପଟର କେମେରା ବ୍ୟବହାର କରନ୍ତୁ।"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ଏହି ସ୍କ୍ରିନ ବନ୍ଦ ହୋଇଯିବ"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 69ce9a2aba9d..3e3d3e86a0fd 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਵੱਲੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਰੋਕਿਆ ਗਿਆ"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"ਹੁਣੇ ਸ਼ੁਰੂ ਕਰੋ"</string> <string name="empty_shade_text" msgid="8935967157319717412">"ਕੋਈ ਸੂਚਨਾਵਾਂ ਨਹੀਂ"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"ਕੋਈ ਨਵੀਂ ਸੂਚਨਾ ਨਹੀਂ"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ਪੁਰਾਣੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਕੋਲ ਇਸ ਡੀਵਾਈਸ ਦੀ ਮਲਕੀਅਤ ਹੈ ਅਤੇ ਇਹ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ਕੋਲ ਇਸ ਡੀਵਾਈਸ ਦੀ ਮਲਕੀਅਤ ਹੈ ਅਤੇ ਇਹ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ਕਾਸਟ ਕਰਨਾ ਬੰਦ ਕਰੋ"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ਆਡੀਓ ਆਊਟਪੁੱਟ ਲਈ ਉਪਲਬਧ ਡੀਵਾਈਸ।"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ਅਵਾਜ਼"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ਪ੍ਰਸਾਰਨ ਕਿਵੇਂ ਕੰਮ ਕਰਦਾ ਹੈ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ਪ੍ਰਸਾਰਨ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ਅਨੁਰੂਪ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨਾਲ ਨਜ਼ਦੀਕੀ ਲੋਕ ਤੁਹਾਡੇ ਵੱਲੋਂ ਪ੍ਰਸਾਰਨ ਕੀਤੇ ਜਾ ਰਹੇ ਮੀਡੀਆ ਨੂੰ ਸੁਣ ਸਕਦੇ ਹਨ"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ ਬੰਦ ਹਨ"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ਸੂਚਨਾ}one{# ਸੂਚਨਾ}other{# ਸੂਚਨਾਵਾਂ}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"ਨੋਟ ਬਣਾਉਣਾ"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ਪ੍ਰਸਾਰਨ"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਦੇ ਪ੍ਰਸਾਰਨ ਨੂੰ ਰੋਕਣਾ ਹੈ?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ਜੇ ਤੁਸੀਂ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ਦਾ ਪ੍ਰਸਾਰਨ ਕਰਦੇ ਹੋ ਜਾਂ ਆਊਟਪੁੱਟ ਬਦਲਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਮੌਜੂਦਾ ਪ੍ਰਸਾਰਨ ਰੁਕ ਜਾਵੇਗਾ"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ਦਾ ਪ੍ਰਸਾਰਨ ਕਰੋ"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"ਆਊਟਪੁੱਟ ਬਦਲੋ"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"ਅਗਿਆਤ"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ਖੋਲ੍ਹੋ"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ਕੀ ਬਿਹਤਰ ਸੈਲਫ਼ੀ ਲਈ ਅਗਲੀ ਡਿਸਪਲੇ \'ਤੇ ਫਲਿੱਪ ਕਰਨਾ ਹੈ?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ਉੱਚ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਵਾਲੀ ਜ਼ਿਆਦਾ ਚੌੜੀ ਫ਼ੋਟੋ ਲਈ ਪਿਛਲੇ ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਕਰੋ।"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ਇਹ ਸਕ੍ਰੀਨ ਬੰਦ ਹੋ ਜਾਵੇਗੀ"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 7944276b93f8..1b68eecdcae0 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Powiadomienia wstrzymane przez tryb Nie przeszkadzać"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Rozpocznij teraz"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Brak powiadomień"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Brak nowych powiadomień"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odblokuj i zobacz starsze powiadomienia"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Tym urządzeniem zarządza Twój rodzic"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Twoja organizacja jest właścicielem tego urządzenia i może monitorować ruch w sieci"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Organizacja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> jest właścicielem tego urządzenia i może monitorować ruch w sieci"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zatrzymaj przesyłanie"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dostępne urządzenia do odtwarzania dźwięku."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Głośność"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak działa transmitowanie"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmisja"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osoby w pobliżu ze zgodnymi urządzeniami Bluetooth mogą słuchać transmitowanych przez Ciebie multimediów"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Aparat i mikrofon są wyłączone"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# powiadomienie}few{# powiadomienia}many{# powiadomień}other{# powiadomienia}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Notatki"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmisja"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Zatrzymaj transmisję aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Jeśli transmitujesz aplikację <xliff:g id="SWITCHAPP">%1$s</xliff:g> lub zmieniasz dane wyjściowe, Twoja obecna transmisja zostanie zakończona"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Transmisja aplikacji <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Zmień dane wyjściowe"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Brak informacji"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otwórz: <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Przełączyć na przedni wyświetlacz?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Użyj tylnego aparatu, aby zrobić szersze zdjęcie o większej rozdzielczości."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Ekran się wyłączy"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index eb522e81ef3f..0e7c68a342ff 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -395,7 +395,7 @@ <string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie para conferir as notificações antigas"</string> - <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu pai/mãe"</string> + <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string> <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"Este dispositivo é fornecido pela <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -434,7 +434,7 @@ <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. As atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir configurações de VPN"</string> - <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu pai/mãe, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string> + <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu familiar responsável, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Desbloqueado pelo TrustAgent"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Parar transmissão"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispositivos disponíveis para saída de áudio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmera e o microfone estão desativados"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}many{# notificações}other{# notificações}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Anotações"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmitindo"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Interromper a transmissão do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se você transmitir o app <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou mudar a saída, a transmissão atual será interrompida"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Transmitir <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Mudar saída"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Desconhecido"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d de MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Usar o display frontal para tirar uma selfie melhor?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use a câmera traseira para tirar uma foto mais ampla e com maior resolução."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta tela vai ser desativada"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index f9d2a73c0a7b..a38550f5ce25 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Parar transmissão"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispositivos disponíveis para a saída de áudio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmissão"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas de si com dispositivos Bluetooth compatíveis podem ouvir o conteúdo multimédia que está a transmitir"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmara e o microfone estão desativados"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}many{# notificações}other{# notificações}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Tomar notas"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"A transmitir"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Interromper a transmissão da app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se transmitir a app <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou alterar a saída, a sua transmissão atual é interrompida"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Transmita a app <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Altere a saída"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Desconhecida"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d de MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Inverter para ecrã frontal para uma selfie melhor?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use a câmara traseira para uma foto mais ampla com uma resolução superior."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Este ecrã vai ser desligado"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index eb522e81ef3f..0e7c68a342ff 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -395,7 +395,7 @@ <string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie para conferir as notificações antigas"</string> - <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu pai/mãe"</string> + <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string> <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"Este dispositivo é fornecido pela <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> @@ -434,7 +434,7 @@ <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Seus apps pessoais estão conectados à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. As atividades de rede, incluindo e-mails e dados de navegação, estão visíveis para o provedor de VPN."</string> <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string> <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir configurações de VPN"</string> - <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu pai/mãe, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string> + <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu familiar responsável, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string> <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string> <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Desbloqueado pelo TrustAgent"</string> <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Parar transmissão"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispositivos disponíveis para saída de áudio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmera e o microfone estão desativados"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}many{# notificações}other{# notificações}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Anotações"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmitindo"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Interromper a transmissão do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Se você transmitir o app <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou mudar a saída, a transmissão atual será interrompida"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Transmitir <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Mudar saída"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Desconhecido"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d de MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,6 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Usar o display frontal para tirar uma selfie melhor?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use a câmera traseira para tirar uma foto mais ampla e com maior resolução."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta tela vai ser desativada"</b></string> + <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string> + <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index e4ceb12cc7c0..ba5eea39e7ae 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificări întrerupte prin „Nu deranja”"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Începe acum"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nicio notificare"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Nicio notificare nouă"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Deblochează ca să vezi notificări vechi"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dispozitivul este gestionat de unul dintre părinți"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organizația ta deține acest dispozitiv și poate monitoriza traficul de rețea"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> deține acest dispozitiv și poate monitoriza traficul din rețea"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Nu mai proiecta"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispozitive disponibile pentru ieșire audio."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volum"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cum funcționează transmisia"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmite"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Persoanele din apropiere cu dispozitive Bluetooth compatibile pot asculta conținutul pe care îl transmiți"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera și microfonul sunt dezactivate"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificare}few{# notificări}other{# de notificări}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Se difuzează"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Oprești transmisia <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Dacă transmiți <xliff:g id="SWITCHAPP">%1$s</xliff:g> sau schimbi ieșirea, transmisia actuală se va opri"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Transmite <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Schimbă rezultatul"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Necunoscută"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EE, z LLL"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Deschide <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Comuți la ecranul frontal pentru un selfie mai bun?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Folosește camera posterioară pentru o fotografie mai lată, cu rezoluție mai mare."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Acest ecran se va dezactiva"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index eca383598b95..5a3f098d81e0 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"В режиме \"Не беспокоить\" уведомления заблокированы"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Начать"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Нет уведомлений"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Новых уведомлений нет"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Разблокируйте, чтобы увидеть уведомления"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Устройством управляет один из родителей."</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ваша организация управляет этим устройством и может отслеживать сетевой трафик"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Организация \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\" управляет этим устройством и может отслеживать сетевой трафик"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Остановить трансляцию"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Доступные устройства для вывода звука."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Громкость"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работают трансляции"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляция"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Находящиеся рядом с вами люди с совместимыми устройствами Bluetooth могут слушать медиафайлы, которые вы транслируете."</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера и микрофон отключены"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# уведомление}one{# уведомление}few{# уведомления}many{# уведомлений}other{# уведомления}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Создание заметок"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Трансляция"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Остановить трансляцию \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Если вы начнете транслировать \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\" или смените целевое устройство, текущая трансляция прервется."</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Транслировать \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\""</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Транслировать на другое устройство"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Неизвестно"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"d MMM EEEE"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Открыть \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Перевернули телефон передним экраном к себе?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Используйте основную камеру с широкоугольным объективом и высоким разрешением."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Этот экран отключится"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 0969b76dfa43..d1fa46ef0348 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"බාධා නොකරන්න මගින් විරාම කරන ලද දැනුම්දීම්"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"දැන් අරඹන්න"</string> <string name="empty_shade_text" msgid="8935967157319717412">"දැනුම්දීම් නැත"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"නව දැනුම්දීම් නැත"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"පැරණි දැනුම්දීම් බැලීමට අගුළු හරින්න"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"මෙම උපාංගය ඔබගේ මාපියන්ගෙන් අයකු විසින් කළමනාකරණය කෙරේ"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ඔබේ සංවිධානයට මෙම උපාංගය අයිති අතර ජාල තදබදය නිරීක්ෂණය කළ හැකිය"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> සංවිධානයට මෙම උපාංගය අයිති අතර ජාල තදබදය නිරීක්ෂණය කළ හැකිය"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"විකාශය නවතන්න"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ශ්රව්ය ප්රතිදානය සඳහා තිබෙන උපාංග."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"හඬ පරිමාව"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"විකාශනය ක්රියා කරන ආකාරය"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"විකාශනය"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ගැළපෙන බ්ලූටූත් උපාංග සහිත ඔබ අවට සිටින පුද්ගලයින්ට ඔබ විකාශනය කරන මාධ්යයට සවන් දිය හැකිය"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"කැමරාව සහ මයික් ක්රියාවිරහිතයි"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{දැනුම්දීම් #ක්}one{දැනුම්දීම් #ක්}other{දැනුම්දීම් #ක්}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"සටහන් කර ගැනීම"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"විකාශනය කරමින්"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> විකාශනය කිරීම නවත්වන්නද?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"ඔබ <xliff:g id="SWITCHAPP">%1$s</xliff:g> විකාශනය කළහොත් හෝ ප්රතිදානය වෙනස් කළහොත්, ඔබගේ වත්මන් විකාශනය නවතිනු ඇත."</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> විකාශනය"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"ප්රතිදානය වෙනස් කරන්න"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"නොදනී"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> විවෘත කරන්න"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"වඩා හොඳ සෙල්ෆියක් සඳහා ඉදිරිපස සංදර්ශකයට පෙරළන්න ද?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ඉහළ විභේදන සහිත පුළුල් ඡායාරූපයක් සඳහා පසුපසට මුහුණලා ඇති කැමරාව භාවිතා කරන්න."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ මෙම තිරය ක්රියා විරහිත වනු ඇත"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index d5629a9bcdb8..2573733fc50b 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Zastaviť prenos"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dostupné zariadenia pre zvukový výstup."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Hlasitosť"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ako vysielanie funguje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Vysielanie"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ľudia v okolí s kompatibilnými zariadeniami s rozhraním Bluetooth si môžu vypočuť médiá, ktoré vysielate"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera a mikrofón sú vypnuté"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# upozornenie}few{# upozornenia}many{# notifications}other{# upozornení}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Zapisovanie poznámok"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Vysiela"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Chcete zastaviť vysielanie aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ak vysielate aplikáciu <xliff:g id="SWITCHAPP">%1$s</xliff:g> alebo zmeníte výstup, aktuálne vysielanie bude zastavené"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Vysielanie aplikácie <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Zmena výstupu"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Neznáme"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d. MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvoriť <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Prevrátiť na pred. obrazovku pre lepšie selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Pomocou zadného fotoaparátu vytvorte širšiu fotku s vyšším rozlíšením."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Táto obrazovka sa vypne"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index b48b632ec8be..fa63f87650c6 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Prikazovanje obvestil je začasno zaustavljeno z načinom »ne moti«"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Začni zdaj"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Ni obvestil"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Ni novih obvestil"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odklenite za ogled starejših obvestil"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"To napravo upravlja tvoj starš"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizacija je lastnica te naprave in lahko nadzira omrežni promet"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Organizacija <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> je lastnica te naprave in lahko nadzira omrežni promet"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ustavi predvajanje"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Razpoložljive naprave za zvočni izhod"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Glasnost"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako deluje oddajanje"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Oddajanje"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osebe v bližini z združljivo napravo Bluetooth lahko poslušajo predstavnost, ki jo oddajate."</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotoaparat in mikrofon sta izklopljena."</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obvestilo}one{# obvestilo}two{# obvestili}few{# obvestila}other{# obvestil}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Ustvarjanje zapiskov"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Oddajanje"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Želite ustaviti oddajanje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Če oddajate aplikacijo <xliff:g id="SWITCHAPP">%1$s</xliff:g> ali spremenite izhod, bo trenutno oddajanje ustavljeno."</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Oddajaj aplikacijo <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Sprememba izhoda"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Neznano"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d. MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Odpri aplikacijo <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Obrnite telefon na sprednji zaslon za boljši selfi"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Uporabite hrbtni fotoaparat, da posnamete širšo sliko višje ločljivosti."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ta zaslon se bo izklopil."</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 9356d28ed980..6eb745ccdfaa 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ndalo transmetimin"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Pajisjet që ofrohen për daljen e audios."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volumi"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Si funksionon transmetimi"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Transmetimi"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personat në afërsi me ty me pajisje të përputhshme me Bluetooth mund të dëgjojnë median që ti po transmeton"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera dhe mikrofoni janë joaktivë"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# njoftim}other{# njoftime}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Mbajtja e shënimeve"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Po transmeton"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Të ndalohet transmetimi i <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Nëse transmeton <xliff:g id="SWITCHAPP">%1$s</xliff:g> ose ndryshon daljen, transmetimi yt aktual do të ndalojë"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Transmeto <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Ndrysho daljen"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"I panjohur"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Hap \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Të kthehet tek ekrani para për selfi më të mirë?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Përdor lenten e kamerës së pasme për një fotografi më të gjerë me rezolucion më të lartë."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ky ekran do të fiket"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 6f694ad3d3b3..75a455997f84 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Заустави пребацивање"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Доступни уређаји за аудио излаз."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Звук"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционише емитовање"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Емитовање"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Људи у близини са компатибилним Bluetooth уређајима могу да слушају медијски садржај који емитујете"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера и микрофон су искључени"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# обавештење}one{# обавештење}few{# обавештења}other{# обавештења}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Прављење бележака"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Емитовање"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Желите да зауставите емитовање апликације <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Ако емитујете апликацију <xliff:g id="SWITCHAPP">%1$s</xliff:g> или промените излаз, актуелно емитовање ће се зауставити"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Емитујте апликацију <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Промените излаз"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Непознато"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"ДДД, д. МММ"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"с:мин"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"ч:мин"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Отворите: <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Желите да обрнете на предњи екран за бољи селфи?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Користите задњу камеру да бисте снимили ширу слику са вишом резолуцијом."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Овај екран ће се искључити"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index c6646960dfd0..39b40e97b3b3 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Aviseringar har pausats via Stör ej"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Starta nu"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Inga aviseringar"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Det finns inga nya aviseringar"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Lås upp för att se äldre aviseringar"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Den här enheten hanteras av din förälder"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisationen äger den här enheten och kan övervaka nätverkstrafiken"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> äger den här enheten och kan övervaka nätverkstrafiken"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Sluta casta"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Enheter som är tillgängliga för ljudutdata."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volym"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Så fungerar utsändning"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Utsändning"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i närheten med kompatibla Bluetooth-enheter kan lyssna på medieinnehåll som du sänder ut"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kameran och mikrofonen är avstängda"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# avisering}other{# aviseringar}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Anteckningar"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Sänder"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vill du sluta sända från <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Om en utsändning från <xliff:g id="SWITCHAPP">%1$s</xliff:g> pågår eller om du byter ljudutgång avbryts den nuvarande utsändningen"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Sänd från <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Byt ljudutgång"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Okänt"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h.mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk.mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Öppna <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vill du ta en bättre selfie med främre skärmen?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Använd den bakre kameran för att ta ett mer vidsträckt foto med högre upplösning."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Den här skärmen inaktiveras"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index cd4fa1541a97..ccf3345e2820 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Kipengele cha Usinisumbue kimesitisha arifa"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Anza sasa"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Hakuna arifa"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Hakuna arifa mpya"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Fungua ili uone arifa za zamani"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Kifaa hiki kinadhibitiwa na mzazi wako"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Shirika lako linamiliki kifaa hiki na huenda likafuatilia trafiki ya mtandao"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> inamiliki kifaa hiki na huenda ikafuatilia trafiki ya mtandao"</string> @@ -997,7 +995,6 @@ <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Tangaza kwenye <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Badilisha maudhui"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Haijulikani"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"saa:dk"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:dk"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Fungua <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1010,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Ungependa kugeuza skrini ya mbele ili upige selfi?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Tumia kamera ya nyuma ili upige picha pana iliyo na ubora wa juu."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Skrini hii itajizima"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 6c0a4e4479f4..9f99b76ea984 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'தொந்தரவு செய்ய வேண்டாம்\' அம்சத்தின் மூலம் அறிவிப்புகள் இடைநிறுத்தப்பட்டுள்ளன"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"இப்போது தொடங்கு"</string> <string name="empty_shade_text" msgid="8935967157319717412">"அறிவிப்புகள் இல்லை"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"புதிய அறிவிப்புகள் இல்லை"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"பழைய அறிவிப்பைப் பார்க்க அன்லாக் செய்க"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"இந்தச் சாதனம் உங்கள் பெற்றோரால் நிர்வகிக்கப்படுகிறது"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு உரியது, நெட்வொர்க் ட்ராஃபிக்கையும் நிறுவனமே கண்காணிக்கக்கூடும்"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"இந்த சாதனம் <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> நிறுவனத்துக்கு உரியது, நெட்வொர்க் ட்ராஃபிக்கையும் நிறுவனமே கண்காணிக்கக்கூடும்"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"அலைபரப்புவதை நிறுத்து"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ஆடியோ அவுட்புட்டுக்குக் கிடைக்கும் சாதனங்கள்."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ஒலியளவு"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"பிராட்காஸ்ட் எவ்வாறு செயல்படுகிறது?"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"பிராட்காஸ்ட்"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"நீங்கள் பிராட்காஸ்ட் செய்யும் மீடியாவை அருகிலுள்ளவர்கள் இணக்கமான புளூடூத் சாதனங்கள் மூலம் கேட்கலாம்"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"கேமராவும் மைக்கும் ஆஃப் செய்யப்பட்டுள்ளன"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# அறிவிப்பு}other{# அறிவிப்புகள்}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"குறிப்பெடுத்தல்"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ஒலிபரப்புதல்"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் ஒலிபரப்பப்படுவதை நிறுத்தவா?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"நீங்கள் <xliff:g id="SWITCHAPP">%1$s</xliff:g> ஆப்ஸை ஒலிபரப்பினாலோ அவுட்புட்டை மாற்றினாலோ உங்களின் தற்போதைய ஒலிபரப்பு நிறுத்தப்படும்"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ஆப்ஸை ஒலிபரப்பு"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"அவுட்புட்டை மாற்று"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"தெரியவில்லை"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸைத் திற"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"சிறந்த செல்ஃபிக்கு முன்புற டிஸ்பிளேவிற்கு மாற்றவா?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"அதிகத் தெளிவுத்திறனுடன் அகலக் கோணத்தில் படத்தை எடுப்பதற்குப் பின்பக்கக் கேமராவைப் பயன்படுத்துங்கள்."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ இந்தத் திரை ஆஃப் ஆகிவிடும்"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 68f547a7312c..4e506d4eadab 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -66,7 +66,7 @@ <string name="usb_contaminant_title" msgid="894052515034594113">"USB పోర్ట్ నిలిపివేయబడింది"</string> <string name="usb_contaminant_message" msgid="7730476585174719805">"మీ పరికరంలోకి నీరు లేదా చెత్తాచెదారం చేరిపోకుండా కాపాడటానికి, USB పోర్ట్ నిలిపివేయబడుతుంది, అలాగే యాక్సెసరీలు వేటిని గుర్తించదు.\n\nUSB పోర్ట్ను ఉపయోగించడం సురక్షితమేనని నిర్ధారించుకున్న తర్వాత, మళ్లీ మీకో నోటిఫికేషన్ రూపంలో తెలియజేయబడుతుంది."</string> <string name="usb_port_enabled" msgid="531823867664717018">"ఛార్జర్లు, యాక్సెసరీలను గుర్తించే విధంగా USB పోర్ట్ ప్రారంభించబడింది"</string> - <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USBని ప్రారంభించు"</string> + <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USBని ప్రారంభించండి"</string> <string name="learn_more" msgid="4690632085667273811">"మరింత తెలుసుకోండి"</string> <string name="global_action_screenshot" msgid="2760267567509131654">"స్క్రీన్షాట్"</string> <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock డిజేబుల్ చేయబడింది"</string> @@ -105,7 +105,7 @@ <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"మీ పరికరం నుండి వచ్చే మ్యూజిక్, కాల్స్, రింగ్టోన్ల వంటి ధ్వనులు"</string> <string name="screenrecord_mic_label" msgid="2111264835791332350">"మైక్రోఫోన్"</string> <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"పరికరం ఆడియో, మైక్రోఫోన్"</string> - <string name="screenrecord_start" msgid="330991441575775004">"ప్రారంభించు"</string> + <string name="screenrecord_start" msgid="330991441575775004">"ప్రారంభించండి"</string> <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"స్క్రీన్ రికార్డింగ్ చేయబడుతోంది"</string> <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"స్క్రీన్, ఆడియో రికార్డింగ్ చేయబడుతున్నాయి"</string> <string name="screenrecord_taps_label" msgid="1595690528298857649">"స్క్రీన్పై తాకే స్థానాలను చూపు"</string> @@ -289,7 +289,7 @@ <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC నిలిపివేయబడింది"</string> <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ప్రారంభించబడింది"</string> <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"స్క్రీన్ రికార్డ్"</string> - <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ప్రారంభించు"</string> + <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ప్రారంభించండి"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ఆపు"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"వన్-హ్యాండెడ్ మోడ్"</string> <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"పరికరం మైక్రోఫోన్ను అన్బ్లాక్ చేయమంటారా?"</string> @@ -356,7 +356,7 @@ <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ఈ సెషన్లోని అన్ని యాప్లు మరియు డేటా తొలగించబడతాయి."</string> <string name="guest_wipe_session_title" msgid="7147965814683990944">"గెస్ట్కు తిరిగి స్వాగతం!"</string> <string name="guest_wipe_session_message" msgid="3393823610257065457">"మీరు మీ సెషన్ని కొనసాగించాలనుకుంటున్నారా?"</string> - <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"మొదటి నుండి ప్రారంభించు"</string> + <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"మొదటి నుండి ప్రారంభించండి"</string> <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"అవును, కొనసాగించు"</string> <string name="guest_notification_app_name" msgid="2110425506754205509">"గెస్ట్ మోడ్"</string> <string name="guest_notification_session_active" msgid="5567273684713471450">"మీరు గెస్ట్ మోడ్లో ఉన్నారు"</string> @@ -391,12 +391,10 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"సంభాషణలు"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"అన్ని నిశ్శబ్ద నోటిఫికేషన్లను క్లియర్ చేస్తుంది"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"అంతరాయం కలిగించవద్దు ద్వారా నోటిఫికేషన్లు పాజ్ చేయబడ్డాయి"</string> - <string name="media_projection_action_text" msgid="3634906766918186440">"ఇప్పుడే ప్రారంభించు"</string> + <string name="media_projection_action_text" msgid="3634906766918186440">"ఇప్పుడే ప్రారంభించండి"</string> <string name="empty_shade_text" msgid="8935967157319717412">"నోటిఫికేషన్లు లేవు"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"కొత్త నోటిఫికేషన్లు ఏవీ లేవు"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"పాత నోటిఫికేషన్ల కోసం అన్లాక్ చేయండి"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ఈ పరికరాన్ని మీ తల్లి/తండ్రి మేనేజ్ చేస్తున్నారు"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ఈ పరికరం మీ సంస్థకు చెందినది, కాబట్టి అది నెట్వర్క్ ట్రాఫిక్ను పర్యవేక్షించవచ్చు"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"మీ పరికరం <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>కు చెందినది, కాబట్టి అది నెట్వర్క్ ట్రాఫిక్ను పర్యవేక్షించవచ్చు"</string> @@ -444,7 +442,7 @@ <string name="volume_odi_captions_tip" msgid="8825655463280990941">"మీడియాకు ఆటోమేటిక్ క్యాప్షన్లు"</string> <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"క్యాప్షన్ల చిట్కాను మూసివేయండి"</string> <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"క్యాప్షన్లు ఓవర్లే"</string> - <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ప్రారంభించు"</string> + <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ప్రారంభించండి"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"నిలిపివేయండి"</string> <string name="sound_settings" msgid="8874581353127418308">"సౌండ్ & వైబ్రేషన్"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"సెట్టింగ్లు"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"ప్రసారాన్ని ఆపివేయండి"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ఆడియో అవుట్పుట్ కోసం అందుబాటులో ఉన్న పరికరాలు."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"వాల్యూమ్"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ప్రసారం కావడం అనేది ఎలా పని చేస్తుంది"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ప్రసారం"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"మీకు సమీపంలో ఉన్న వ్యక్తులు అనుకూలత ఉన్న బ్లూటూత్ పరికరాలతో మీరు ప్రసారం చేస్తున్న మీడియాను వినగలరు"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"కెమెరా, మైక్ ఆఫ్లో ఉన్నాయి"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# నోటిఫికేషన్}other{# నోటిఫికేషన్లు}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"నోట్టేకింగ్"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"ప్రసారం చేస్తోంది"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ప్రసారం చేయడాన్ని ఆపివేయాలా?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"మీరు <xliff:g id="SWITCHAPP">%1$s</xliff:g> ప్రసారం చేస్తే లేదా అవుట్పుట్ను మార్చినట్లయితే, మీ ప్రస్తుత ప్రసారం ఆగిపోతుంది"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ప్రసారం చేయండి"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"అవుట్పుట్ను మార్చండి"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"తెలియదు"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g>ను తెరవండి"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"మంచి సెల్ఫీ కోసం ముందు వైపు డిస్ప్లేకు తిప్పాలా?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"అధిక రిజల్యూషన్తో పెద్ద ఫోటో కోసం వెనుక వైపున ఉన్న కెమెరాను ఉపయోగించండి."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ఈ స్క్రీన్ ఆఫ్ అవుతుంది"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index b335a69cad89..544dde40d5f3 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"หยุดแคสต์"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"อุปกรณ์ที่พร้อมใช้งานสำหรับเอาต์พุตเสียง"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ระดับเสียง"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"วิธีการทำงานของการออกอากาศ"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"ประกาศ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ผู้ที่อยู่ใกล้คุณและมีอุปกรณ์บลูทูธที่รองรับสามารถรับฟังสื่อที่คุณกำลังออกอากาศได้"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"กล้องและไมค์ปิดอยู่"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{การแจ้งเตือน # รายการ}other{การแจ้งเตือน # รายการ}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"การจดบันทึก"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"กำลังออกอากาศ"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"หยุดการออกอากาศ <xliff:g id="APP_NAME">%1$s</xliff:g> ไหม"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"หากคุณออกอากาศ <xliff:g id="SWITCHAPP">%1$s</xliff:g> หรือเปลี่ยนแปลงเอาต์พุต การออกอากาศในปัจจุบันจะหยุดลง"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"ออกอากาศ <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"เปลี่ยนเอาต์พุต"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"ไม่ทราบ"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"HH:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"เปิด <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"พลิกเป็นหน้าจอด้านหน้าเพื่อภาพเซลฟีที่ดีขึ้นไหม"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ใช้กล้องหลังเพื่อถ่ายภาพกว้างขึ้นด้วยความละเอียดสูงขึ้น"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ หน้าจอนี้จะปิดไป"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 79b10b2f4990..c27b13308bf8 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Mga notification na na-pause ng Huwag Istorbohin"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Magsimula ngayon"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Walang mga notification"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Walang bagong notification"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"I-unlock para makita ang mga mas lumang notification"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Pinapamahalaan ng magulang mo itong device"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Pagmamay-ari ng organisasyon mo ang device na ito at puwede nitong subaybayan ang trapiko sa network"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ang device na ito at puwede nitong subaybayan ang trapiko sa network"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Ihinto ang pag-cast"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Mga available na device para sa audio output."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Paano gumagana ang pag-broadcast"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Makakapakinig ang mga taong malapit sa iyo na may mga compatible na Bluetooth device sa media na bino-broadcast mo"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Naka-off ang camera at mikropono"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}other{# na notification}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Pagtatala"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Nagbo-broadcast"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Ihinto ang pag-broadcast ng <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Kung magbo-broadcast ka ng <xliff:g id="SWITCHAPP">%1$s</xliff:g> o babaguhin mo ang output, hihinto ang iyong kasalukuyang broadcast"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"I-broadcast ang <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Baguhin ang output"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Hindi alam"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Buksan ang <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"I-flip sa front display para sa magandang selfie?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gamitin ang camera sa harap para sa mas malawak na larawan na may mas mataas na resolution."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Mag-o-off ang screen na ito"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 308acb35dce8..90cd4a7e6f73 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bildirimler, Rahatsız Etmeyin özelliği tarafından duraklatıldı"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Şimdi başlat"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Bildirim yok"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Yeni bildirim yok"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Eski bildirimler için kilidi açın"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu cihaz ebeveyniniz tarafından yönetiliyor"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Bu cihaz, kuruluşunuza ait olup ağ trafiği kuruluşunuz tarafından izlenebilir"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Bu cihaz, <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> adlı kuruluşa ait olup ağ trafiği bu kuruluş tarafından izlenebilir"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Yayını durdur"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Ses çıkışı için kullanılabilir cihazlar."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Ses düzeyi"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayınlamanın işleyiş şekli"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Anons"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Yakınınızda ve uyumlu Bluetooth cihazları olan kişiler yayınladığınız medya içeriğini dinleyebilir"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera ve mikrofon kapalı"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# bildirim}other{# bildirim}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Not alma"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Yayınlama"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında anons durdurulsun mu?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> uygulamasında anons yapar veya çıkışı değiştirirseniz mevcut anonsunuz duraklatılır"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> uygulamasında anons yapın"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Çıkışı değiştirme"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Bilinmiyor"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"d MMM, EEE"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:dd"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> uygulamasını aç"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Daha iyi bir selfie için ön ekrana geçilsin mi?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Daha yüksek çözünürlüğe sahip daha büyük bir fotoğraf için arka yüz kamerasını kullanın."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ * Bu ekran kapatılacak"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index d4465e86ebd6..76e99ef4bc3b 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Режим \"Не турбувати\" призупинив сповіщення"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Почати зараз"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Сповіщень немає"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Немає нових сповіщень"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Розблокуйте, щоб переглянути старіші"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Цим пристроєм керує батько або мати"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Цей пристрій належить вашій організації. Її адміністратор може відстежувати мережевий трафік"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Цей пристрій належить організації \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\". Її адміністратор може відстежувати мережевий трафік"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Припинити трансляцію"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Доступні пристрої для відтворення звуку."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Гучність"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як працює трансляція"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляція"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Люди поблизу, які мають сумісні пристрої з Bluetooth, можуть слухати медіаконтент, який ви транслюєте."</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камеру й мікрофон вимкнено"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# сповіщення}one{# сповіщення}few{# сповіщення}many{# сповіщень}other{# сповіщення}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Створення нотаток"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Трансляція"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Зупинити трансляцію з додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Якщо ви зміните додаток (<xliff:g id="SWITCHAPP">%1$s</xliff:g>) або аудіовихід, поточну трансляцію буде припинено"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Змінити додаток для трансляції на <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Змінити аудіовихід"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Невідомо"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, d MMM"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Відкрити <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Перемкнути на фронтальну камеру для кращого селфі?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Використовуйте камеру на задній панелі, щоб зробити знімок із ширшим кутом і вищою роздільною здатністю."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Цей екран вимкнеться"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 91558d84503e..7f805984dc1b 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'ڈسٹرب نہ کریں\' کے ذریعے اطلاعات کو موقوف کیا گیا"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"ابھی شروع کریں"</string> <string name="empty_shade_text" msgid="8935967157319717412">"کوئی اطلاعات نہیں ہیں"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"کوئی نئی اطلاعات نہیں"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"پرانی اطلاعات دیکھنے کیلئے غیر مقفل کریں"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"یہ آلہ آپ کے والدین کے زیر انتظام ہے"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"آپ کی تنظیم اس آلے کی مالک ہے اور نیٹ ورک ٹریفک کی نگرانی کر سکتی ہے"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> اس آلے کی مالک ہے اور نیٹ ورک ٹریفک کی نگرانی کر سکتی ہے"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"کاسٹ کرنا بند کریں"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"آڈیو آؤٹ پٹ کے لیے دستیاب آلات۔"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"والیوم"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"براڈکاسٹنگ کیسے کام کرتا ہے"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"براڈکاسٹ"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"موافق بلوٹوتھ آلات کے ساتھ آپ کے قریبی لوگ آپ کے نشر کردہ میڈیا کو سن سکتے ہیں"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"کیمرا اور مائیک آف ہیں"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# اطلاع}other{# اطلاعات}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>، <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"نوٹ لینا"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"نشریات"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> براڈکاسٹنگ روکیں؟"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"اگر آپ <xliff:g id="SWITCHAPP">%1$s</xliff:g> براڈکاسٹ کرتے ہیں یا آؤٹ پٹ کو تبدیل کرتے ہیں تو آپ کا موجودہ براڈکاسٹ رک جائے گا"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> پر براڈکاسٹ کریں"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"آؤٹ پٹ تبدیل کریں"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"نامعلوم"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> کھولیں"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"بہتر سیلفی کے لیے سامنے والے ڈسپلے پر پلٹائیں؟"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"اعلی ریزولیوشن والی وسیع تصویر کے لیے ییچھے والا کیمرا استعمال کریں۔"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ یہ اسکرین آف ہو جائے گی"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 13a57d48e8e1..99e8abc13b6b 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bezovta qilinmasin rejimida bildirishnomalar pauza qilinadi"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Boshlash"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Bildirishnomalar yo‘q"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Yangi bildirishoma yoʻq"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Eskilarini koʻrish uchun qulfni yeching"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu qurilmani ota-onangiz boshqaradi"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Bu qurilma tashkilotingizga tegishli va tarmoq trafigi tashkilotingiz tomonidan kuzatilishi mumkin"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Bu qurilma <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> tashkilotiga tegishli va tarmoq trafigi tashkilot tomonidan kuzatilishi mumkin"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Toʻxtatish"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Audio chiqish uchun mavjud qurilmalar."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Tovush balandligi"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Translatsiya qanday ishlaydi"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Translatsiya"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Atrofingizdagi mos Bluetooth qurilmasiga ega foydalanuvchilar siz translatsiya qilayotgan mediani tinglay olishadi"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera va mikrofon yoqilmagan"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ta bildirishnoma}other{# ta bildirishnoma}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Eslatma yozish"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Signal uzatish"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga translatsiya toʻxtatilsinmi?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Agar <xliff:g id="SWITCHAPP">%1$s</xliff:g> ilovasiga translatsiya qilsangiz yoki ovoz chiqishini oʻzgartirsangiz, joriy translatsiya toʻxtab qoladi"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ilovasiga translatsiya"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Ovoz chiqishini oʻzgartirish"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Noaniq"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"s:dd"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ochish: <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Old ekran sizga qaragan holda aylantirdingizmi?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Keng va yuqori tiniqlikdagi suratga olish uchun orqa kameradan foydalaning."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Bu ekran oʻchiriladi"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 7bba2f8df1ec..88bf8de25e09 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Chế độ Không làm phiền đã tạm dừng thông báo"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Bắt đầu ngay"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Không có thông báo nào"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Không có thông báo mới"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Mở khoá để xem thông báo cũ"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Thiết bị này do cha mẹ của bạn quản lý"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Tổ chức của bạn sở hữu thiết bị này và có thể giám sát lưu lượng truy cập mạng"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> sở hữu thiết bị này và có thể giám sát lưu lượng truy cập mạng"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Dừng truyền"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Các thiết bị có sẵn để xuất âm thanh."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Âm lượng"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cách tính năng truyền hoạt động"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Truyền"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Những người ở gần có thiết bị Bluetooth tương thích có thể nghe nội dung nghe nhìn bạn đang truyền"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Máy ảnh và micrô đang tắt"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# thông báo}other{# thông báo}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Ghi chú"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Phát sóng"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Dừng phát <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Nếu bạn phát <xliff:g id="SWITCHAPP">%1$s</xliff:g> hoặc thay đổi đầu ra, phiên truyền phát hiện tại sẽ dừng"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Phát <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Thay đổi đầu ra"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Không xác định"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Mở <xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Lật sang màn hình ngoài để tự chụp ảnh chân dung đẹp hơn?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Sử dụng máy ảnh sau để chụp ảnh góc rộng hơn với độ phân giải cao hơn."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Màn hình này sẽ tắt"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index def5cf881e1b..81b61c6644e7 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"勿扰模式暂停的通知"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"立即开始"</string> <string name="empty_shade_text" msgid="8935967157319717412">"没有通知"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"没有新通知"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"解锁即可查看旧通知"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"此设备由您的家长管理"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"贵单位拥有此设备,且可能会监控网络流量"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>拥有此设备,且可能会监控网络流量"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"停止投放"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"音频输出的可用设备。"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"音量"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"广播的运作方式"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"广播"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近使用兼容蓝牙设备的用户可以收听您广播的媒体内容"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"摄像头和麦克风已关闭"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 条通知}other{# 条通知}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>,<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"记录"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"正在广播"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"要停止广播“<xliff:g id="APP_NAME">%1$s</xliff:g>”的内容吗?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"如果广播“<xliff:g id="SWITCHAPP">%1$s</xliff:g>”的内容或更改输出来源,当前的广播就会停止"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"广播“<xliff:g id="SWITCHAPP">%1$s</xliff:g>”的内容"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"更改输出来源"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"未知"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"打开<xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"要翻转到外屏以拍出更好的自拍照吗?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"您可以使用后置摄像头拍摄视角更广、分辨率更高的照片。"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 此屏幕将会关闭"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index c222ea54592d..3d7ba058a0eb 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"停止投放"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"可用作音訊輸出的裝置"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"音量"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播運作方式"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近有兼容藍牙裝置的人可收聽您正在廣播的媒體內容"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"相機和麥克風已關閉"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 則通知}other{# 則通知}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>,<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"做筆記"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"廣播"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"要停止廣播「<xliff:g id="APP_NAME">%1$s</xliff:g>」的內容嗎?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"如要廣播「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容或變更輸出來源,系統就會停止廣播目前的內容"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"廣播「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"變更輸出來源"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"不明"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"MMM d EEE"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"開啟「<xliff:g id="APPNAME">%1$s</xliff:g>」"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"要翻轉至前方螢幕拍攝更出色的自拍嗎?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"使用後置鏡頭,拍攝更廣角、解像度更高的相片。"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 此螢幕將關閉"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 7123c4c8fb42..47c0561c39a0 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -872,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"停止投放"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"可用於輸出音訊的裝置。"</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"音量"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播功能的運作方式"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"如果附近的人有相容的藍牙裝置,就可以聽到你正在廣播的媒體內容"</string> @@ -987,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"已關閉相機和麥克風"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 則通知}other{# 則通知}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>,<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"做筆記"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"廣播"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"要停止播送「<xliff:g id="APP_NAME">%1$s</xliff:g>」的內容嗎?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"如果播送「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容或變更輸出來源,系統就會停止播送目前的內容"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"播送「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"變更輸出來源"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"不明"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"MMM d EEE"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"開啟「<xliff:g id="APPNAME">%1$s</xliff:g>」"</string> @@ -1011,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"要翻轉到前螢幕拍攝更優質的自拍照嗎?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"使用後置鏡頭可拍攝視角較寬廣、解析度較高的相片。"</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 這麼做會關閉這個螢幕"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index b9c44e502b32..b77851954f50 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -393,10 +393,8 @@ <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Izaziso zimiswe okwesikhashana ukungaphazamisi"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Qala manje"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Azikho izaziso"</string> - <!-- no translation found for no_unseen_notif_text (395512586119868682) --> - <skip /> - <!-- no translation found for unlock_to_see_notif_text (7439033907167561227) --> - <skip /> + <string name="no_unseen_notif_text" msgid="395512586119868682">"Azikho izaziso ezintsha"</string> + <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Vula ukuze ubone izaziso ezindala"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Le divayisi iphethwe ngumzali wakho"</string> <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Inhlangano yakho ingumnikazi wale divayisi futhi ingaqapha ithrafikhi yenethiwekhi"</string> <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"I-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ingumnikazi wale divayisi futhi ingaqapha ithrafikhi yenethiwekhi"</string> @@ -874,8 +872,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"Misa ukusakaza"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Amadivayisi atholakalayo okukhipha umsindo."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Ivolumu"</string> - <!-- no translation found for media_output_dialog_volume_percentage (1613984910585111798) --> - <skip /> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Indlela ukusakaza okusebenza ngayo"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Sakaza"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Abantu abaseduze nawe abanamadivayisi e-Bluetooth ahambisanayo bangalalela imidiya oyisakazayo"</string> @@ -989,15 +986,13 @@ <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Ikhamera nemakrofoni kuvaliwe"</string> <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{Isaziso esingu-#}one{Izaziso ezingu-#}other{Izaziso ezingu-#}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> - <!-- no translation found for note_task_button_label (8718616095800343136) --> - <skip /> + <string name="note_task_button_label" msgid="8718616095800343136">"Ukuthatha amanothi"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Ukusakaza"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Misa ukusakaza i-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="7889684551194225793">"Uma usakaza i-<xliff:g id="SWITCHAPP">%1$s</xliff:g> noma ushintsha okuphumayo, ukusakaza kwakho kwamanje kuzoma"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="6098768269397105733">"Sakaza i-<xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="7885102097302562674">"Shintsha okuphumayo"</string> <string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Akwaziwa"</string> - <string name="dream_date_complication_date_format" msgid="8191225366513860104">"EEE, MMM d"</string> <string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string> <string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string> <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Vula i-<xliff:g id="APPNAME">%1$s</xliff:g>"</string> @@ -1013,4 +1008,8 @@ <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Phendulela kwisibonisi sangaphambili ukuba nesithombe ozishuthe sona esingcono?"</string> <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Sebenzisa ikhamera ebheke ngemuva ukuze uthole isithombe esibanzi esinokucaca okuphezulu."</string> <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Lesi sikrini sizovala"</b></string> + <!-- no translation found for rear_display_accessibility_folded_animation (1538121649587978179) --> + <skip /> + <!-- no translation found for rear_display_accessibility_unfolded_animation (1946153682258289040) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index bc88bee41df8..ca4217f64b60 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -236,15 +236,6 @@ <color name="dream_overlay_camera_mic_off_dot_color">#FCBE03</color> - <!-- Air Quality --> - <color name="dream_overlay_aqi_good">#689F38</color> - <color name="dream_overlay_aqi_moderate">#FBC02D</color> - <color name="dream_overlay_aqi_unhealthy_sensitive">#F57C00</color> - <color name="dream_overlay_aqi_unhealthy">#C53929</color> - <color name="dream_overlay_aqi_very_unhealthy">#AD1457</color> - <color name="dream_overlay_aqi_hazardous">#880E4F</color> - <color name="dream_overlay_aqi_unknown">#BDC1C6</color> - <!-- Dream overlay text shadows --> <color name="dream_overlay_clock_key_text_shadow_color">#4D000000</color> <color name="dream_overlay_clock_ambient_text_shadow_color">#4D000000</color> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 4cda8c7b5328..6d88e512eddb 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -773,15 +773,11 @@ <integer name="complicationFadeOutDelayMs">200</integer> <!-- Duration in milliseconds of the dream in un-blur animation. --> - <integer name="config_dreamOverlayInBlurDurationMs">249</integer> - <!-- Delay in milliseconds of the dream in un-blur animation. --> - <integer name="config_dreamOverlayInBlurDelayMs">133</integer> + <integer name="config_dreamOverlayInBlurDurationMs">250</integer> <!-- Duration in milliseconds of the dream in complications fade-in animation. --> - <integer name="config_dreamOverlayInComplicationsDurationMs">282</integer> - <!-- Delay in milliseconds of the dream in top complications fade-in animation. --> - <integer name="config_dreamOverlayInTopComplicationsDelayMs">216</integer> - <!-- Delay in milliseconds of the dream in bottom complications fade-in animation. --> - <integer name="config_dreamOverlayInBottomComplicationsDelayMs">299</integer> + <integer name="config_dreamOverlayInComplicationsDurationMs">250</integer> + <!-- Duration in milliseconds of the y-translation animation when entering a dream --> + <integer name="config_dreamOverlayInTranslationYDurationMs">917</integer> <!-- Icons that don't show in a collapsed non-keyguard statusbar --> <string-array name="config_collapsed_statusbar_icon_blocklist" translatable="false"> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index f3d2638c4ee7..e8a8534581d2 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -758,6 +758,8 @@ <dimen name="keyguard_affordance_fixed_height">48dp</dimen> <dimen name="keyguard_affordance_fixed_width">48dp</dimen> <dimen name="keyguard_affordance_fixed_radius">24dp</dimen> + <!-- Amount the button should shake when it's not long-pressed for long enough. --> + <dimen name="keyguard_affordance_shake_amplitude">8dp</dimen> <dimen name="keyguard_affordance_horizontal_offset">32dp</dimen> <dimen name="keyguard_affordance_vertical_offset">32dp</dimen> @@ -1505,6 +1507,8 @@ <dimen name="dream_overlay_status_bar_extra_margin">8dp</dimen> <!-- Dream overlay complications related dimensions --> + <!-- The blur radius applied to the dream overlay when entering and exiting dreams --> + <dimen name="dream_overlay_anim_blur_radius">50dp</dimen> <dimen name="dream_overlay_complication_clock_time_text_size">86dp</dimen> <dimen name="dream_overlay_complication_clock_time_translation_y">28dp</dimen> <dimen name="dream_overlay_complication_home_controls_padding">28dp</dimen> @@ -1558,12 +1562,9 @@ <dimen name="dream_overlay_complication_margin">0dp</dimen> <dimen name="dream_overlay_y_offset">80dp</dimen> + <dimen name="dream_overlay_entry_y_offset">40dp</dimen> <dimen name="dream_overlay_exit_y_offset">40dp</dimen> - <dimen name="dream_aqi_badge_corner_radius">28dp</dimen> - <dimen name="dream_aqi_badge_padding_vertical">6dp</dimen> - <dimen name="dream_aqi_badge_padding_horizontal">16dp</dimen> - <dimen name="status_view_margin_horizontal">0dp</dimen> <!-- Media output broadcast dialog QR code picture size --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 6e11fcf62749..ca2cf1a56b41 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2688,9 +2688,6 @@ <!-- [CHAR LIMIT=NONE] Le audio broadcast dialog, media app is unknown --> <string name="bt_le_audio_broadcast_dialog_unknown_name">Unknown</string> - <!-- Date format for the Dream Date Complication [CHAR LIMIT=NONE] --> - <string name="dream_date_complication_date_format">EEE, MMM d</string> - <!-- Time format for the Dream Time Complication for 12-hour time format [CHAR LIMIT=NONE] --> <string name="dream_time_complication_12_hr_time_format">h:mm</string> @@ -2743,6 +2740,12 @@ --> <string name="keyguard_affordance_enablement_dialog_home_instruction_2">• At least one device is available</string> + <!-- + Error message shown when a button should be pressed and held to activate it, usually shown when + the user attempted to tap the button or held it for too short a time. [CHAR LIMIT=32]. + --> + <string name="keyguard_affordance_press_too_short">Press and hold to activate</string> + <!-- Text for education page of cancel button to hide the page. [CHAR_LIMIT=NONE] --> <string name="rear_display_bottom_sheet_cancel">Cancel</string> <!-- Text for the user to confirm they flipped the device around. [CHAR_LIMIT=NONE] --> diff --git a/packages/SystemUI/res/xml/combined_qs_header_scene.xml b/packages/SystemUI/res/xml/combined_qs_header_scene.xml index c32de70771d0..38c164023315 100644 --- a/packages/SystemUI/res/xml/combined_qs_header_scene.xml +++ b/packages/SystemUI/res/xml/combined_qs_header_scene.xml @@ -124,6 +124,11 @@ </KeyFrameSet> </Transition> + <Transition + android:id="@+id/large_screen_header_transition" + app:constraintSetStart="@id/large_screen_header_constraint" + app:constraintSetEnd="@id/large_screen_header_constraint"/> + <Include app:constraintSet="@xml/large_screen_shade_header"/> <Include app:constraintSet="@xml/qs_header"/> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java index e226d58203f4..b057fe422fc4 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java @@ -362,8 +362,7 @@ public class PluginActionManager<T extends Plugin> { nb.addAction(new Action.Builder(null, "Disable plugin", pi).build()); mNotificationManager.notify(SystemMessage.NOTE_PLUGIN, nb.build()); // TODO: Warn user. - Log.w(TAG, "Plugin has invalid interface version " + e.getActualVersion() - + ", expected " + e.getExpectedVersion()); + Log.w(TAG, "Error loading plugin; " + e.getMessage()); } /** diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java index 5883b6c0e723..b92715516a75 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java @@ -39,7 +39,6 @@ public class PreviewPositionHelper { private boolean mIsOrientationChanged; private SplitBounds mSplitBounds; private int mDesiredStagePosition; - private boolean mTaskbarInApp; public Matrix getMatrix() { return mMatrix; @@ -58,10 +57,6 @@ public class PreviewPositionHelper { mDesiredStagePosition = desiredStagePosition; } - public void setTaskbarInApp(boolean taskbarInApp) { - mTaskbarInApp = taskbarInApp; - } - /** * Updates the matrix based on the provided parameters */ @@ -79,34 +74,21 @@ public class PreviewPositionHelper { float scaledTaskbarSize; float canvasScreenRatio; if (mSplitBounds != null) { - float fullscreenTaskWidth; - float fullscreenTaskHeight; - - float taskPercent; if (mSplitBounds.appsStackedVertically) { - taskPercent = mDesiredStagePosition != STAGE_POSITION_TOP_OR_LEFT - ? mSplitBounds.topTaskPercent - : (1 - (mSplitBounds.topTaskPercent + mSplitBounds.dividerHeightPercent)); - // Scale portrait height to that of the actual screen - fullscreenTaskHeight = screenHeightPx * taskPercent; - if (mTaskbarInApp) { - canvasScreenRatio = canvasHeight / fullscreenTaskHeight; + if (mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT) { + // Top app isn't cropped at all by taskbar + canvasScreenRatio = 0; } else { - if (mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT) { - // Top app isn't cropped at all by taskbar - canvasScreenRatio = 0; - } else { - // Same as fullscreen ratio - canvasScreenRatio = (float) canvasWidth / screenWidthPx; - } + // Same as fullscreen ratio + canvasScreenRatio = (float) canvasWidth / screenWidthPx; } } else { // For landscape, scale the width - taskPercent = mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT + float taskPercent = mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT ? mSplitBounds.leftTaskPercent : (1 - (mSplitBounds.leftTaskPercent + mSplitBounds.dividerWidthPercent)); // Scale landscape width to that of actual screen - fullscreenTaskWidth = screenWidthPx * taskPercent; + float fullscreenTaskWidth = screenWidthPx * taskPercent; canvasScreenRatio = canvasWidth / fullscreenTaskWidth; } } else { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java index 860c8e3a9f77..7da27b1d6898 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java @@ -260,7 +260,8 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey if (reason != PROMPT_REASON_NONE) { int promtReasonStringRes = mView.getPromptReasonStringRes(reason); if (promtReasonStringRes != 0) { - mMessageAreaController.setMessage(promtReasonStringRes); + mMessageAreaController.setMessage( + mView.getResources().getString(promtReasonStringRes), false); } } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index 40423cd9ac2c..62babadc45d8 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -9,6 +9,7 @@ import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.View; +import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.RelativeLayout; @@ -43,6 +44,21 @@ public class KeyguardClockSwitch extends RelativeLayout { public static final int LARGE = 0; public static final int SMALL = 1; + /** Returns a region for the large clock to position itself, based on the given parent. */ + public static Rect getLargeClockRegion(ViewGroup parent) { + int largeClockTopMargin = parent.getResources() + .getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin); + int targetHeight = parent.getResources() + .getDimensionPixelSize(R.dimen.large_clock_text_size) * 2; + int top = parent.getHeight() / 2 - targetHeight / 2 + + largeClockTopMargin / 2; + return new Rect( + parent.getLeft(), + top, + parent.getRight(), + top + targetHeight); + } + /** * Frame for small/large clocks */ @@ -129,17 +145,8 @@ public class KeyguardClockSwitch extends RelativeLayout { } if (mLargeClockFrame.isLaidOut()) { - int largeClockTopMargin = getResources() - .getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin); - int targetHeight = getResources() - .getDimensionPixelSize(R.dimen.large_clock_text_size) * 2; - int top = mLargeClockFrame.getHeight() / 2 - targetHeight / 2 - + largeClockTopMargin / 2; - mClock.getLargeClock().getEvents().onTargetRegionChanged(new Rect( - mLargeClockFrame.getLeft(), - top, - mLargeClockFrame.getRight(), - top + targetHeight)); + mClock.getLargeClock().getEvents().onTargetRegionChanged( + getLargeClockRegion(mLargeClockFrame)); } } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index 789f6218caf9..788f1200d603 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -78,6 +78,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS private int mCurrentClockSize = SMALL; private int mKeyguardSmallClockTopMargin = 0; + private int mKeyguardLargeClockTopMargin = 0; private final ClockRegistry.ClockChangeListener mClockChangedListener; private ViewGroup mStatusArea; @@ -164,6 +165,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mClockEventController.registerListeners(mView); mKeyguardSmallClockTopMargin = mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin); + mKeyguardLargeClockTopMargin = + mView.getResources().getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin); if (mOnlyClock) { View ksv = mView.findViewById(R.id.keyguard_slice_view); @@ -246,6 +249,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mView.onDensityOrFontScaleChanged(); mKeyguardSmallClockTopMargin = mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin); + mKeyguardLargeClockTopMargin = + mView.getResources().getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin); mView.updateClockTargetRegions(); } @@ -324,10 +329,18 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS } if (mLargeClockFrame.getVisibility() == View.VISIBLE) { + // This gets the expected clock bottom if mLargeClockFrame had a top margin, but it's + // top margin only contributed to height and didn't move the top of the view (as this + // was the computation previously). As we no longer have a margin, we add this back + // into the computation manually. int frameHeight = mLargeClockFrame.getHeight(); int clockHeight = clock.getLargeClock().getView().getHeight(); - return frameHeight / 2 + clockHeight / 2; + return frameHeight / 2 + clockHeight / 2 + mKeyguardLargeClockTopMargin / -2; } else { + // This is only called if we've never shown the large clock as the frame is inflated + // with 'gone', but then the visibility is never set when it is animated away by + // KeyguardClockSwitch, instead it is removed from the view hierarchy. + // TODO(b/261755021): Cleanup Large Frame Visibility int clockHeight = clock.getSmallClock().getView().getHeight(); return clockHeight + statusBarHeaderHeight + mKeyguardSmallClockTopMargin; } @@ -345,11 +358,15 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS if (mLargeClockFrame.getVisibility() == View.VISIBLE) { return clock.getLargeClock().getView().getHeight(); } else { + // Is not called except in certain edge cases, see comment in getClockBottom + // TODO(b/261755021): Cleanup Large Frame Visibility return clock.getSmallClock().getView().getHeight(); } } boolean isClockTopAligned() { + // Returns false except certain edge cases, see comment in getClockBottom + // TODO(b/261755021): Cleanup Large Frame Visibility return mLargeClockFrame.getVisibility() != View.VISIBLE; } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java index 2e9ad5868eba..d1c9a3090860 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java @@ -142,8 +142,11 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView> } public void startAppearAnimation() { - if (TextUtils.isEmpty(mMessageAreaController.getMessage())) { - mMessageAreaController.setMessage(getInitialMessageResId()); + if (TextUtils.isEmpty(mMessageAreaController.getMessage()) + && getInitialMessageResId() != 0) { + mMessageAreaController.setMessage( + mView.getResources().getString(getInitialMessageResId()), + /* animate= */ false); } mView.startAppearAnimation(); } @@ -163,9 +166,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView> } /** Determines the message to show in the bouncer when it first appears. */ - protected int getInitialMessageResId() { - return 0; - } + protected abstract int getInitialMessageResId(); /** Factory for a {@link KeyguardInputViewController}. */ public static class Factory { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java index 5d86ccd5409e..67e3400670ba 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java @@ -52,6 +52,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { private int mYTransOffset; private View mBouncerMessageView; @DevicePostureInt private int mLastDevicePosture = DEVICE_POSTURE_UNKNOWN; + public static final long ANIMATION_DURATION = 650; public KeyguardPINView(Context context) { this(context, null); @@ -181,7 +182,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { if (mAppearAnimator.isRunning()) { mAppearAnimator.cancel(); } - mAppearAnimator.setDuration(650); + mAppearAnimator.setDuration(ANIMATION_DURATION); mAppearAnimator.addUpdateListener(animation -> animate(animation.getAnimatedFraction())); mAppearAnimator.start(); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java index c985fd7bef82..c1fae9e44bd3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java @@ -24,6 +24,7 @@ import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT; +import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; import android.animation.Animator; @@ -107,6 +108,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView { return R.string.kg_prompt_reason_timeout_password; case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT: return R.string.kg_prompt_reason_timeout_password; + case PROMPT_REASON_TRUSTAGENT_EXPIRED: + return R.string.kg_prompt_reason_timeout_password; case PROMPT_REASON_NONE: return 0; default: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java index 571d2740773d..0c1748982e51 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java @@ -313,6 +313,9 @@ public class KeyguardPatternViewController case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT: mMessageAreaController.setMessage(R.string.kg_prompt_reason_timeout_pattern); break; + case PROMPT_REASON_TRUSTAGENT_EXPIRED: + mMessageAreaController.setMessage(R.string.kg_prompt_reason_timeout_pattern); + break; case PROMPT_REASON_NONE: break; default: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java index c46e33d9fd53..0a91150e6c39 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -22,6 +22,7 @@ import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT; +import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; import android.animation.Animator; @@ -123,6 +124,8 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView return R.string.kg_prompt_reason_timeout_pin; case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT: return R.string.kg_prompt_reason_timeout_pin; + case PROMPT_REASON_TRUSTAGENT_EXPIRED: + return R.string.kg_prompt_reason_timeout_pin; case PROMPT_REASON_NONE: return 0; default: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java index f7423ed12e68..8011efdc1ae7 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java @@ -139,4 +139,9 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB super.startErrorAnimation(); mView.startErrorAnimation(); } + + @Override + protected int getInitialMessageResId() { + return R.string.keyguard_enter_your_pin; + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java index f51ac325c9c1..35b2db27d879 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java @@ -74,9 +74,4 @@ public class KeyguardPinViewController return mView.startDisappearAnimation( mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable); } - - @Override - protected int getInitialMessageResId() { - return R.string.keyguard_enter_your_pin; - } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 8f3484a0c99b..5d7a6f122e69 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -36,8 +36,11 @@ import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY; import static java.lang.Integer.max; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.app.Activity; import android.app.AlertDialog; import android.app.admin.DevicePolicyManager; @@ -967,11 +970,23 @@ public class KeyguardSecurityContainer extends ConstraintLayout { } mUserSwitcherViewGroup.setAlpha(0f); - ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mUserSwitcherViewGroup, View.ALPHA, - 1f); - alphaAnim.setInterpolator(Interpolators.ALPHA_IN); - alphaAnim.setDuration(500); - alphaAnim.start(); + ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f); + int yTrans = mView.getResources().getDimensionPixelSize(R.dimen.pin_view_trans_y_entry); + animator.setInterpolator(Interpolators.STANDARD_DECELERATE); + animator.setDuration(650); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mUserSwitcherViewGroup.setAlpha(1f); + mUserSwitcherViewGroup.setTranslationY(0f); + } + }); + animator.addUpdateListener(animation -> { + float value = (float) animation.getAnimatedValue(); + mUserSwitcherViewGroup.setAlpha(value); + mUserSwitcherViewGroup.setTranslationY(yTrans - yTrans * value); + }); + animator.start(); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java index ac00e9453c97..67d77e53738a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java @@ -61,6 +61,12 @@ public interface KeyguardSecurityView { int PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT = 7; /** + * Some auth is required because the trustagent expired either from timeout or manually by the + * user + */ + int PROMPT_REASON_TRUSTAGENT_EXPIRED = 8; + + /** * Reset the view and prepare to take input. This should do things like clearing the * password or pattern and clear error messages. */ diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java index a5c8c7881e3b..39b567fd21b9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java @@ -156,5 +156,10 @@ public class KeyguardSecurityViewFlipperController @Override public void onStartingToHide() { } + + @Override + protected int getInitialMessageResId() { + return 0; + } } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 71d5bf57baf6..ec4b78065c63 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1660,7 +1660,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onAuthenticationFailed() { - requestActiveUnlock( + requestActiveUnlockDismissKeyguard( ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL, "fingerprintFailure"); handleFingerprintAuthFailed(); @@ -2591,6 +2591,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } /** + * Attempts to trigger active unlock from trust agent with a request to dismiss the keyguard. + */ + public void requestActiveUnlockDismissKeyguard( + @NonNull ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN requestOrigin, + String extraReason + ) { + requestActiveUnlock( + requestOrigin, + extraReason + "-dismissKeyguard", true); + } + + /** * Whether the UDFPS bouncer is showing. */ public void setUdfpsBouncerShowing(boolean showing) { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java b/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java index 632fcdc16259..0fc9ef96f6e9 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java @@ -22,6 +22,8 @@ import android.os.Handler; import android.os.HandlerThread; import android.util.Log; +import androidx.annotation.Nullable; + import com.android.systemui.dagger.GlobalRootComponent; import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.WMComponent; @@ -53,6 +55,7 @@ public abstract class SystemUIInitializer { mContext = context; } + @Nullable protected abstract GlobalRootComponent.Builder getGlobalRootComponentBuilder(); /** @@ -69,6 +72,11 @@ public abstract class SystemUIInitializer { * Starts the initialization process. This stands up the Dagger graph. */ public void init(boolean fromTest) throws ExecutionException, InterruptedException { + GlobalRootComponent.Builder globalBuilder = getGlobalRootComponentBuilder(); + if (globalBuilder == null) { + return; + } + mRootComponent = getGlobalRootComponentBuilder() .context(mContext) .instrumentationTest(fromTest) @@ -119,6 +127,7 @@ public abstract class SystemUIInitializer { .setBackAnimation(Optional.ofNullable(null)) .setDesktopMode(Optional.ofNullable(null)); } + mSysUIComponent = builder.build(); if (initializeComponents) { mSysUIComponent.init(); diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt b/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt index 8aa3040c6015..55c095b0be25 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt @@ -16,6 +16,7 @@ package com.android.systemui +import android.app.Application import android.content.Context import com.android.systemui.dagger.DaggerReferenceGlobalRootComponent import com.android.systemui.dagger.GlobalRootComponent @@ -24,7 +25,17 @@ import com.android.systemui.dagger.GlobalRootComponent * {@link SystemUIInitializer} that stands up AOSP SystemUI. */ class SystemUIInitializerImpl(context: Context) : SystemUIInitializer(context) { - override fun getGlobalRootComponentBuilder(): GlobalRootComponent.Builder { - return DaggerReferenceGlobalRootComponent.builder() + + override fun getGlobalRootComponentBuilder(): GlobalRootComponent.Builder? { + return when (Application.getProcessName()) { + SCREENSHOT_CROSS_PROFILE_PROCESS -> null + else -> DaggerReferenceGlobalRootComponent.builder() + } + } + + companion object { + private const val SYSTEMUI_PROCESS = "com.android.systemui" + private const val SCREENSHOT_CROSS_PROFILE_PROCESS = + "$SYSTEMUI_PROCESS:screenshot_cross_profile" } } diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt index e2ef2477c836..58d40d349dec 100644 --- a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt @@ -28,7 +28,6 @@ import android.os.RemoteException import android.os.UserHandle import android.util.Log import android.view.WindowManager -import androidx.annotation.VisibleForTesting import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.ActivityIntentHelper import com.android.systemui.dagger.qualifiers.Main @@ -83,7 +82,7 @@ class CameraGestureHelper @Inject constructor( */ fun launchCamera(source: Int) { val intent: Intent = getStartCameraIntent() - intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source) + intent.putExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, source) val wouldLaunchResolverActivity = activityIntentHelper.wouldLaunchResolverActivity( intent, KeyguardUpdateMonitor.getCurrentUser() ) @@ -149,9 +148,4 @@ class CameraGestureHelper @Inject constructor( cameraIntents.getInsecureCameraIntent() } } - - companion object { - @VisibleForTesting - const val EXTRA_CAMERA_LAUNCH_SOURCE = "com.android.systemui.camera_launch_source" - } } diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt index f8a20023e47a..867faf9843fe 100644 --- a/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt +++ b/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt @@ -29,6 +29,7 @@ class CameraIntents { MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE val DEFAULT_INSECURE_CAMERA_INTENT_ACTION = MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA + const val EXTRA_LAUNCH_SOURCE = "com.android.systemui.camera_launch_source" @JvmStatic fun getOverrideCameraPackage(context: Context): String? { diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt index 4aa597ef3d28..8d0edf829416 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt @@ -50,7 +50,12 @@ object ControlsAnimations { * Setup an activity to handle enter/exit animations. [view] should be the root of the content. * Fade and translate together. */ - fun observerForAnimations(view: ViewGroup, window: Window, intent: Intent): LifecycleObserver { + fun observerForAnimations( + view: ViewGroup, + window: Window, + intent: Intent, + animateY: Boolean = true + ): LifecycleObserver { return object : LifecycleObserver { var showAnimation = intent.getBooleanExtra(ControlsUiController.EXTRA_ANIMATE, false) @@ -61,8 +66,12 @@ object ControlsAnimations { view.transitionAlpha = 0.0f if (translationY == -1f) { - translationY = view.context.resources.getDimensionPixelSize( - R.dimen.global_actions_controls_y_translation).toFloat() + if (animateY) { + translationY = view.context.resources.getDimensionPixelSize( + R.dimen.global_actions_controls_y_translation).toFloat() + } else { + translationY = 0f + } } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt index 5d611c4c8212..d8d8c0ead06a 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt @@ -70,7 +70,8 @@ class ControlsActivity @Inject constructor( ControlsAnimations.observerForAnimations( requireViewById<ViewGroup>(R.id.control_detail_root), window, - intent + intent, + !featureFlags.isEnabled(Flags.USE_APP_PANELS) ) ) diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index fb678aa420bf..1e3e5cd1c31c 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -186,7 +186,7 @@ class ControlsUiControllerImpl @Inject constructor ( val allStructures = controlsController.get().getFavorites() val selected = getPreferredSelectedItem(allStructures) val anyPanels = controlsListingController.get().getCurrentServices() - .none { it.panelActivity != null } + .any { it.panelActivity != null } return if (controlsController.get().addSeedingFavoritesCallback(onSeedingComplete)) { ControlsActivity::class.java diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt index 7143be298a9d..f5764c2fdc04 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt @@ -24,6 +24,10 @@ import android.app.PendingIntent import android.content.ComponentName import android.content.Context import android.content.Intent +import android.graphics.Color +import android.graphics.drawable.ShapeDrawable +import android.graphics.drawable.shapes.RoundRectShape +import com.android.systemui.R import com.android.systemui.util.boundsOnScreen import com.android.wm.shell.TaskView import java.util.concurrent.Executor @@ -64,6 +68,16 @@ class PanelTaskViewController( options.taskAlwaysOnTop = true taskView.post { + val roundedCorner = + activityContext.resources.getDimensionPixelSize( + R.dimen.notification_corner_radius + ) + val radii = FloatArray(8) { roundedCorner.toFloat() } + taskView.background = + ShapeDrawable(RoundRectShape(radii, null, null)).apply { + setTint(Color.TRANSPARENT) + } + taskView.clipToOutline = true taskView.startActivity( pendingIntent, fillInIntent, diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt index 0087c8439370..9b8ef71882e9 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt @@ -21,11 +21,12 @@ import android.animation.AnimatorSet import android.animation.ValueAnimator import android.view.View import android.view.animation.Interpolator -import androidx.annotation.FloatRange import androidx.core.animation.doOnEnd import com.android.systemui.animation.Interpolators import com.android.systemui.dreams.complication.ComplicationHostViewController import com.android.systemui.dreams.complication.ComplicationLayoutParams +import com.android.systemui.dreams.complication.ComplicationLayoutParams.POSITION_BOTTOM +import com.android.systemui.dreams.complication.ComplicationLayoutParams.POSITION_TOP import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position import com.android.systemui.dreams.dagger.DreamOverlayModule import com.android.systemui.statusbar.BlurUtils @@ -41,16 +42,15 @@ constructor( private val mComplicationHostViewController: ComplicationHostViewController, private val mStatusBarViewController: DreamOverlayStatusBarViewController, private val mOverlayStateController: DreamOverlayStateController, + @Named(DreamOverlayModule.DREAM_BLUR_RADIUS) private val mDreamBlurRadius: Int, @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION) private val mDreamInBlurAnimDurationMs: Long, - @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DELAY) - private val mDreamInBlurAnimDelayMs: Long, @Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION) private val mDreamInComplicationsAnimDurationMs: Long, - @Named(DreamOverlayModule.DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY) - private val mDreamInTopComplicationsAnimDelayMs: Long, - @Named(DreamOverlayModule.DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY) - private val mDreamInBottomComplicationsAnimDelayMs: Long, + @Named(DreamOverlayModule.DREAM_IN_TRANSLATION_Y_DISTANCE) + private val mDreamInTranslationYDistance: Int, + @Named(DreamOverlayModule.DREAM_IN_TRANSLATION_Y_DURATION) + private val mDreamInTranslationYDurationMs: Long, @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DISTANCE) private val mDreamOutTranslationYDistance: Int, @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DURATION) @@ -74,7 +74,7 @@ constructor( */ private var mCurrentAlphaAtPosition = mutableMapOf<Int, Float>() - @FloatRange(from = 0.0, to = 1.0) private var mBlurProgress: Float = 0f + private var mCurrentBlurRadius: Float = 0f /** Starts the dream content and dream overlay entry animations. */ @JvmOverloads @@ -86,25 +86,23 @@ constructor( playTogether( blurAnimator( view = view, - from = 1f, - to = 0f, + fromBlurRadius = mDreamBlurRadius.toFloat(), + toBlurRadius = 0f, durationMs = mDreamInBlurAnimDurationMs, - delayMs = mDreamInBlurAnimDelayMs + interpolator = Interpolators.EMPHASIZED_DECELERATE ), alphaAnimator( from = 0f, to = 1f, durationMs = mDreamInComplicationsAnimDurationMs, - delayMs = mDreamInTopComplicationsAnimDelayMs, - position = ComplicationLayoutParams.POSITION_TOP + interpolator = Interpolators.LINEAR + ), + translationYAnimator( + from = mDreamInTranslationYDistance.toFloat(), + to = 0f, + durationMs = mDreamInTranslationYDurationMs, + interpolator = Interpolators.EMPHASIZED_DECELERATE ), - alphaAnimator( - from = 0f, - to = 1f, - durationMs = mDreamInComplicationsAnimDurationMs, - delayMs = mDreamInBottomComplicationsAnimDelayMs, - position = ComplicationLayoutParams.POSITION_BOTTOM - ) ) doOnEnd { mAnimator = null @@ -130,47 +128,48 @@ constructor( view = view, // Start the blurring wherever the entry animation ended, in // case it was cancelled early. - from = mBlurProgress, - to = 1f, - durationMs = mDreamOutBlurDurationMs + fromBlurRadius = mCurrentBlurRadius, + toBlurRadius = mDreamBlurRadius.toFloat(), + durationMs = mDreamOutBlurDurationMs, + interpolator = Interpolators.EMPHASIZED_ACCELERATE ), translationYAnimator( from = 0f, to = mDreamOutTranslationYDistance.toFloat(), durationMs = mDreamOutTranslationYDurationMs, delayMs = mDreamOutTranslationYDelayBottomMs, - position = ComplicationLayoutParams.POSITION_BOTTOM, - animInterpolator = Interpolators.EMPHASIZED_ACCELERATE + positions = POSITION_BOTTOM, + interpolator = Interpolators.EMPHASIZED_ACCELERATE ), translationYAnimator( from = 0f, to = mDreamOutTranslationYDistance.toFloat(), durationMs = mDreamOutTranslationYDurationMs, delayMs = mDreamOutTranslationYDelayTopMs, - position = ComplicationLayoutParams.POSITION_TOP, - animInterpolator = Interpolators.EMPHASIZED_ACCELERATE + positions = POSITION_TOP, + interpolator = Interpolators.EMPHASIZED_ACCELERATE ), alphaAnimator( from = mCurrentAlphaAtPosition.getOrDefault( - key = ComplicationLayoutParams.POSITION_BOTTOM, + key = POSITION_BOTTOM, defaultValue = 1f ), to = 0f, durationMs = mDreamOutAlphaDurationMs, delayMs = mDreamOutAlphaDelayBottomMs, - position = ComplicationLayoutParams.POSITION_BOTTOM + positions = POSITION_BOTTOM ), alphaAnimator( from = mCurrentAlphaAtPosition.getOrDefault( - key = ComplicationLayoutParams.POSITION_TOP, + key = POSITION_TOP, defaultValue = 1f ), to = 0f, durationMs = mDreamOutAlphaDurationMs, delayMs = mDreamOutAlphaDelayTopMs, - position = ComplicationLayoutParams.POSITION_TOP + positions = POSITION_TOP ) ) doOnEnd { @@ -194,20 +193,21 @@ constructor( private fun blurAnimator( view: View, - from: Float, - to: Float, + fromBlurRadius: Float, + toBlurRadius: Float, durationMs: Long, - delayMs: Long = 0 + delayMs: Long = 0, + interpolator: Interpolator = Interpolators.LINEAR ): Animator { - return ValueAnimator.ofFloat(from, to).apply { + return ValueAnimator.ofFloat(fromBlurRadius, toBlurRadius).apply { duration = durationMs startDelay = delayMs - interpolator = Interpolators.LINEAR + this.interpolator = interpolator addUpdateListener { animator: ValueAnimator -> - mBlurProgress = animator.animatedValue as Float + mCurrentBlurRadius = animator.animatedValue as Float mBlurUtils.applyBlur( viewRootImpl = view.viewRootImpl, - radius = mBlurUtils.blurRadiusOfRatio(mBlurProgress).toInt(), + radius = mCurrentBlurRadius.toInt(), opaque = false ) } @@ -218,18 +218,24 @@ constructor( from: Float, to: Float, durationMs: Long, - delayMs: Long, - @Position position: Int + delayMs: Long = 0, + @Position positions: Int = POSITION_TOP or POSITION_BOTTOM, + interpolator: Interpolator = Interpolators.LINEAR ): Animator { return ValueAnimator.ofFloat(from, to).apply { duration = durationMs startDelay = delayMs - interpolator = Interpolators.LINEAR + this.interpolator = interpolator addUpdateListener { va: ValueAnimator -> - setElementsAlphaAtPosition( - alpha = va.animatedValue as Float, - position = position, - fadingOut = to < from + ComplicationLayoutParams.iteratePositions( + { position: Int -> + setElementsAlphaAtPosition( + alpha = va.animatedValue as Float, + position = position, + fadingOut = to < from + ) + }, + positions ) } } @@ -239,16 +245,21 @@ constructor( from: Float, to: Float, durationMs: Long, - delayMs: Long, - @Position position: Int, - animInterpolator: Interpolator + delayMs: Long = 0, + @Position positions: Int = POSITION_TOP or POSITION_BOTTOM, + interpolator: Interpolator = Interpolators.LINEAR ): Animator { return ValueAnimator.ofFloat(from, to).apply { duration = durationMs startDelay = delayMs - interpolator = animInterpolator + this.interpolator = interpolator addUpdateListener { va: ValueAnimator -> - setElementsTranslationYAtPosition(va.animatedValue as Float, position) + ComplicationLayoutParams.iteratePositions( + { position: Int -> + setElementsTranslationYAtPosition(va.animatedValue as Float, position) + }, + positions + ) } } } @@ -263,7 +274,7 @@ constructor( CrossFadeHelper.fadeIn(view, alpha, /* remap= */ false) } } - if (position == ComplicationLayoutParams.POSITION_TOP) { + if (position == POSITION_TOP) { mStatusBarViewController.setFadeAmount(alpha, fadingOut) } } @@ -273,7 +284,7 @@ constructor( mComplicationHostViewController.getViewsAtPosition(position).forEach { v -> v.translationY = translationY } - if (position == ComplicationLayoutParams.POSITION_TOP) { + if (position == POSITION_TOP) { mStatusBarViewController.setTranslationY(translationY) } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java index d145f5c14917..87c5f51ce13a 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java @@ -16,6 +16,8 @@ package com.android.systemui.dreams; +import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_SERVICE_COMPONENT; + import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -35,6 +37,7 @@ import com.android.systemui.CoreStartable; import com.android.systemui.dagger.qualifiers.Main; import javax.inject.Inject; +import javax.inject.Named; /** * {@link DreamOverlayRegistrant} is responsible for telling system server that SystemUI should be @@ -98,12 +101,13 @@ public class DreamOverlayRegistrant implements CoreStartable { } @Inject - public DreamOverlayRegistrant(Context context, @Main Resources resources) { + public DreamOverlayRegistrant(Context context, @Main Resources resources, + @Named(DREAM_OVERLAY_SERVICE_COMPONENT) ComponentName dreamOverlayServiceComponent) { mContext = context; mResources = resources; mDreamManager = IDreamManager.Stub.asInterface( ServiceManager.getService(DreamService.DREAM_SERVICE)); - mOverlayServiceComponent = new ComponentName(mContext, DreamOverlayService.class); + mOverlayServiceComponent = dreamOverlayServiceComponent; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java index 5f942b6fb834..ccfdd0966e98 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java @@ -16,6 +16,8 @@ package com.android.systemui.dreams; +import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_ENABLED; + import android.service.dreams.DreamService; import android.util.Log; @@ -37,6 +39,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; import javax.inject.Inject; +import javax.inject.Named; /** * {@link DreamOverlayStateController} is the source of truth for Dream overlay configurations and @@ -83,6 +86,7 @@ public class DreamOverlayStateController implements } private final Executor mExecutor; + private final boolean mOverlayEnabled; private final ArrayList<Callback> mCallbacks = new ArrayList<>(); @Complication.ComplicationType @@ -94,14 +98,27 @@ public class DreamOverlayStateController implements @VisibleForTesting @Inject - public DreamOverlayStateController(@Main Executor executor) { + public DreamOverlayStateController(@Main Executor executor, + @Named(DREAM_OVERLAY_ENABLED) boolean overlayEnabled) { mExecutor = executor; + mOverlayEnabled = overlayEnabled; + if (DEBUG) { + Log.d(TAG, "Dream overlay enabled:" + mOverlayEnabled); + } } /** * Adds a complication to be included on the dream overlay. */ public void addComplication(Complication complication) { + if (!mOverlayEnabled) { + if (DEBUG) { + Log.d(TAG, + "Ignoring adding complication due to overlay disabled:" + complication); + } + return; + } + mExecutor.execute(() -> { if (mComplications.add(complication)) { if (DEBUG) { @@ -116,6 +133,14 @@ public class DreamOverlayStateController implements * Removes a complication from inclusion on the dream overlay. */ public void removeComplication(Complication complication) { + if (!mOverlayEnabled) { + if (DEBUG) { + Log.d(TAG, + "Ignoring removing complication due to overlay disabled:" + complication); + } + return; + } + mExecutor.execute(() -> { if (mComplications.remove(complication)) { if (DEBUG) { @@ -193,7 +218,7 @@ public class DreamOverlayStateController implements * @return {@code true} if overlay is active, {@code false} otherwise. */ public boolean isOverlayActive() { - return containsState(STATE_DREAM_OVERLAY_ACTIVE); + return mOverlayEnabled && containsState(STATE_DREAM_OVERLAY_ACTIVE); } /** diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java index 100ccc35e638..a2e11b21ea59 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java @@ -138,19 +138,27 @@ public class ComplicationHostViewController extends ViewController<ConstraintLay final ComplicationId id = complication.getId(); final Complication.ViewHolder viewHolder = complication.getComplication() .createView(complication); + + final View view = viewHolder.getView(); + + if (view == null) { + Log.e(TAG, "invalid complication view. null view supplied by ViewHolder"); + return; + } + // Complications to be added before dream entry animations are finished are set // to invisible and are animated in. if (!mEntryAnimationsFinished) { - viewHolder.getView().setVisibility(View.INVISIBLE); + view.setVisibility(View.INVISIBLE); } mComplications.put(id, viewHolder); - if (viewHolder.getView().getParent() != null) { + if (view.getParent() != null) { Log.e(TAG, "View for complication " + complication.getComplication().getClass() + " already has a parent. Make sure not to reuse complication " + "views!"); } - mLayoutEngine.addComplication(id, viewHolder.getView(), + mLayoutEngine.addComplication(id, view, viewHolder.getLayoutParams(), viewHolder.getCategory()); }); } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java index 1755cb92da70..99e19fc96d8f 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java @@ -251,9 +251,17 @@ public class ComplicationLayoutParams extends ViewGroup.LayoutParams { * position specified for this {@link ComplicationLayoutParams}. */ public void iteratePositions(Consumer<Integer> consumer) { + iteratePositions(consumer, mPosition); + } + + /** + * Iterates over the defined positions and invokes the specified {@link Consumer} for each + * position specified by the given {@code position}. + */ + public static void iteratePositions(Consumer<Integer> consumer, @Position int position) { for (int currentPosition = FIRST_POSITION; currentPosition <= LAST_POSITION; currentPosition <<= 1) { - if ((mPosition & currentPosition) == currentPosition) { + if ((position & currentPosition) == currentPosition) { consumer.accept(currentPosition); } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java index ee0051220787..1065b94508f8 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java @@ -136,8 +136,15 @@ public class DreamHomeControlsComplication implements Complication { final boolean hasFavorites = mControlsComponent.getControlsController() .map(c -> !c.getFavorites().isEmpty()) .orElse(false); + boolean hasPanels = false; + for (int i = 0; i < controlsServices.size(); i++) { + if (controlsServices.get(i).getPanelActivity() != null) { + hasPanels = true; + break; + } + } final ControlsComponent.Visibility visibility = mControlsComponent.getVisibility(); - return hasFavorites && visibility != UNAVAILABLE; + return (hasFavorites || hasPanels) && visibility != UNAVAILABLE; } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java index 101f4a450071..e7b29bb84b3d 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java @@ -16,7 +16,9 @@ package com.android.systemui.dreams.dagger; +import android.content.ComponentName; import android.content.Context; +import android.content.pm.PackageManager; import android.content.res.Resources; import com.android.dream.lowlight.dagger.LowLightDreamModule; @@ -24,6 +26,7 @@ import com.android.settingslib.dream.DreamBackend; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.DreamOverlayNotificationCountProvider; +import com.android.systemui.dreams.DreamOverlayService; import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule; import java.util.Optional; @@ -45,10 +48,35 @@ import dagger.Provides; }) public interface DreamModule { String DREAM_ONLY_ENABLED_FOR_DOCK_USER = "dream_only_enabled_for_dock_user"; + String DREAM_OVERLAY_SERVICE_COMPONENT = "dream_overlay_service_component"; + String DREAM_OVERLAY_ENABLED = "dream_overlay_enabled"; String DREAM_SUPPORTED = "dream_supported"; /** + * Provides the dream component + */ + @Provides + @Named(DREAM_OVERLAY_SERVICE_COMPONENT) + static ComponentName providesDreamOverlayService(Context context) { + return new ComponentName(context, DreamOverlayService.class); + } + + /** + * Provides whether dream overlay is enabled. + */ + @Provides + @Named(DREAM_OVERLAY_ENABLED) + static Boolean providesDreamOverlayEnabled(PackageManager packageManager, + @Named(DREAM_OVERLAY_SERVICE_COMPONENT) ComponentName component) { + try { + return packageManager.getServiceInfo(component, PackageManager.GET_META_DATA).enabled; + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + + /** * Provides an instance of the dream backend. */ @Provides diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java index ed0e1d97e40a..4f1ac1a8abd5 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java @@ -47,14 +47,14 @@ public abstract class DreamOverlayModule { public static final String BURN_IN_PROTECTION_UPDATE_INTERVAL = "burn_in_protection_update_interval"; public static final String MILLIS_UNTIL_FULL_JITTER = "millis_until_full_jitter"; + public static final String DREAM_BLUR_RADIUS = "DREAM_BLUR_RADIUS"; public static final String DREAM_IN_BLUR_ANIMATION_DURATION = "dream_in_blur_anim_duration"; - public static final String DREAM_IN_BLUR_ANIMATION_DELAY = "dream_in_blur_anim_delay"; public static final String DREAM_IN_COMPLICATIONS_ANIMATION_DURATION = "dream_in_complications_anim_duration"; - public static final String DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY = - "dream_in_top_complications_anim_delay"; - public static final String DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY = - "dream_in_bottom_complications_anim_delay"; + public static final String DREAM_IN_TRANSLATION_Y_DISTANCE = + "dream_in_complications_translation_y"; + public static final String DREAM_IN_TRANSLATION_Y_DURATION = + "dream_in_complications_translation_y_duration"; public static final String DREAM_OUT_TRANSLATION_Y_DISTANCE = "dream_out_complications_translation_y"; public static final String DREAM_OUT_TRANSLATION_Y_DURATION = @@ -139,21 +139,21 @@ public abstract class DreamOverlayModule { } /** - * Duration in milliseconds of the dream in un-blur animation. + * The blur radius applied to the dream overlay at dream entry and exit. */ @Provides - @Named(DREAM_IN_BLUR_ANIMATION_DURATION) - static long providesDreamInBlurAnimationDuration(@Main Resources resources) { - return (long) resources.getInteger(R.integer.config_dreamOverlayInBlurDurationMs); + @Named(DREAM_BLUR_RADIUS) + static int providesDreamBlurRadius(@Main Resources resources) { + return resources.getDimensionPixelSize(R.dimen.dream_overlay_anim_blur_radius); } /** - * Delay in milliseconds of the dream in un-blur animation. + * Duration in milliseconds of the dream in un-blur animation. */ @Provides - @Named(DREAM_IN_BLUR_ANIMATION_DELAY) - static long providesDreamInBlurAnimationDelay(@Main Resources resources) { - return (long) resources.getInteger(R.integer.config_dreamOverlayInBlurDelayMs); + @Named(DREAM_IN_BLUR_ANIMATION_DURATION) + static long providesDreamInBlurAnimationDuration(@Main Resources resources) { + return (long) resources.getInteger(R.integer.config_dreamOverlayInBlurDurationMs); } /** @@ -166,22 +166,23 @@ public abstract class DreamOverlayModule { } /** - * Delay in milliseconds of the dream in top complications fade-in animation. + * Provides the number of pixels to translate complications when entering a dream. */ @Provides - @Named(DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY) - static long providesDreamInTopComplicationsAnimationDelay(@Main Resources resources) { - return (long) resources.getInteger(R.integer.config_dreamOverlayInTopComplicationsDelayMs); + @Named(DREAM_IN_TRANSLATION_Y_DISTANCE) + @DreamOverlayComponent.DreamOverlayScope + static int providesDreamInComplicationsTranslationY(@Main Resources resources) { + return resources.getDimensionPixelSize(R.dimen.dream_overlay_entry_y_offset); } /** - * Delay in milliseconds of the dream in bottom complications fade-in animation. + * Provides the duration in ms of the y-translation when dream enters. */ @Provides - @Named(DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY) - static long providesDreamInBottomComplicationsAnimationDelay(@Main Resources resources) { - return (long) resources.getInteger( - R.integer.config_dreamOverlayInBottomComplicationsDelayMs); + @Named(DREAM_IN_TRANSLATION_Y_DURATION) + @DreamOverlayComponent.DreamOverlayScope + static long providesDreamInComplicationsTranslationYDuration(@Main Resources resources) { + return (long) resources.getInteger(R.integer.config_dreamOverlayInTranslationYDurationMs); } /** diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 1ee51ce3e160..efb513d57db6 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -83,7 +83,7 @@ object Flags { val STABILITY_INDEX_FIX = releasedFlag(114, "stability_index_fix") // TODO(b/259559750): Tracking Bug - val SEMI_STABLE_SORT = unreleasedFlag(115, "semi_stable_sort", teamfood = true) + val SEMI_STABLE_SORT = releasedFlag(115, "semi_stable_sort") @JvmField val USE_ROUNDNESS_SOURCETYPES = unreleasedFlag(116, "use_roundness_sourcetype", teamfood = true) @@ -285,7 +285,8 @@ object Flags { // TODO(b/254513168): Tracking Bug @JvmField val UMO_SURFACE_RIPPLE = unreleasedFlag(907, "umo_surface_ripple") - @JvmField val MEDIA_FALSING_PENALTY = unreleasedFlag(908, "media_falsing_media") + @JvmField + val MEDIA_FALSING_PENALTY = unreleasedFlag(908, "media_falsing_media", teamfood = true) // TODO(b/261734857): Tracking Bug @JvmField val UMO_TURBULENCE_NOISE = unreleasedFlag(909, "umo_turbulence_noise") @@ -435,6 +436,8 @@ object Flags { // 2300 - stylus @JvmField val TRACK_STYLUS_EVER_USED = unreleasedFlag(2300, "track_stylus_ever_used") @JvmField val ENABLE_STYLUS_CHARGING_UI = unreleasedFlag(2301, "enable_stylus_charging_ui") + @JvmField + val ENABLE_USI_BATTERY_NOTIFICATIONS = unreleasedFlag(2302, "enable_usi_battery_notifications") // 2400 - performance tools and debugging info // TODO(b/238923086): Tracking Bug diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProvider.kt index 4ae37c51f278..cbcede023708 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProvider.kt @@ -21,14 +21,18 @@ import android.content.ContentProvider import android.content.ContentValues import android.content.Context import android.content.UriMatcher +import android.content.pm.PackageManager import android.content.pm.ProviderInfo import android.database.Cursor import android.database.MatrixCursor import android.net.Uri +import android.os.Binder +import android.os.Bundle import android.util.Log import com.android.systemui.SystemUIAppComponentFactoryBase import com.android.systemui.SystemUIAppComponentFactoryBase.ContextAvailableCallback import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor +import com.android.systemui.keyguard.ui.preview.KeyguardRemotePreviewManager import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract as Contract import javax.inject.Inject import kotlinx.coroutines.runBlocking @@ -37,6 +41,7 @@ class KeyguardQuickAffordanceProvider : ContentProvider(), SystemUIAppComponentFactoryBase.ContextInitializer { @Inject lateinit var interactor: KeyguardQuickAffordanceInteractor + @Inject lateinit var previewManager: KeyguardRemotePreviewManager private lateinit var contextAvailableCallback: ContextAvailableCallback @@ -149,6 +154,21 @@ class KeyguardQuickAffordanceProvider : return deleteSelection(uri, selectionArgs) } + override fun call(method: String, arg: String?, extras: Bundle?): Bundle? { + return if ( + requireContext() + .checkPermission( + android.Manifest.permission.BIND_WALLPAPER, + Binder.getCallingPid(), + Binder.getCallingUid(), + ) == PackageManager.PERMISSION_GRANTED + ) { + previewManager.preview(extras) + } else { + null + } + } + private fun insertSelection(values: ContentValues?): Uri? { if (values == null) { throw IllegalArgumentException("Cannot insert selection, no values passed in!") diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 306e92e6c96c..96ec43dd725e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -25,6 +25,7 @@ import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NAV_BA import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_OCCLUSION; import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD; import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_UNLOCK_ANIMATION; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; @@ -142,12 +143,12 @@ import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.util.DeviceConfigProxy; +import dagger.Lazy; + import java.io.PrintWriter; import java.util.ArrayList; import java.util.concurrent.Executor; -import dagger.Lazy; - /** * Mediates requests related to the keyguard. This includes queries about the * state of the keyguard, power management events that effect whether the keyguard @@ -821,6 +822,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } else if (trustAgentsEnabled && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) { return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; + } else if (trustAgentsEnabled + && (strongAuth & SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED) != 0) { + return KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED; } else if (any && ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0 || mUpdateMonitor.isFingerprintLockedOut())) { return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT; @@ -1613,7 +1617,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // TODO: Rename all screen off/on references to interactive/sleeping synchronized (this) { mDeviceInteractive = true; - if (mPendingLock && !cameraGestureTriggered) { + if (mPendingLock && !cameraGestureTriggered && !mWakeAndUnlocking) { doKeyguardLocked(null); } mAnimatingScreenOff = false; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt index 2558fab216a0..394426df5552 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt @@ -130,6 +130,7 @@ constructor( state( isFeatureEnabled = component.isEnabled(), hasFavorites = favorites?.isNotEmpty() == true, + hasPanels = serviceInfos.any { it.panelActivity != null }, hasServiceInfos = serviceInfos.isNotEmpty(), iconResourceId = component.getTileImageId(), visibility = component.getVisibility(), @@ -148,13 +149,14 @@ constructor( private fun state( isFeatureEnabled: Boolean, hasFavorites: Boolean, + hasPanels: Boolean, hasServiceInfos: Boolean, visibility: ControlsComponent.Visibility, @DrawableRes iconResourceId: Int?, ): KeyguardQuickAffordanceConfig.LockScreenState { return if ( isFeatureEnabled && - hasFavorites && + (hasFavorites || hasPanels) && hasServiceInfos && iconResourceId != null && visibility == ControlsComponent.Visibility.AVAILABLE diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt index 748c6e8b75b9..57668c795d1c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt @@ -34,7 +34,6 @@ import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentati import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition import com.android.systemui.plugins.ActivityStarter import com.android.systemui.settings.UserTracker -import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract import com.android.systemui.statusbar.policy.KeyguardStateController import dagger.Lazy @@ -62,12 +61,20 @@ constructor( private val isUsingRepository: Boolean get() = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES) + /** + * Whether the UI should use the long press gesture to activate quick affordances. + * + * If `false`, the UI goes back to using single taps. + */ + val useLongPress: Boolean + get() = featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES) + /** Returns an observable for the quick affordance at the given position. */ fun quickAffordance( position: KeyguardQuickAffordancePosition ): Flow<KeyguardQuickAffordanceModel> { return combine( - quickAffordanceInternal(position), + quickAffordanceAlwaysVisible(position), keyguardInteractor.isDozing, keyguardInteractor.isKeyguardShowing, ) { affordance, isDozing, isKeyguardShowing -> @@ -80,6 +87,19 @@ constructor( } /** + * Returns an observable for the quick affordance at the given position but always visible, + * regardless of lock screen state. + * + * This is useful for experiences like the lock screen preview mode, where the affordances must + * always be visible. + */ + fun quickAffordanceAlwaysVisible( + position: KeyguardQuickAffordancePosition, + ): Flow<KeyguardQuickAffordanceModel> { + return quickAffordanceInternal(position) + } + + /** * Notifies that a quick affordance has been "triggered" (clicked) by the user. * * @param configKey The configuration key corresponding to the [KeyguardQuickAffordanceModel] of @@ -290,15 +310,6 @@ constructor( } } - private fun KeyguardQuickAffordancePosition.toSlotId(): String { - return when (this) { - KeyguardQuickAffordancePosition.BOTTOM_START -> - KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START - KeyguardQuickAffordancePosition.BOTTOM_END -> - KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END - } - } - private fun String.encode(slotId: String): String { return "$slotId$DELIMITER$this" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt index a18b036c5189..2581b595d812 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt @@ -16,8 +16,17 @@ package com.android.systemui.keyguard.shared.quickaffordance +import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots + /** Enumerates all possible positions for quick affordances that can appear on the lock-screen. */ enum class KeyguardQuickAffordancePosition { BOTTOM_START, - BOTTOM_END, + BOTTOM_END; + + fun toSlotId(): String { + return when (this) { + BOTTOM_START -> KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START + BOTTOM_END -> KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt index cbe512ff83ba..ae8edfece4cb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt @@ -16,14 +16,19 @@ package com.android.systemui.keyguard.ui.binder +import android.annotation.SuppressLint import android.graphics.drawable.Animatable2 import android.util.Size import android.util.TypedValue +import android.view.MotionEvent import android.view.View +import android.view.ViewConfiguration import android.view.ViewGroup import android.view.ViewPropertyAnimator import android.widget.ImageView import android.widget.TextView +import androidx.core.animation.CycleInterpolator +import androidx.core.animation.ObjectAnimator import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.lifecycle.Lifecycle @@ -38,8 +43,10 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.FalsingManager +import kotlin.math.pow +import kotlin.math.sqrt +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map @@ -52,6 +59,7 @@ import kotlinx.coroutines.launch * view-binding, binding each view only once. It is okay and expected for the same instance of the * view-model to be reused for multiple view/view-binder bindings. */ +@OptIn(ExperimentalCoroutinesApi::class) object KeyguardBottomAreaViewBinder { private const val EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS = 250L @@ -84,7 +92,8 @@ object KeyguardBottomAreaViewBinder { fun bind( view: ViewGroup, viewModel: KeyguardBottomAreaViewModel, - falsingManager: FalsingManager, + falsingManager: FalsingManager?, + messageDisplayer: (Int) -> Unit, ): Binding { val indicationArea: View = view.requireViewById(R.id.keyguard_indication_area) val ambientIndicationArea: View? = view.findViewById(R.id.ambient_indication_container) @@ -108,6 +117,7 @@ object KeyguardBottomAreaViewBinder { view = startButton, viewModel = buttonModel, falsingManager = falsingManager, + messageDisplayer = messageDisplayer, ) } } @@ -118,6 +128,7 @@ object KeyguardBottomAreaViewBinder { view = endButton, viewModel = buttonModel, falsingManager = falsingManager, + messageDisplayer = messageDisplayer, ) } } @@ -222,10 +233,12 @@ object KeyguardBottomAreaViewBinder { } } + @SuppressLint("ClickableViewAccessibility") private fun updateButton( view: ImageView, viewModel: KeyguardQuickAffordanceViewModel, - falsingManager: FalsingManager, + falsingManager: FalsingManager?, + messageDisplayer: (Int) -> Unit, ) { if (!viewModel.isVisible) { view.isVisible = false @@ -281,21 +294,126 @@ object KeyguardBottomAreaViewBinder { }, ) ) + view.backgroundTintList = - Utils.getColorAttr( - view.context, - if (viewModel.isActivated) { - com.android.internal.R.attr.colorAccentPrimary - } else { - com.android.internal.R.attr.colorSurface - } - ) + if (!viewModel.isSelected) { + Utils.getColorAttr( + view.context, + if (viewModel.isActivated) { + com.android.internal.R.attr.colorAccentPrimary + } else { + com.android.internal.R.attr.colorSurface + } + ) + } else { + null + } view.isClickable = viewModel.isClickable if (viewModel.isClickable) { - view.setOnClickListener(OnClickListener(viewModel, falsingManager)) + if (viewModel.useLongPress) { + view.setOnTouchListener(OnTouchListener(view, viewModel, messageDisplayer)) + } else { + view.setOnClickListener(OnClickListener(viewModel, checkNotNull(falsingManager))) + } } else { view.setOnClickListener(null) + view.setOnTouchListener(null) + } + + view.isSelected = viewModel.isSelected + } + + private class OnTouchListener( + private val view: View, + private val viewModel: KeyguardQuickAffordanceViewModel, + private val messageDisplayer: (Int) -> Unit, + ) : View.OnTouchListener { + + private val longPressDurationMs = ViewConfiguration.getLongPressTimeout().toLong() + private var longPressAnimator: ViewPropertyAnimator? = null + private var downTimestamp = 0L + + @SuppressLint("ClickableViewAccessibility") + override fun onTouch(v: View?, event: MotionEvent?): Boolean { + return when (event?.actionMasked) { + MotionEvent.ACTION_DOWN -> + if (viewModel.configKey != null) { + downTimestamp = System.currentTimeMillis() + longPressAnimator = + view + .animate() + .scaleX(PRESSED_SCALE) + .scaleY(PRESSED_SCALE) + .setDuration(longPressDurationMs) + .withEndAction { + view.setOnClickListener { + viewModel.onClicked( + KeyguardQuickAffordanceViewModel.OnClickedParameters( + configKey = viewModel.configKey, + expandable = Expandable.fromView(view), + ) + ) + } + view.performClick() + view.setOnClickListener(null) + } + true + } else { + false + } + MotionEvent.ACTION_MOVE -> { + if (event.historySize > 0) { + val distance = + sqrt( + (event.y - event.getHistoricalY(0)).pow(2) + + (event.x - event.getHistoricalX(0)).pow(2) + ) + if (distance > ViewConfiguration.getTouchSlop()) { + cancel() + } + } + true + } + MotionEvent.ACTION_UP -> { + if (System.currentTimeMillis() - downTimestamp < longPressDurationMs) { + messageDisplayer.invoke(R.string.keyguard_affordance_press_too_short) + val shakeAnimator = + ObjectAnimator.ofFloat( + view, + "translationX", + 0f, + view.context.resources + .getDimensionPixelSize( + R.dimen.keyguard_affordance_shake_amplitude + ) + .toFloat(), + 0f, + ) + shakeAnimator.duration = 300 + shakeAnimator.interpolator = CycleInterpolator(5f) + shakeAnimator.start() + } + cancel() + true + } + MotionEvent.ACTION_CANCEL -> { + cancel() + true + } + else -> false + } + } + + private fun cancel() { + downTimestamp = 0L + longPressAnimator?.cancel() + longPressAnimator = null + view.animate().scaleX(1f).scaleY(1f) + } + + companion object { + private const val PRESSED_SCALE = 1.5f } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt new file mode 100644 index 000000000000..a5ae8ba58d45 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt @@ -0,0 +1,207 @@ +/* + * 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.keyguard.ui.preview + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.hardware.display.DisplayManager +import android.os.Bundle +import android.os.IBinder +import android.view.Gravity +import android.view.LayoutInflater +import android.view.SurfaceControlViewHost +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.FrameLayout +import com.android.keyguard.ClockEventController +import com.android.keyguard.KeyguardClockSwitch +import com.android.systemui.R +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel +import com.android.systemui.shared.clocks.ClockRegistry +import com.android.systemui.shared.quickaffordance.shared.model.KeyguardQuickAffordancePreviewConstants +import com.android.systemui.statusbar.phone.KeyguardBottomAreaView +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.DisposableHandle +import kotlinx.coroutines.runBlocking + +/** Renders the preview of the lock screen. */ +class KeyguardPreviewRenderer +@AssistedInject +constructor( + @Application private val context: Context, + @Main private val mainDispatcher: CoroutineDispatcher, + private val bottomAreaViewModel: KeyguardBottomAreaViewModel, + displayManager: DisplayManager, + private val windowManager: WindowManager, + private val clockController: ClockEventController, + private val clockRegistry: ClockRegistry, + private val broadcastDispatcher: BroadcastDispatcher, + @Assisted bundle: Bundle, +) { + + val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN) + private val width: Int = bundle.getInt(KEY_VIEW_WIDTH) + private val height: Int = bundle.getInt(KEY_VIEW_HEIGHT) + + private var host: SurfaceControlViewHost + + val surfacePackage: SurfaceControlViewHost.SurfacePackage + get() = host.surfacePackage + + private var clockView: View? = null + + private val disposables = mutableSetOf<DisposableHandle>() + private var isDestroyed = false + + init { + bottomAreaViewModel.enablePreviewMode( + initiallySelectedSlotId = + bundle.getString( + KeyguardQuickAffordancePreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID, + ), + ) + runBlocking(mainDispatcher) { + host = + SurfaceControlViewHost( + context, + displayManager.getDisplay(bundle.getInt(KEY_DISPLAY_ID)), + hostToken, + ) + disposables.add(DisposableHandle { host.release() }) + } + } + + fun render() { + runBlocking(mainDispatcher) { + val rootView = FrameLayout(context) + + setUpBottomArea(rootView) + setUpClock(rootView) + + rootView.measure( + View.MeasureSpec.makeMeasureSpec( + windowManager.currentWindowMetrics.bounds.width(), + View.MeasureSpec.EXACTLY + ), + View.MeasureSpec.makeMeasureSpec( + windowManager.currentWindowMetrics.bounds.height(), + View.MeasureSpec.EXACTLY + ), + ) + rootView.layout(0, 0, rootView.measuredWidth, rootView.measuredHeight) + + // This aspect scales the view to fit in the surface and centers it + val scale: Float = + (width / rootView.measuredWidth.toFloat()).coerceAtMost( + height / rootView.measuredHeight.toFloat() + ) + + rootView.scaleX = scale + rootView.scaleY = scale + rootView.pivotX = 0f + rootView.pivotY = 0f + rootView.translationX = (width - scale * rootView.width) / 2 + rootView.translationY = (height - scale * rootView.height) / 2 + + host.setView(rootView, rootView.measuredWidth, rootView.measuredHeight) + } + } + + fun onSlotSelected(slotId: String) { + bottomAreaViewModel.onPreviewSlotSelected(slotId = slotId) + } + + fun destroy() { + isDestroyed = true + disposables.forEach { it.dispose() } + } + + private fun setUpBottomArea(parentView: ViewGroup) { + val bottomAreaView = + LayoutInflater.from(context) + .inflate( + R.layout.keyguard_bottom_area, + parentView, + false, + ) as KeyguardBottomAreaView + bottomAreaView.init( + viewModel = bottomAreaViewModel, + ) + parentView.addView( + bottomAreaView, + FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.WRAP_CONTENT, + Gravity.BOTTOM, + ), + ) + } + + private fun setUpClock(parentView: ViewGroup) { + val clockChangeListener = ClockRegistry.ClockChangeListener { onClockChanged(parentView) } + clockRegistry.registerClockChangeListener(clockChangeListener) + disposables.add( + DisposableHandle { clockRegistry.unregisterClockChangeListener(clockChangeListener) } + ) + + clockController.registerListeners(parentView) + disposables.add(DisposableHandle { clockController.unregisterListeners() }) + + val receiver = + object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + clockController.clock?.events?.onTimeTick() + } + } + broadcastDispatcher.registerReceiver( + receiver, + IntentFilter().apply { + addAction(Intent.ACTION_TIME_TICK) + addAction(Intent.ACTION_TIME_CHANGED) + }, + ) + disposables.add(DisposableHandle { broadcastDispatcher.unregisterReceiver(receiver) }) + + onClockChanged(parentView) + } + + private fun onClockChanged(parentView: ViewGroup) { + clockController.clock = clockRegistry.createCurrentClock() + clockController.clock + ?.largeClock + ?.events + ?.onTargetRegionChanged(KeyguardClockSwitch.getLargeClockRegion(parentView)) + clockView?.let { parentView.removeView(it) } + clockView = clockController.clock?.largeClock?.view?.apply { parentView.addView(this) } + } + + companion object { + private const val KEY_HOST_TOKEN = "host_token" + private const val KEY_VIEW_WIDTH = "width" + private const val KEY_VIEW_HEIGHT = "height" + private const val KEY_DISPLAY_ID = "display_id" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRendererFactory.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRendererFactory.kt new file mode 100644 index 000000000000..be1d3a18520a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRendererFactory.kt @@ -0,0 +1,26 @@ +/* + * 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.keyguard.ui.preview + +import android.os.Bundle +import dagger.assisted.AssistedFactory + +@AssistedFactory +interface KeyguardPreviewRendererFactory { + fun create(bundle: Bundle): KeyguardPreviewRenderer +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt new file mode 100644 index 000000000000..50722d5c68f8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt @@ -0,0 +1,138 @@ +/* + * 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.keyguard.ui.preview + +import android.os.Bundle +import android.os.Handler +import android.os.IBinder +import android.os.Message +import android.os.Messenger +import android.util.ArrayMap +import android.util.Log +import androidx.annotation.VisibleForTesting +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.shared.quickaffordance.shared.model.KeyguardQuickAffordancePreviewConstants +import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.runBlocking + +@SysUISingleton +class KeyguardRemotePreviewManager +@Inject +constructor( + private val previewRendererFactory: KeyguardPreviewRendererFactory, + @Main private val mainDispatcher: CoroutineDispatcher, + @Background private val backgroundHandler: Handler, +) { + private val activePreviews: ArrayMap<IBinder, PreviewLifecycleObserver> = + ArrayMap<IBinder, PreviewLifecycleObserver>() + + fun preview(request: Bundle?): Bundle? { + if (request == null) { + return null + } + + var observer: PreviewLifecycleObserver? = null + return try { + val renderer = previewRendererFactory.create(request) + + // Destroy any previous renderer associated with this token. + activePreviews[renderer.hostToken]?.let { destroyObserver(it) } + observer = PreviewLifecycleObserver(renderer, mainDispatcher, ::destroyObserver) + activePreviews[renderer.hostToken] = observer + renderer.render() + renderer.hostToken?.linkToDeath(observer, 0) + val result = Bundle() + result.putParcelable( + KEY_PREVIEW_SURFACE_PACKAGE, + renderer.surfacePackage, + ) + val messenger = + Messenger( + Handler( + backgroundHandler.looper, + observer, + ) + ) + val msg = Message.obtain() + msg.replyTo = messenger + result.putParcelable(KEY_PREVIEW_CALLBACK, msg) + result + } catch (e: Exception) { + Log.e(TAG, "Unable to generate preview", e) + observer?.let { destroyObserver(it) } + null + } + } + + private fun destroyObserver(observer: PreviewLifecycleObserver) { + observer.onDestroy()?.let { hostToken -> + if (activePreviews[hostToken] === observer) { + activePreviews.remove(hostToken) + } + } + } + + private class PreviewLifecycleObserver( + private val renderer: KeyguardPreviewRenderer, + private val mainDispatcher: CoroutineDispatcher, + private val requestDestruction: (PreviewLifecycleObserver) -> Unit, + ) : Handler.Callback, IBinder.DeathRecipient { + + private var isDestroyed = false + + override fun handleMessage(message: Message): Boolean { + when (message.what) { + KeyguardQuickAffordancePreviewConstants.MESSAGE_ID_SLOT_SELECTED -> { + message.data + .getString( + KeyguardQuickAffordancePreviewConstants.KEY_SLOT_ID, + ) + ?.let { slotId -> renderer.onSlotSelected(slotId = slotId) } + } + else -> requestDestruction(this) + } + + return true + } + + override fun binderDied() { + requestDestruction(this) + } + + fun onDestroy(): IBinder? { + if (isDestroyed) { + return null + } + + isDestroyed = true + val hostToken = renderer.hostToken + hostToken?.unlinkToDeath(this, 0) + runBlocking(mainDispatcher) { renderer.destroy() } + return hostToken + } + } + + companion object { + private const val TAG = "KeyguardRemotePreviewManager" + @VisibleForTesting const val KEY_PREVIEW_SURFACE_PACKAGE = "surface_package" + @VisibleForTesting const val KEY_PREVIEW_CALLBACK = "callback" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt index 227796f43e35..5d85680efcf4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt @@ -24,13 +24,19 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceIn import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel import com.android.systemui.keyguard.shared.quickaffordance.ActivationState import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition +import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import javax.inject.Inject +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map /** View-model for the keyguard bottom area view */ +@OptIn(ExperimentalCoroutinesApi::class) class KeyguardBottomAreaViewModel @Inject constructor( @@ -40,6 +46,20 @@ constructor( private val burnInHelperWrapper: BurnInHelperWrapper, ) { /** + * Whether this view-model instance is powering the preview experience that renders exclusively + * in the wallpaper picker application. This should _always_ be `false` for the real lock screen + * experience. + */ + private val isInPreviewMode = MutableStateFlow(false) + + /** + * ID of the slot that's currently selected in the preview that renders exclusively in the + * wallpaper picker application. This is ignored for the actual, real lock screen experience. + */ + private val selectedPreviewSlotId = + MutableStateFlow(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START) + + /** * Whether quick affordances are "opaque enough" to be considered visible to and interactive by * the user. If they are not interactive, user input should not be allowed on them. * @@ -66,7 +86,14 @@ constructor( val isOverlayContainerVisible: Flow<Boolean> = keyguardInteractor.isDozing.map { !it }.distinctUntilChanged() /** An observable for the alpha level for the entire bottom area. */ - val alpha: Flow<Float> = bottomAreaInteractor.alpha.distinctUntilChanged() + val alpha: Flow<Float> = + isInPreviewMode.flatMapLatest { isInPreviewMode -> + if (isInPreviewMode) { + flowOf(1f) + } else { + bottomAreaInteractor.alpha.distinctUntilChanged() + } + } /** An observable for whether the indication area should be padded. */ val isIndicationAreaPadded: Flow<Boolean> = combine(startButton, endButton) { startButtonModel, endButtonModel -> @@ -94,27 +121,61 @@ constructor( * Returns whether the keyguard bottom area should be constrained to the top of the lock icon */ fun shouldConstrainToTopOfLockIcon(): Boolean = - bottomAreaInteractor.shouldConstrainToTopOfLockIcon() + bottomAreaInteractor.shouldConstrainToTopOfLockIcon() + + /** + * Puts this view-model in "preview mode", which means it's being used for UI that is rendering + * the lock screen preview in wallpaper picker / settings and not the real experience on the + * lock screen. + * + * @param initiallySelectedSlotId The ID of the initial slot to render as the selected one. + */ + fun enablePreviewMode(initiallySelectedSlotId: String?) { + isInPreviewMode.value = true + onPreviewSlotSelected( + initiallySelectedSlotId ?: KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START + ) + } + + /** + * Notifies that a slot with the given ID has been selected in the preview experience that is + * rendering in the wallpaper picker. This is ignored for the real lock screen experience. + * + * @see enablePreviewMode + */ + fun onPreviewSlotSelected(slotId: String) { + selectedPreviewSlotId.value = slotId + } private fun button( position: KeyguardQuickAffordancePosition ): Flow<KeyguardQuickAffordanceViewModel> { - return combine( - quickAffordanceInteractor.quickAffordance(position), - bottomAreaInteractor.animateDozingTransitions.distinctUntilChanged(), - areQuickAffordancesFullyOpaque, - ) { model, animateReveal, isFullyOpaque -> - model.toViewModel( - animateReveal = animateReveal, - isClickable = isFullyOpaque, - ) - } - .distinctUntilChanged() + return isInPreviewMode.flatMapLatest { isInPreviewMode -> + combine( + if (isInPreviewMode) { + quickAffordanceInteractor.quickAffordanceAlwaysVisible(position = position) + } else { + quickAffordanceInteractor.quickAffordance(position = position) + }, + bottomAreaInteractor.animateDozingTransitions.distinctUntilChanged(), + areQuickAffordancesFullyOpaque, + selectedPreviewSlotId, + ) { model, animateReveal, isFullyOpaque, selectedPreviewSlotId -> + model.toViewModel( + animateReveal = !isInPreviewMode && animateReveal, + isClickable = isFullyOpaque && !isInPreviewMode, + isSelected = + (isInPreviewMode && selectedPreviewSlotId == position.toSlotId()), + ) + } + .distinctUntilChanged() + } } private fun KeyguardQuickAffordanceModel.toViewModel( animateReveal: Boolean, isClickable: Boolean, + isSelected: Boolean, ): KeyguardQuickAffordanceViewModel { return when (this) { is KeyguardQuickAffordanceModel.Visible -> @@ -131,6 +192,8 @@ constructor( }, isClickable = isClickable, isActivated = activationState is ActivationState.Active, + isSelected = isSelected, + useLongPress = quickAffordanceInteractor.useLongPress, ) is KeyguardQuickAffordanceModel.Hidden -> KeyguardQuickAffordanceViewModel() } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceViewModel.kt index 44f48f97b62e..cf3a6daa40bb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceViewModel.kt @@ -29,6 +29,8 @@ data class KeyguardQuickAffordanceViewModel( val onClicked: (OnClickedParameters) -> Unit = {}, val isClickable: Boolean = false, val isActivated: Boolean = false, + val isSelected: Boolean = false, + val useLongPress: Boolean = false, ) { data class OnClickedParameters( val configKey: String, diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java index 3e5d337bff9d..bb833df1ff69 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java +++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java @@ -30,9 +30,11 @@ import com.android.systemui.media.nearby.NearbyMediaDevicesManager; import com.android.systemui.media.taptotransfer.MediaTttCommandLineHelper; import com.android.systemui.media.taptotransfer.MediaTttFlags; import com.android.systemui.media.taptotransfer.common.MediaTttLogger; +import com.android.systemui.media.taptotransfer.receiver.ChipReceiverInfo; import com.android.systemui.media.taptotransfer.receiver.MediaTttReceiverLogger; import com.android.systemui.media.taptotransfer.sender.MediaTttSenderLogger; import com.android.systemui.plugins.log.LogBuffer; +import com.android.systemui.temporarydisplay.chipbar.ChipbarInfo; import java.util.Optional; @@ -95,19 +97,19 @@ public interface MediaModule { @Provides @SysUISingleton @MediaTttSenderLogger - static MediaTttLogger providesMediaTttSenderLogger( + static MediaTttLogger<ChipbarInfo> providesMediaTttSenderLogger( @MediaTttSenderLogBuffer LogBuffer buffer ) { - return new MediaTttLogger("Sender", buffer); + return new MediaTttLogger<>("Sender", buffer); } @Provides @SysUISingleton @MediaTttReceiverLogger - static MediaTttLogger providesMediaTttReceiverLogger( + static MediaTttLogger<ChipReceiverInfo> providesMediaTttReceiverLogger( @MediaTttReceiverLogBuffer LogBuffer buffer ) { - return new MediaTttLogger("Receiver", buffer); + return new MediaTttLogger<>("Receiver", buffer); } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt index b55bedda2dc1..8aef9385fe3e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt @@ -18,17 +18,21 @@ package com.android.systemui.media.taptotransfer.common import com.android.systemui.plugins.log.LogBuffer import com.android.systemui.plugins.log.LogLevel +import com.android.systemui.temporarydisplay.TemporaryViewInfo import com.android.systemui.temporarydisplay.TemporaryViewLogger /** * A logger for media tap-to-transfer events. * * @param deviceTypeTag the type of device triggering the logs -- "Sender" or "Receiver". + * + * TODO(b/245610654): We should de-couple the sender and receiver loggers, since they're vastly + * different experiences. */ -class MediaTttLogger( +class MediaTttLogger<T : TemporaryViewInfo>( deviceTypeTag: String, buffer: LogBuffer -) : TemporaryViewLogger(buffer, BASE_TAG + deviceTypeTag) { +) : TemporaryViewLogger<T>(buffer, BASE_TAG + deviceTypeTag) { /** Logs a change in the chip state for the given [mediaRouteId]. */ fun logStateChange(stateName: String, mediaRouteId: String, packageName: String?) { buffer.log( diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt index 009595a6da8b..066c1853818f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt @@ -25,6 +25,7 @@ import com.android.systemui.R import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.TintedIcon +import com.android.systemui.temporarydisplay.TemporaryViewInfo /** Utility methods for media tap-to-transfer. */ class MediaTttUtils { @@ -47,7 +48,7 @@ class MediaTttUtils { fun getIconInfoFromPackageName( context: Context, appPackageName: String?, - logger: MediaTttLogger + logger: MediaTttLogger<out TemporaryViewInfo> ): IconInfo { if (appPackageName != null) { val packageManager = context.packageManager diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt index 40ea1e6e87df..11348adb582c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt @@ -35,6 +35,14 @@ enum class ChipStateReceiver( FAR_FROM_SENDER( StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER, MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_FAR_FROM_SENDER + ), + TRANSFER_TO_RECEIVER_SUCCEEDED( + StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, + MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_TRANSFER_TO_RECEIVER_SUCCEEDED, + ), + TRANSFER_TO_RECEIVER_FAILED( + StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_FAILED, + MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_TRANSFER_TO_RECEIVER_FAILED, ); companion object { diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt index 1c3a53cbf815..7b9d0b4205af 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt @@ -45,8 +45,10 @@ import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.temporarydisplay.TemporaryViewDisplayController import com.android.systemui.temporarydisplay.TemporaryViewInfo +import com.android.systemui.temporarydisplay.ViewPriority import com.android.systemui.util.animation.AnimationUtil.Companion.frames import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.time.SystemClock import com.android.systemui.util.view.ViewUtil import com.android.systemui.util.wakelock.WakeLock import javax.inject.Inject @@ -62,7 +64,7 @@ import javax.inject.Inject open class MediaTttChipControllerReceiver @Inject constructor( private val commandQueue: CommandQueue, context: Context, - @MediaTttReceiverLogger logger: MediaTttLogger, + @MediaTttReceiverLogger logger: MediaTttLogger<ChipReceiverInfo>, windowManager: WindowManager, mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, @@ -73,7 +75,8 @@ open class MediaTttChipControllerReceiver @Inject constructor( private val uiEventLogger: MediaTttReceiverUiEventLogger, private val viewUtil: ViewUtil, wakeLockBuilder: WakeLock.Builder, -) : TemporaryViewDisplayController<ChipReceiverInfo, MediaTttLogger>( + systemClock: SystemClock, +) : TemporaryViewDisplayController<ChipReceiverInfo, MediaTttLogger<ChipReceiverInfo>>( context, logger, windowManager, @@ -83,6 +86,7 @@ open class MediaTttChipControllerReceiver @Inject constructor( powerManager, R.layout.media_ttt_chip_receiver, wakeLockBuilder, + systemClock, ) { @SuppressLint("WrongConstant") // We're allowed to use LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS override val windowLayoutParams = commonWindowLayoutParams.apply { @@ -123,8 +127,8 @@ open class MediaTttChipControllerReceiver @Inject constructor( } uiEventLogger.logReceiverStateChange(chipState) - if (chipState == ChipStateReceiver.FAR_FROM_SENDER) { - removeView(routeInfo.id, removalReason = ChipStateReceiver.FAR_FROM_SENDER.name) + if (chipState != ChipStateReceiver.CLOSE_TO_SENDER) { + removeView(routeInfo.id, removalReason = chipState.name) return } if (appIcon == null) { @@ -290,4 +294,5 @@ data class ChipReceiverInfo( override val windowTitle: String = MediaTttUtils.WINDOW_TITLE_RECEIVER, override val wakeReason: String = MediaTttUtils.WAKE_REASON_RECEIVER, override val id: String, + override val priority: ViewPriority = ViewPriority.NORMAL, ) : TemporaryViewInfo() diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLogger.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLogger.kt index 39a276329a9b..6e515f27c25e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLogger.kt @@ -34,7 +34,11 @@ enum class MediaTttReceiverUiEvents(val metricId: Int) : UiEventLogger.UiEventEn @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_RECEIVER_* docs") MEDIA_TTT_RECEIVER_CLOSE_TO_SENDER(982), @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_RECEIVER_* docs") - MEDIA_TTT_RECEIVER_FAR_FROM_SENDER(983); + MEDIA_TTT_RECEIVER_FAR_FROM_SENDER(983), + @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_RECEIVER_* docs") + MEDIA_TTT_RECEIVER_TRANSFER_TO_RECEIVER_SUCCEEDED(1263), + @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_RECEIVER_* docs") + MEDIA_TTT_RECEIVER_TRANSFER_TO_RECEIVER_FAILED(1264); override fun getId() = metricId } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt index ec1984d78cf9..9f44d984124f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt @@ -30,6 +30,7 @@ import com.android.systemui.media.taptotransfer.MediaTttFlags import com.android.systemui.media.taptotransfer.common.MediaTttLogger import com.android.systemui.media.taptotransfer.common.MediaTttUtils import com.android.systemui.statusbar.CommandQueue +import com.android.systemui.temporarydisplay.ViewPriority import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator import com.android.systemui.temporarydisplay.chipbar.ChipbarEndItem import com.android.systemui.temporarydisplay.chipbar.ChipbarInfo @@ -46,7 +47,7 @@ constructor( private val chipbarCoordinator: ChipbarCoordinator, private val commandQueue: CommandQueue, private val context: Context, - @MediaTttSenderLogger private val logger: MediaTttLogger, + @MediaTttSenderLogger private val logger: MediaTttLogger<ChipbarInfo>, private val mediaTttFlags: MediaTttFlags, private val uiEventLogger: MediaTttSenderUiEventLogger, ) : CoreStartable { @@ -146,7 +147,7 @@ constructor( routeInfo: MediaRoute2Info, undoCallback: IUndoMediaTransferCallback?, context: Context, - logger: MediaTttLogger, + logger: MediaTttLogger<ChipbarInfo>, ): ChipbarInfo { val packageName = routeInfo.clientPackageName val otherDeviceName = routeInfo.name.toString() @@ -180,6 +181,7 @@ constructor( wakeReason = MediaTttUtils.WAKE_REASON_SENDER, timeoutMs = chipStateSender.timeout, id = routeInfo.id, + priority = ViewPriority.NORMAL, ) } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index d03ac3b419f6..13c5b48906c5 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -635,8 +635,9 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } private void updateMLModelState() { - boolean newState = mIsEnabled && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL, false); + boolean newState = + mIsGesturalModeEnabled && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, + SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL, false); if (newState == mUseMLModel) { return; @@ -766,7 +767,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack // ML model boolean withinMinRange = x < mMLEnableWidth + mLeftInset || x >= (mDisplaySize.x - mMLEnableWidth - mRightInset); - if (!withinMinRange && mUseMLModel + if (!withinMinRange && mUseMLModel && !mMLModelIsLoading && (results = getBackGesturePredictionsCategory(x, y, app)) != -1) { withinRange = (results == 1); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index f92bbf75d027..8ceee1a950ea 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java @@ -741,6 +741,14 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { } }; + /** + * Force all tiles to be redistributed across pages. + * Should be called when one of the following changes: rows, columns, number of tiles. + */ + public void forceTilesRedistribution() { + mDistributeTiles = true; + } + public interface PageListener { int INVALID_PAGE = -1; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java index 1827eaf3fad1..b2ca6b728113 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -148,6 +148,11 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { } } + @Override + protected void onSplitShadeChanged() { + ((PagedTileLayout) mView.getOrCreateTileLayout()).forceTilesRedistribution(); + } + /** */ public void setVisibility(int visibility) { mView.setVisibility(visibility); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java index dd88c83949fb..60d2c177c7cd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java @@ -96,17 +96,23 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr /* newOrientation= */ newConfig.orientation, /* containerName= */ mView.getDumpableTag()); + boolean previousSplitShadeState = mShouldUseSplitNotificationShade; mShouldUseSplitNotificationShade = LargeScreenUtils.shouldUseSplitNotificationShade(getResources()); mLastOrientation = newConfig.orientation; switchTileLayoutIfNeeded(); onConfigurationChanged(); + if (previousSplitShadeState != mShouldUseSplitNotificationShade) { + onSplitShadeChanged(); + } } }; protected void onConfigurationChanged() { } + protected void onSplitShadeChanged() { } + private final Function1<Boolean, Unit> mMediaHostVisibilityListener = (visible) -> { if (mMediaVisibilityChangedListener != null) { mMediaVisibilityChangedListener.accept(visible); @@ -264,14 +270,6 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr } } } - protected QSTile getTile(String subPanel) { - for (int i = 0; i < mRecords.size(); i++) { - if (subPanel.equals(mRecords.get(i).tile.getTileSpec())) { - return mRecords.get(i).tile; - } - } - return mHost.createTile(subPanel); - } boolean areThereTiles() { return !mRecords.isEmpty(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java index ee3b13091d00..1ed18c3df332 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -363,6 +363,9 @@ public class InternetDialog extends SystemUIDialog implements if (!isChecked && shouldShowMobileDialog()) { showTurnOffMobileDialog(); } else if (!shouldShowMobileDialog()) { + if (mInternetDialogController.isMobileDataEnabled() == isChecked) { + return; + } mInternetDialogController.setMobileDataEnabled(mContext, mDefaultDataSubId, isChecked, false); } diff --git a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt index b511b5463cbf..7fc0a5f6d4bf 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt @@ -101,6 +101,8 @@ class LargeScreenShadeHeaderController @Inject constructor( @VisibleForTesting internal val HEADER_TRANSITION_ID = R.id.header_transition @VisibleForTesting + internal val LARGE_SCREEN_HEADER_TRANSITION_ID = R.id.large_screen_header_transition + @VisibleForTesting internal val QQS_HEADER_CONSTRAINT = R.id.qqs_header_constraint @VisibleForTesting internal val QS_HEADER_CONSTRAINT = R.id.qs_header_constraint @@ -429,8 +431,11 @@ class LargeScreenShadeHeaderController @Inject constructor( } header as MotionLayout if (largeScreenActive) { - header.getConstraintSet(LARGE_SCREEN_HEADER_CONSTRAINT).applyTo(header) + logInstantEvent("Large screen constraints set") + header.setTransition(HEADER_TRANSITION_ID) + header.transitionToStart() } else { + logInstantEvent("Small screen constraints set") header.setTransition(HEADER_TRANSITION_ID) header.transitionToStart() updatePosition() @@ -440,15 +445,19 @@ class LargeScreenShadeHeaderController @Inject constructor( private fun updatePosition() { if (header is MotionLayout && !largeScreenActive && visible) { - Trace.instantForTrack( - TRACE_TAG_APP, - "LargeScreenHeaderController - updatePosition", - "position: $qsExpandedFraction" - ) + logInstantEvent("updatePosition: $qsExpandedFraction") header.progress = qsExpandedFraction } } + private fun logInstantEvent(message: String) { + Trace.instantForTrack( + TRACE_TAG_APP, + "LargeScreenHeaderController", + message + ) + } + private fun updateListeners() { qsCarrierGroupController.setListening(visible) if (visible) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index e33248cc5a2b..6d6427acec4c 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -40,6 +40,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; +import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED; import static com.android.systemui.statusbar.VibratorHelper.TOUCH_VIBRATION_ATTRIBUTES; import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_FOLD_TO_AOD; import static com.android.systemui.util.DumpUtilsKt.asIndenting; @@ -1327,7 +1328,9 @@ public final class NotificationPanelViewController implements Dumpable { mKeyguardBottomArea.init( mKeyguardBottomAreaViewModel, mFalsingManager, - mLockIconViewController + mLockIconViewController, + stringResourceId -> + mKeyguardIndicationController.showTransientIndication(stringResourceId) ); } @@ -2325,7 +2328,7 @@ public final class NotificationPanelViewController implements Dumpable { private boolean handleQsTouch(MotionEvent event) { - if (mSplitShadeEnabled && touchXOutsideOfQs(event.getX())) { + if (isSplitShadeAndTouchXOutsideQs(event.getX())) { return false; } final int action = event.getActionMasked(); @@ -2382,12 +2385,14 @@ public final class NotificationPanelViewController implements Dumpable { return false; } - private boolean touchXOutsideOfQs(float touchX) { - return touchX < mQsFrame.getX() || touchX > mQsFrame.getX() + mQsFrame.getWidth(); + /** Returns whether split shade is enabled and an x coordinate is outside of the QS frame. */ + private boolean isSplitShadeAndTouchXOutsideQs(float touchX) { + return mSplitShadeEnabled && (touchX < mQsFrame.getX() + || touchX > mQsFrame.getX() + mQsFrame.getWidth()); } private boolean isInQsArea(float x, float y) { - if (touchXOutsideOfQs(x)) { + if (isSplitShadeAndTouchXOutsideQs(x)) { return false; } // Let's reject anything at the very bottom around the home handle in gesture nav @@ -4720,6 +4725,7 @@ public final class NotificationPanelViewController implements Dumpable { if (!openingWithTouch || !mHasVibratedOnOpen) { mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK); mHasVibratedOnOpen = true; + mShadeLog.v("Vibrating on opening, mHasVibratedOnOpen=true"); } } } @@ -5316,7 +5322,7 @@ public final class NotificationPanelViewController implements Dumpable { @Override public void flingTopOverscroll(float velocity, boolean open) { // in split shade mode we want to expand/collapse QS only when touch happens within QS - if (mSplitShadeEnabled && touchXOutsideOfQs(mInitialTouchX)) { + if (isSplitShadeAndTouchXOutsideQs(mInitialTouchX)) { return; } mLastOverscroll = 0f; @@ -5477,6 +5483,15 @@ public final class NotificationPanelViewController implements Dumpable { mBarState = statusBarState; mKeyguardShowing = keyguardShowing; + boolean fromShadeToKeyguard = statusBarState == KEYGUARD + && (oldState == SHADE || oldState == SHADE_LOCKED); + if (mSplitShadeEnabled && fromShadeToKeyguard) { + // user can go to keyguard from different shade states and closing animation + // may not fully run - we always want to make sure we close QS when that happens + // as we never need QS open in fresh keyguard state + closeQs(); + } + if (oldState == KEYGUARD && (goingToFullShade || statusBarState == StatusBarState.SHADE_LOCKED)) { @@ -5496,27 +5511,12 @@ public final class NotificationPanelViewController implements Dumpable { mKeyguardStatusBarViewController.animateKeyguardStatusBarIn(); mNotificationStackScrollLayoutController.resetScrollPosition(); - // Only animate header if the header is visible. If not, it will partially - // animate out - // the top of QS - if (!mQsExpanded) { - // TODO(b/185683835) Nicer clipping when using new spacial model - if (mSplitShadeEnabled) { - mQs.animateHeaderSlidingOut(); - } - } } else { // this else branch means we are doing one of: // - from KEYGUARD to SHADE (but not fully expanded as when swiping from the top) // - from SHADE to KEYGUARD // - from SHADE_LOCKED to SHADE // - getting notified again about the current SHADE or KEYGUARD state - if (mSplitShadeEnabled && oldState == SHADE && statusBarState == KEYGUARD) { - // user can go to keyguard from different shade states and closing animation - // may not fully run - we always want to make sure we close QS when that happens - // as we never need QS open in fresh keyguard state - closeQs(); - } final boolean animatingUnlockedShadeToKeyguard = oldState == SHADE && statusBarState == KEYGUARD && mScreenOffAnimationController.isKeyguardShowDelayed(); @@ -6120,6 +6120,7 @@ public final class NotificationPanelViewController implements Dumpable { if (isFullyCollapsed()) { // If panel is fully collapsed, reset haptic effect before adding movement. mHasVibratedOnOpen = false; + mShadeLog.logHasVibrated(mHasVibratedOnOpen, mExpandedFraction); } addMovement(event); if (!isFullyCollapsed()) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt index 0b59af3435ca..5fedbeb556c2 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt @@ -140,6 +140,15 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) { }) } + fun logHasVibrated(hasVibratedOnOpen: Boolean, fraction: Float) { + log(LogLevel.VERBOSE, { + bool1 = hasVibratedOnOpen + double1 = fraction.toDouble() + }, { + "hasVibratedOnOpen=$bool1, expansionFraction=$double1" + }) + } + fun logQsExpansionChanged( message: String, qsExpanded: Boolean, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt index 42edb309d577..c22dbf615190 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt @@ -27,8 +27,10 @@ class LaunchAnimationParameters( /** * The top position of the notification at the start of the animation. This is needed in order * to keep the notification at its place when launching a notification that is clipped rounded. + * This value is in absolute screen coordinates. */ - var startNotificationTop = 0f + var startNotificationTop = 0 + var notificationParentTop = 0 var startClipTopAmount = 0 var parentStartClipTopAmount = 0 var progress = 0f diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt index 39daa13ae168..3072c810d31b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt @@ -33,6 +33,8 @@ class NotifPipelineFlags @Inject constructor( fun fullScreenIntentRequiresKeyguard(): Boolean = featureFlags.isEnabled(Flags.FSI_REQUIRES_KEYGUARD) + fun fsiOnDNDUpdate(): Boolean = featureFlags.isEnabled(Flags.FSI_ON_DND_UPDATE) + val isStabilityIndexFixEnabled: Boolean by lazy { featureFlags.isEnabled(Flags.STABILITY_INDEX_FIX) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt index 0d35fdce953e..798bbe8aff7a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt @@ -92,11 +92,12 @@ class NotificationLaunchAnimatorController( ) params.startTranslationZ = notification.translationZ - params.startNotificationTop = notification.translationY + params.startNotificationTop = location[1] + params.notificationParentTop = notificationListContainer + .getViewParentForNotification(notificationEntry).locationOnScreen[1] params.startRoundedTopClipping = roundedTopClipping params.startClipTopAmount = notification.clipTopAmount if (notification.isChildInGroup) { - params.startNotificationTop += notification.notificationParent.translationY val locationOnScreen = notification.notificationParent.locationOnScreen[1] val parentRoundedClip = (clipStartLocation - locationOnScreen).coerceAtLeast(0) params.parentStartRoundedTopClipping = parentRoundedClip diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt index 3e2dd053d938..aeae89cb3223 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt @@ -244,7 +244,7 @@ class NotificationWakeUpCoordinator @Inject constructor( } override fun onDozeAmountChanged(linear: Float, eased: Float) { - logger.logOnDozeAmountChanged(linear, eased) + logger.logOnDozeAmountChanged(linear = linear, eased = eased) if (overrideDozeAmountIfAnimatingScreenOff(linear)) { return } @@ -263,6 +263,7 @@ class NotificationWakeUpCoordinator @Inject constructor( fun setDozeAmount(linear: Float, eased: Float, source: String) { val changed = linear != mLinearDozeAmount + logger.logSetDozeAmount(linear, eased, source, statusBarStateController.state, changed) mLinearDozeAmount = linear mDozeAmount = eased mDozeAmountSource = source @@ -276,7 +277,7 @@ class NotificationWakeUpCoordinator @Inject constructor( } override fun onStateChanged(newState: Int) { - logger.logOnStateChanged(newState) + logger.logOnStateChanged(newState = newState, storedState = state) if (state == StatusBarState.SHADE && newState == StatusBarState.SHADE) { // The SHADE -> SHADE transition is only possible as part of cancelling the screen-off // animation (e.g. by fingerprint unlock). This is done because the system is in an @@ -324,12 +325,8 @@ class NotificationWakeUpCoordinator @Inject constructor( private fun overrideDozeAmountIfBypass(): Boolean { if (bypassController.bypassEnabled) { if (statusBarStateController.state == StatusBarState.KEYGUARD) { - logger.logSetDozeAmount("1.0", "1.0", - "Override: bypass (keyguard)", StatusBarState.KEYGUARD) setDozeAmount(1f, 1f, source = "Override: bypass (keyguard)") } else { - logger.logSetDozeAmount("0.0", "0.0", - "Override: bypass (shade)", statusBarStateController.state) setDozeAmount(0f, 0f, source = "Override: bypass (shade)") } return true diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt index b40ce25c58d2..de18b0c4307d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt @@ -16,22 +16,33 @@ package com.android.systemui.statusbar.notification import com.android.systemui.log.dagger.NotificationLog import com.android.systemui.plugins.log.LogBuffer import com.android.systemui.plugins.log.LogLevel.DEBUG +import com.android.systemui.statusbar.StatusBarState import javax.inject.Inject class NotificationWakeUpCoordinatorLogger @Inject constructor(@NotificationLog private val buffer: LogBuffer) { - fun logSetDozeAmount(linear: String, eased: String, source: String, state: Int) { + fun logSetDozeAmount( + linear: Float, + eased: Float, + source: String, + state: Int, + changed: Boolean, + ) { buffer.log( TAG, DEBUG, { - str1 = linear - str2 = eased + double1 = linear.toDouble() + str2 = eased.toString() str3 = source int1 = state + bool1 = changed }, - { "setDozeAmount: linear: $str1, eased: $str2, source: $str3, state: $int1" } + { + "setDozeAmount(linear=$double1, eased=$str2, source=$str3)" + + " state=${StatusBarState.toString(int1)} changed=$bool1" + } ) } @@ -43,12 +54,23 @@ constructor(@NotificationLog private val buffer: LogBuffer) { double1 = linear.toDouble() str2 = eased.toString() }, - { "onDozeAmountChanged($double1, $str2)" } + { "onDozeAmountChanged(linear=$double1, eased=$str2)" } ) } - fun logOnStateChanged(newState: Int) { - buffer.log(TAG, DEBUG, { int1 = newState }, { "onStateChanged($int1)" }) + fun logOnStateChanged(newState: Int, storedState: Int) { + buffer.log( + TAG, + DEBUG, + { + int1 = newState + int2 = storedState + }, + { + "onStateChanged(newState=${StatusBarState.toString(int1)})" + + " stored=${StatusBarState.toString(int2)}" + } + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index 5dbb4f9d70df..1004ec195493 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -22,6 +22,7 @@ import android.util.ArraySet import com.android.internal.annotations.VisibleForTesting import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.NotificationRemoteInputManager +import com.android.systemui.statusbar.notification.NotifPipelineFlags import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline @@ -38,6 +39,7 @@ import com.android.systemui.statusbar.notification.collection.render.NodeControl import com.android.systemui.statusbar.notification.dagger.IncomingHeader import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider +import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider.FullScreenIntentDecision import com.android.systemui.statusbar.notification.logKey import com.android.systemui.statusbar.notification.stack.BUCKET_HEADS_UP import com.android.systemui.statusbar.policy.HeadsUpManager @@ -70,11 +72,13 @@ class HeadsUpCoordinator @Inject constructor( private val mNotificationInterruptStateProvider: NotificationInterruptStateProvider, private val mRemoteInputManager: NotificationRemoteInputManager, private val mLaunchFullScreenIntentProvider: LaunchFullScreenIntentProvider, + private val mFlags: NotifPipelineFlags, @IncomingHeader private val mIncomingHeaderController: NodeController, @Main private val mExecutor: DelayableExecutor, ) : Coordinator { private val mEntriesBindingUntil = ArrayMap<String, Long>() private val mEntriesUpdateTimes = ArrayMap<String, Long>() + private val mFSIUpdateCandidates = ArrayMap<String, Long>() private var mEndLifetimeExtension: OnEndLifetimeExtensionCallback? = null private lateinit var mNotifPipeline: NotifPipeline private var mNow: Long = -1 @@ -278,7 +282,7 @@ class HeadsUpCoordinator @Inject constructor( mPostedEntries.clear() // Also take this opportunity to clean up any stale entry update times - cleanUpEntryUpdateTimes() + cleanUpEntryTimes() } /** @@ -384,8 +388,15 @@ class HeadsUpCoordinator @Inject constructor( override fun onEntryAdded(entry: NotificationEntry) { // First check whether this notification should launch a full screen intent, and // launch it if needed. - if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) { + val fsiDecision = mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry) + if (fsiDecision != null && fsiDecision.shouldLaunch) { + mNotificationInterruptStateProvider.logFullScreenIntentDecision(entry, fsiDecision) mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry) + } else if (mFlags.fsiOnDNDUpdate() && + fsiDecision.equals(FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)) { + // If DND was the only reason this entry was suppressed, note it for potential + // reconsideration on later ranking updates. + addForFSIReconsideration(entry, mSystemClock.currentTimeMillis()) } // shouldHeadsUp includes check for whether this notification should be filtered @@ -488,11 +499,32 @@ class HeadsUpCoordinator @Inject constructor( if (!isNewEnoughForRankingUpdate(entry)) continue // The only entries we consider alerting for here are entries that have never - // interrupted and that now say they should heads up; if they've alerted in the - // past, we don't want to incorrectly alert a second time if there wasn't an + // interrupted and that now say they should heads up or FSI; if they've alerted in + // the past, we don't want to incorrectly alert a second time if there wasn't an // explicit notification update. if (entry.hasInterrupted()) continue + // Before potentially allowing heads-up, check for any candidates for a FSI launch. + // Any entry that is a candidate meets two criteria: + // - was suppressed from FSI launch only by a DND suppression + // - is within the recency window for reconsideration + // If any of these entries are no longer suppressed, launch the FSI now. + if (mFlags.fsiOnDNDUpdate() && isCandidateForFSIReconsideration(entry)) { + val decision = + mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry) + if (decision.shouldLaunch) { + // Log both the launch of the full screen and also that this was via a + // ranking update. + mLogger.logEntryUpdatedToFullScreen(entry.key) + mNotificationInterruptStateProvider.logFullScreenIntentDecision( + entry, decision) + mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry) + + // if we launch the FSI then this is no longer a candidate for HUN + continue + } + } + // The cases where we should consider this notification to be updated: // - if this entry is not present in PostedEntries, and is now in a shouldHeadsUp // state @@ -528,6 +560,15 @@ class HeadsUpCoordinator @Inject constructor( } /** + * Add the entry to the list of entries potentially considerable for FSI ranking update, where + * the provided time is the time the entry was added. + */ + @VisibleForTesting + fun addForFSIReconsideration(entry: NotificationEntry, time: Long) { + mFSIUpdateCandidates[entry.key] = time + } + + /** * Checks whether the entry is new enough to be updated via ranking update. * We want to avoid updating an entry too long after it was originally posted/updated when we're * only reacting to a ranking change, as relevant ranking updates are expected to come in @@ -541,17 +582,38 @@ class HeadsUpCoordinator @Inject constructor( return (mSystemClock.currentTimeMillis() - updateTime) <= MAX_RANKING_UPDATE_DELAY_MS } - private fun cleanUpEntryUpdateTimes() { + /** + * Checks whether the entry is present new enough for reconsideration for full screen launch. + * The time window is the same as for ranking update, but this doesn't allow a potential update + * to an entry with full screen intent to count for timing purposes. + */ + private fun isCandidateForFSIReconsideration(entry: NotificationEntry): Boolean { + val addedTime = mFSIUpdateCandidates[entry.key] ?: return false + return (mSystemClock.currentTimeMillis() - addedTime) <= MAX_RANKING_UPDATE_DELAY_MS + } + + private fun cleanUpEntryTimes() { // Because we won't update entries that are older than this amount of time anyway, clean - // up any entries that are too old to notify. + // up any entries that are too old to notify from both the general and FSI specific lists. + + // Anything newer than this time is still within the window. + val timeThreshold = mSystemClock.currentTimeMillis() - MAX_RANKING_UPDATE_DELAY_MS + val toRemove = ArraySet<String>() for ((key, updateTime) in mEntriesUpdateTimes) { - if (updateTime == null || - (mSystemClock.currentTimeMillis() - updateTime) > MAX_RANKING_UPDATE_DELAY_MS) { + if (updateTime == null || timeThreshold > updateTime) { toRemove.add(key) } } mEntriesUpdateTimes.removeAll(toRemove) + + val toRemoveForFSI = ArraySet<String>() + for ((key, addedTime) in mFSIUpdateCandidates) { + if (addedTime == null || timeThreshold > addedTime) { + toRemoveForFSI.add(key) + } + } + mFSIUpdateCandidates.removeAll(toRemoveForFSI) } /** When an action is pressed on a notification, end HeadsUp lifetime extension. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt index 473c35d6095a..2c6bf6b51451 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt @@ -70,6 +70,14 @@ class HeadsUpCoordinatorLogger constructor( }) } + fun logEntryUpdatedToFullScreen(key: String) { + buffer.log(TAG, LogLevel.DEBUG, { + str1 = key + }, { + "updating entry to launch full screen intent: $str1" + }) + } + fun logSummaryMarkedInterrupted(summaryKey: String, childKey: String) { buffer.log(TAG, LogLevel.DEBUG, { str1 = summaryKey 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 c7c1634ea105..a487af1998fc 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 @@ -2223,6 +2223,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView if (mNotificationParent != null) { mNotificationParent.setClipTopAmount(0); } + setTranslationX(0); return; } @@ -2241,6 +2242,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView setTranslationZ(translationZ); float extraWidthForClipping = params.getWidth() - getWidth(); setExtraWidthForClipping(extraWidthForClipping); + int top; if (params.getStartRoundedTopClipping() > 0) { // If we were clipping initially, let's interpolate from the start position to the @@ -2248,20 +2250,22 @@ public class ExpandableNotificationRow extends ActivatableNotificationView float expandProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation( params.getProgress(0, NotificationLaunchAnimatorController.ANIMATION_DURATION_TOP_ROUNDING)); - float startTop = params.getStartNotificationTop(); - top = (int) Math.min(MathUtils.lerp(startTop, - params.getTop(), expandProgress), + int startTop = params.getStartNotificationTop(); + top = (int) Math.min(MathUtils.lerp(startTop, params.getTop(), expandProgress), startTop); } else { top = params.getTop(); } int actualHeight = params.getBottom() - top; setActualHeight(actualHeight); + + int notificationStackTop = params.getNotificationParentTop(); + top -= notificationStackTop; int startClipTopAmount = params.getStartClipTopAmount(); int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, params.getProgress()); if (mNotificationParent != null) { - float parentY = mNotificationParent.getTranslationY(); - top -= parentY; + float parentTranslationY = mNotificationParent.getTranslationY(); + top -= parentTranslationY; mNotificationParent.setTranslationZ(translationZ); // When the expanding notification is below its parent, the parent must be clipped @@ -2270,15 +2274,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView // pixels to show the expanding notification, while still taking the decreasing // notification clipTopAmount into consideration, so 'top + clipTopAmount'. int parentStartClipTopAmount = params.getParentStartClipTopAmount(); - int parentClipTopAmount = Math.min(parentStartClipTopAmount, - top + clipTopAmount); + int parentClipTopAmount = Math.min(parentStartClipTopAmount, top + clipTopAmount); mNotificationParent.setClipTopAmount(parentClipTopAmount); mNotificationParent.setExtraWidthForClipping(extraWidthForClipping); - float clipBottom = Math.max(params.getBottom(), - parentY + mNotificationParent.getActualHeight() + float clipBottom = Math.max(params.getBottom() - notificationStackTop, + parentTranslationY + mNotificationParent.getActualHeight() - mNotificationParent.getClipBottomAmount()); - float clipTop = Math.min(params.getTop(), parentY); + float clipTop = Math.min(params.getTop() - notificationStackTop, parentTranslationY); int minimumHeightForClipping = (int) (clipBottom - clipTop); mNotificationParent.setMinimumHeightForClipping(minimumHeightForClipping); } else if (startClipTopAmount != 0) { @@ -2286,6 +2289,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } setTranslationY(top); + float absoluteCenterX = getLocationOnScreen()[0] + getWidth() / 2f - getTranslationX(); + setTranslationX(params.getCenterX() - absoluteCenterX); + final float maxRadius = getMaxRadius(); mTopRoundnessDuringLaunchAnimation = params.getTopCornerRadius() / maxRadius; mBottomRoundnessDuringLaunchAnimation = params.getBottomCornerRadius() / maxRadius; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 21e2bd877bae..d22bfe8b9e3c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -5772,14 +5772,20 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable || mExpandingNotificationRow == null) { return; } - int left = Math.min(mLaunchAnimationParams.getLeft(), mRoundedRectClippingLeft); - int right = Math.max(mLaunchAnimationParams.getRight(), mRoundedRectClippingRight); - int bottom = Math.max(mLaunchAnimationParams.getBottom(), mRoundedRectClippingBottom); + int[] absoluteCoords = new int[2]; + getLocationOnScreen(absoluteCoords); + + int left = Math.min(mLaunchAnimationParams.getLeft() - absoluteCoords[0], + mRoundedRectClippingLeft); + int right = Math.max(mLaunchAnimationParams.getRight() - absoluteCoords[0], + mRoundedRectClippingRight); + int bottom = Math.max(mLaunchAnimationParams.getBottom() - absoluteCoords[1], + mRoundedRectClippingBottom); float expandProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation( mLaunchAnimationParams.getProgress(0, NotificationLaunchAnimatorController.ANIMATION_DURATION_TOP_ROUNDING)); int top = (int) Math.min(MathUtils.lerp(mRoundedRectClippingTop, - mLaunchAnimationParams.getTop(), expandProgress), + mLaunchAnimationParams.getTop() - absoluteCoords[1], expandProgress), mRoundedRectClippingTop); float topRadius = mLaunchAnimationParams.getTopCornerRadius(); float bottomRadius = mLaunchAnimationParams.getBottomCornerRadius(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index aff7b4c6c515..b6cf9482f00d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -871,8 +871,7 @@ public class StackScrollAlgorithm { } for (int i = childCount - 1; i >= 0; i--) { - childrenOnTop = updateChildZValue(i, childrenOnTop, - algorithmState, ambientState, i == topHunIndex); + updateChildZValue(i, algorithmState, ambientState, i == topHunIndex); } } @@ -882,15 +881,11 @@ public class StackScrollAlgorithm { * * @param isTopHun Whether the child is a top HUN. A top HUN means a HUN that shows on the * vertically top of screen. Top HUNs should have drop shadows - * @param childrenOnTop It is greater than 0 when there's an existing HUN that is elevated - * @return childrenOnTop The decimal part represents the fraction of the elevated HUN's height - * that overlaps with QQS Panel. The integer part represents the count of - * previous HUNs whose Z positions are greater than 0. */ - protected float updateChildZValue(int i, float childrenOnTop, - StackScrollAlgorithmState algorithmState, - AmbientState ambientState, - boolean isTopHun) { + protected void updateChildZValue(int i, + StackScrollAlgorithmState algorithmState, + AmbientState ambientState, + boolean isTopHun) { ExpandableView child = algorithmState.visibleChildren.get(i); ExpandableViewState childViewState = child.getViewState(); float baseZ = ambientState.getBaseZHeight(); @@ -904,22 +899,16 @@ public class StackScrollAlgorithm { // Handles HUN shadow when Shade is opened, and AmbientState.mScrollY > 0 // Calculate the HUN's z-value based on its overlapping fraction with QQS Panel. // When scrolling down shade to make HUN back to in-position in Notification Panel, - // The over-lapping fraction goes to 0, and shadows hides gradually. - if (childrenOnTop != 0.0f) { - // To elevate the later HUN over previous HUN - childrenOnTop++; - } else { - float overlap = ambientState.getTopPadding() - + ambientState.getStackTranslation() - childViewState.getYTranslation(); - // To prevent over-shadow during HUN entry - childrenOnTop += Math.min( - 1.0f, - overlap / childViewState.height - ); - MathUtils.saturate(childrenOnTop); + // the overlapFraction goes to 0, and the pinned HUN's shadows hides gradually. + float overlap = ambientState.getTopPadding() + + ambientState.getStackTranslation() - childViewState.getYTranslation(); + + if (childViewState.height > 0) { // To avoid 0/0 problems + // To prevent over-shadow + float overlapFraction = MathUtils.saturate(overlap / childViewState.height); + childViewState.setZTranslation(baseZ + + overlapFraction * mPinnedZTranslationExtra); } - childViewState.setZTranslation(baseZ - + childrenOnTop * mPinnedZTranslationExtra); } else if (isTopHun) { // In case this is a new view that has never been measured before, we don't want to // elevate if we are currently expanded more than the notification @@ -947,15 +936,14 @@ public class StackScrollAlgorithm { } // Handles HUN shadow when shade is closed. - // While HUN is showing and Shade is closed: headerVisibleAmount stays 0, shadow stays. + // While shade is closed, and during HUN's entry: headerVisibleAmount stays 0, shadow stays. + // While shade is closed, and HUN is showing: headerVisibleAmount stays 0, shadow stays. // During HUN-to-Shade (eg. dragging down HUN to open Shade): headerVisibleAmount goes // gradually from 0 to 1, shadow hides gradually. // Header visibility is a deprecated concept, we are using headerVisibleAmount only because // this value nicely goes from 0 to 1 during the HUN-to-Shade process. - childViewState.setZTranslation(childViewState.getZTranslation() + (1.0f - child.getHeaderVisibleAmount()) * mPinnedZTranslationExtra); - return childrenOnTop; } public void setIsExpanded(boolean isExpanded) { 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 556431114ff1..5e98f5419e84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -161,7 +161,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private KeyguardViewController mKeyguardViewController; private DozeScrimController mDozeScrimController; private KeyguardViewMediator mKeyguardViewMediator; - private ScrimController mScrimController; private PendingAuthenticated mPendingAuthenticated = null; private boolean mHasScreenTurnedOnSinceAuthenticating; private boolean mFadedAwayAfterWakeAndUnlock; @@ -261,7 +260,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp @Inject public BiometricUnlockController( DozeScrimController dozeScrimController, - KeyguardViewMediator keyguardViewMediator, ScrimController scrimController, + KeyguardViewMediator keyguardViewMediator, ShadeController shadeController, NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, Handler handler, @@ -293,7 +292,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mNotificationShadeWindowController = notificationShadeWindowController; mDozeScrimController = dozeScrimController; mKeyguardViewMediator = keyguardViewMediator; - mScrimController = scrimController; mKeyguardStateController = keyguardStateController; mHandler = handler; mConsecutiveFpFailureThreshold = resources.getInteger( @@ -375,12 +373,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp Trace.endSection(); } - private boolean pulsingOrAod() { - final ScrimState scrimState = mScrimController.getState(); - return scrimState == ScrimState.AOD - || scrimState == ScrimState.PULSING; - } - @Override public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType, boolean isStrongBiometric) { @@ -425,7 +417,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive(); mMode = mode; mHasScreenTurnedOnSinceAuthenticating = false; - if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) { + if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) { // If we are waking the device up while we are pulsing the clock and the // notifications would light up first, creating an unpleasant animation. // Defer changing the screen brightness by forcing doze brightness on our window diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java index 72ada0e17a01..2dad8e053ee1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java @@ -371,6 +371,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba if (!mKeyguardStateController.isShowing()) { final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext); + cameraIntent.putExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, source); mCentralSurfaces.startActivityDismissingKeyguard(cameraIntent, false /* onlyProvisioned */, true /* dismissShade */, true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0, 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 31cdb0549d45..005cd1bff90c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone; +import static android.app.StatusBarManager.DISABLE_HOME; import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; import static android.app.StatusBarManager.WindowVisibleState; @@ -70,6 +71,7 @@ import android.graphics.Point; import android.hardware.devicestate.DeviceStateManager; import android.metrics.LogMaker; import android.net.Uri; +import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -1047,8 +1049,21 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { // set the initial view visibility int disabledFlags1 = result.mDisabledFlags1; int disabledFlags2 = result.mDisabledFlags2; - mInitController.addPostInitTask( - () -> setUpDisableFlags(disabledFlags1, disabledFlags2)); + mInitController.addPostInitTask(() -> { + setUpDisableFlags(disabledFlags1, disabledFlags2); + try { + // NOTE(b/262059863): Force-update the disable flags after applying the flags + // returned from registerStatusBar(). The result's disabled flags may be stale + // if StatusBarManager's disabled flags are updated between registering the bar and + // this handling this post-init task. We force an update in this case, and use a new + // token to not conflict with any other disabled flags already requested by SysUI + Binder token = new Binder(); + mBarService.disable(DISABLE_HOME, token, mContext.getPackageName()); + mBarService.disable(0, token, mContext.getPackageName()); + } catch (RemoteException ex) { + ex.rethrowFromSystemServer(); + } + }); mFalsingManager.addFalsingBeliefListener(mFalsingBeliefListener); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt index 78b28d203629..2ce116394236 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt @@ -23,7 +23,7 @@ import android.view.ViewGroup import android.view.ViewPropertyAnimator import android.view.WindowInsets import android.widget.FrameLayout -import com.android.keyguard.KeyguardUpdateMonitor +import androidx.annotation.StringRes import com.android.keyguard.LockIconViewController import com.android.systemui.R import com.android.systemui.keyguard.ui.binder.KeyguardBottomAreaViewBinder @@ -51,21 +51,29 @@ constructor( defStyleRes, ) { + interface MessageDisplayer { + fun display(@StringRes stringResourceId: Int) + } + private var ambientIndicationArea: View? = null private lateinit var binding: KeyguardBottomAreaViewBinder.Binding - private lateinit var lockIconViewController: LockIconViewController + private var lockIconViewController: LockIconViewController? = null /** Initializes the view. */ fun init( viewModel: KeyguardBottomAreaViewModel, - falsingManager: FalsingManager, - lockIconViewController: LockIconViewController, + falsingManager: FalsingManager? = null, + lockIconViewController: LockIconViewController? = null, + messageDisplayer: MessageDisplayer? = null, ) { - binding = bind( + binding = + bind( this, viewModel, falsingManager, - ) + ) { + messageDisplayer?.display(it) + } this.lockIconViewController = lockIconViewController } @@ -129,21 +137,21 @@ constructor( findViewById<View>(R.id.ambient_indication_container)?.let { val (ambientLeft, ambientTop) = it.locationOnScreen if (binding.shouldConstrainToTopOfLockIcon()) { - //make top of ambient indication view the bottom of the lock icon + // make top of ambient indication view the bottom of the lock icon it.layout( - ambientLeft, - lockIconViewController.bottom.toInt(), - right - ambientLeft, - ambientTop + it.measuredHeight + ambientLeft, + lockIconViewController?.bottom?.toInt() ?: 0, + right - ambientLeft, + ambientTop + it.measuredHeight ) } else { - //make bottom of ambient indication view the top of the lock icon - val lockLocationTop = lockIconViewController.top + // make bottom of ambient indication view the top of the lock icon + val lockLocationTop = lockIconViewController?.top ?: 0 it.layout( - ambientLeft, - lockLocationTop.toInt() - it.measuredHeight, - right - ambientLeft, - lockLocationTop.toInt() + ambientLeft, + lockLocationTop.toInt() - it.measuredHeight, + right - ambientLeft, + lockLocationTop.toInt() ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt index f5b5950d33a8..cc67c84772a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt @@ -46,6 +46,7 @@ import kotlinx.coroutines.launch * view-model to be reused for multiple view/view-binder bindings. */ @OptIn(InternalCoroutinesApi::class) +@Suppress("EXPERIMENTAL_IS_NOT_ENABLED") object WifiViewBinder { /** @@ -59,6 +60,12 @@ object WifiViewBinder { /** Notifies that the visibility state has changed. */ fun onVisibilityStateChanged(@StatusBarIconView.VisibleState state: Int) + + /** Notifies that the icon tint has been updated. */ + fun onIconTintChanged(newTint: Int) + + /** Notifies that the decor tint has been updated (used only for the dot). */ + fun onDecorTintChanged(newTint: Int) } /** Binds the view to the view-model, continuing to update the former based on the latter. */ @@ -82,6 +89,9 @@ object WifiViewBinder { @StatusBarIconView.VisibleState val visibilityState: MutableStateFlow<Int> = MutableStateFlow(STATE_HIDDEN) + val iconTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor) + val decorTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor) + view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { launch { @@ -101,7 +111,7 @@ object WifiViewBinder { } launch { - viewModel.tint.collect { tint -> + iconTint.collect { tint -> val tintList = ColorStateList.valueOf(tint) iconView.imageTintList = tintList activityInView.imageTintList = tintList @@ -110,6 +120,8 @@ object WifiViewBinder { } } + launch { decorTint.collect { tint -> dotView.setDecorColor(tint) } } + launch { viewModel.isActivityInViewVisible.distinctUntilChanged().collect { visible -> activityInView.isVisible = visible @@ -144,6 +156,20 @@ object WifiViewBinder { override fun onVisibilityStateChanged(@StatusBarIconView.VisibleState state: Int) { visibilityState.value = state } + + override fun onIconTintChanged(newTint: Int) { + if (viewModel.useDebugColoring) { + return + } + iconTint.value = newTint + } + + override fun onDecorTintChanged(newTint: Int) { + if (viewModel.useDebugColoring) { + return + } + decorTint.value = newTint + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt index a45076b53356..be7782c37cfd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt @@ -22,6 +22,7 @@ import android.util.AttributeSet import android.view.Gravity import android.view.LayoutInflater import com.android.systemui.R +import com.android.systemui.plugins.DarkIconDispatcher import com.android.systemui.statusbar.BaseStatusBarFrameLayout import com.android.systemui.statusbar.StatusBarIconView import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT @@ -51,18 +52,20 @@ class ModernStatusBarWifiView( binding.onVisibilityStateChanged(value) } + override fun getSlot() = slot + override fun onDarkChanged(areas: ArrayList<Rect>?, darkIntensity: Float, tint: Int) { - // TODO(b/238425913) + val newTint = DarkIconDispatcher.getTint(areas, this, tint) + binding.onIconTintChanged(newTint) + binding.onDecorTintChanged(newTint) } - override fun getSlot() = slot - override fun setStaticDrawableColor(color: Int) { - // TODO(b/238425913) + binding.onIconTintChanged(color) } override fun setDecorColor(color: Int) { - // TODO(b/238425913) + binding.onDecorTintChanged(color) } override fun setVisibleState(@StatusBarIconView.VisibleState state: Int, animate: Boolean) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt index e35a8fef4528..a4615cc897cf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt @@ -21,7 +21,6 @@ import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.flowOf /** * A view model for a wifi icon in a specific location. This allows us to control parameters that @@ -48,24 +47,12 @@ abstract class LocationBasedWifiViewModel( /** True if the airplane spacer view should be visible. */ val isAirplaneSpacerVisible: Flow<Boolean>, ) { - /** The color that should be used to tint the icon. */ - val tint: Flow<Int> = - flowOf( - if (statusBarPipelineFlags.useWifiDebugColoring()) { - debugTint - } else { - DEFAULT_TINT - } - ) - - companion object { - /** - * A default icon tint. - * - * TODO(b/238425913): The tint is actually controlled by - * [com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager]. We - * should use that logic instead of white as a default. - */ - private const val DEFAULT_TINT = Color.WHITE - } + val useDebugColoring: Boolean = statusBarPipelineFlags.useWifiDebugColoring() + + val defaultColor: Int = + if (useDebugColoring) { + debugTint + } else { + Color.WHITE + } } diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt index ea4020861a09..db7315f311ac 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt @@ -34,6 +34,7 @@ import com.android.systemui.CoreStartable import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.time.SystemClock import com.android.systemui.util.wakelock.WakeLock /** @@ -44,8 +45,24 @@ import com.android.systemui.util.wakelock.WakeLock * * The generic type T is expected to contain all the information necessary for the subclasses to * display the view in a certain state, since they receive <T> in [updateView]. + * + * Some information about display ordering: + * + * [ViewPriority] defines different priorities for the incoming views. The incoming view will be + * displayed so long as its priority is equal to or greater than the currently displayed view. + * (Concretely, this means that a [ViewPriority.NORMAL] won't be displayed if a + * [ViewPriority.CRITICAL] is currently displayed. But otherwise, the incoming view will get + * displayed and kick out the old view). + * + * Once the currently displayed view times out, we *may* display a previously requested view if it + * still has enough time left before its own timeout. The same priority ordering applies. + * + * Note: [TemporaryViewInfo.id] is the identifier that we use to determine if a call to + * [displayView] will just update the current view with new information, or display a completely new + * view. This means that you *cannot* change the [TemporaryViewInfo.priority] or + * [TemporaryViewInfo.windowTitle] while using the same ID. */ -abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : TemporaryViewLogger>( +abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : TemporaryViewLogger<T>>( internal val context: Context, internal val logger: U, internal val windowManager: WindowManager, @@ -55,6 +72,7 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora private val powerManager: PowerManager, @LayoutRes private val viewLayoutRes: Int, private val wakeLockBuilder: WakeLock.Builder, + private val systemClock: SystemClock, ) : CoreStartable { /** * Window layout params that will be used as a starting point for the [windowLayoutParams] of @@ -78,27 +96,18 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora */ internal abstract val windowLayoutParams: WindowManager.LayoutParams - /** A container for all the display-related objects. Null if the view is not being displayed. */ - private var displayInfo: DisplayInfo? = null - - /** A [Runnable] that, when run, will cancel the pending timeout of the view. */ - private var cancelViewTimeout: Runnable? = null - /** - * A wakelock that is acquired when view is displayed and screen off, - * then released when view is removed. + * A list of the currently active views, ordered from highest priority in the beginning to + * lowest priority at the end. + * + * Whenever the current view disappears, the next-priority view will be displayed if it's still + * valid. */ - private var wakeLock: WakeLock? = null - - /** A string that keeps track of wakelock reason once it is acquired till it gets released */ - private var wakeReasonAcquired: String? = null + internal val activeViews: MutableList<DisplayInfo> = mutableListOf() - /** - * A stack of pairs of device id and temporary view info. This is used when there may be - * multiple devices in range, and we want to always display the chip for the most recently - * active device. - */ - internal val activeViews: ArrayDeque<Pair<String, T>> = ArrayDeque() + private fun getCurrentDisplayInfo(): DisplayInfo? { + return activeViews.getOrNull(0) + } /** * Displays the view with the provided [newInfo]. @@ -107,94 +116,139 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora * display the correct information in the view. * @param onViewTimeout a runnable that runs after the view timeout. */ + @Synchronized fun displayView(newInfo: T, onViewTimeout: Runnable? = null) { - val currentDisplayInfo = displayInfo - - // Update our list of active devices by removing it if necessary, then adding back at the - // front of the list - val id = newInfo.id - val position = findAndRemoveFromActiveViewsList(id) - activeViews.addFirst(Pair(id, newInfo)) - - if (currentDisplayInfo != null && - currentDisplayInfo.info.windowTitle == newInfo.windowTitle) { - // We're already displaying information in the correctly-titled window, so we just need - // to update the view. - currentDisplayInfo.info = newInfo - updateView(currentDisplayInfo.info, currentDisplayInfo.view) - } else { - if (currentDisplayInfo != null) { - // We're already displaying information but that information is under a different - // window title. So, we need to remove the old window with the old title and add a - // new window with the new title. - removeView( - id, - removalReason = "New info has new window title: ${newInfo.windowTitle}" - ) - } - - // At this point, we're guaranteed to no longer be displaying a view. - // So, set up all our callbacks and inflate the view. - configurationController.addCallback(displayScaleListener) - - wakeLock = if (!powerManager.isScreenOn) { - // If the screen is off, fully wake it so the user can see the view. - wakeLockBuilder - .setTag(newInfo.windowTitle) - .setLevelsAndFlags( - PowerManager.FULL_WAKE_LOCK or - PowerManager.ACQUIRE_CAUSES_WAKEUP - ) - .build() - } else { - // Per b/239426653, we want the view to show over the dream state. - // If the screen is on, using screen bright level will leave screen on the dream - // state but ensure the screen will not go off before wake lock is released. - wakeLockBuilder - .setTag(newInfo.windowTitle) - .setLevelsAndFlags(PowerManager.SCREEN_BRIGHT_WAKE_LOCK) - .build() - } - wakeLock?.acquire(newInfo.wakeReason) - wakeReasonAcquired = newInfo.wakeReason - logger.logViewAddition(id, newInfo.windowTitle) - inflateAndUpdateView(newInfo) - } - - // Cancel and re-set the view timeout each time we get a new state. val timeout = accessibilityManager.getRecommendedTimeoutMillis( newInfo.timeoutMs, // Not all views have controls so FLAG_CONTENT_CONTROLS might be superfluous, but // include it just to be safe. FLAG_CONTENT_ICONS or FLAG_CONTENT_TEXT or FLAG_CONTENT_CONTROLS - ) + ) + val timeExpirationMillis = systemClock.currentTimeMillis() + timeout + + val currentDisplayInfo = getCurrentDisplayInfo() + + // We're current displaying a chipbar with the same ID, we just need to update its info + if (currentDisplayInfo != null && currentDisplayInfo.info.id == newInfo.id) { + val view = checkNotNull(currentDisplayInfo.view) { + "First item in activeViews list must have a valid view" + } + logger.logViewUpdate(newInfo) + currentDisplayInfo.info = newInfo + currentDisplayInfo.timeExpirationMillis = timeExpirationMillis + updateTimeout(currentDisplayInfo, timeout, onViewTimeout) + updateView(newInfo, view) + return + } + + val newDisplayInfo = DisplayInfo( + info = newInfo, + onViewTimeout = onViewTimeout, + timeExpirationMillis = timeExpirationMillis, + // Null values will be updated to non-null if/when this view actually gets displayed + view = null, + wakeLock = null, + cancelViewTimeout = null, + ) + + // We're not displaying anything, so just render this new info + if (currentDisplayInfo == null) { + addCallbacks() + activeViews.add(newDisplayInfo) + showNewView(newDisplayInfo, timeout) + return + } + + // The currently displayed info takes higher priority than the new one. + // So, just store the new one in case the current one disappears. + if (currentDisplayInfo.info.priority > newInfo.priority) { + logger.logViewAdditionDelayed(newInfo) + // Remove any old information for this id (if it exists) and re-add it to the list in + // the right priority spot + removeFromActivesIfNeeded(newInfo.id) + var insertIndex = 0 + while (insertIndex < activeViews.size && + activeViews[insertIndex].info.priority > newInfo.priority) { + insertIndex++ + } + activeViews.add(insertIndex, newDisplayInfo) + return + } + + // Else: The newInfo should be displayed and the currentInfo should be hidden + hideView(currentDisplayInfo) + // Remove any old information for this id (if it exists) and put this info at the beginning + removeFromActivesIfNeeded(newDisplayInfo.info.id) + activeViews.add(0, newDisplayInfo) + showNewView(newDisplayInfo, timeout) + } + + private fun showNewView(newDisplayInfo: DisplayInfo, timeout: Int) { + logger.logViewAddition(newDisplayInfo.info) + createAndAcquireWakeLock(newDisplayInfo) + updateTimeout(newDisplayInfo, timeout, newDisplayInfo.onViewTimeout) + inflateAndUpdateView(newDisplayInfo) + } - // Only cancel timeout of the most recent view displayed, as it will be reset. - if (position == 0) { - cancelViewTimeout?.run() + private fun createAndAcquireWakeLock(displayInfo: DisplayInfo) { + // TODO(b/262009503): Migrate off of isScrenOn, since it's deprecated. + val newWakeLock = if (!powerManager.isScreenOn) { + // If the screen is off, fully wake it so the user can see the view. + wakeLockBuilder + .setTag(displayInfo.info.windowTitle) + .setLevelsAndFlags( + PowerManager.FULL_WAKE_LOCK or + PowerManager.ACQUIRE_CAUSES_WAKEUP + ) + .build() + } else { + // Per b/239426653, we want the view to show over the dream state. + // If the screen is on, using screen bright level will leave screen on the dream + // state but ensure the screen will not go off before wake lock is released. + wakeLockBuilder + .setTag(displayInfo.info.windowTitle) + .setLevelsAndFlags(PowerManager.SCREEN_BRIGHT_WAKE_LOCK) + .build() } - cancelViewTimeout = mainExecutor.executeDelayed( + displayInfo.wakeLock = newWakeLock + newWakeLock.acquire(displayInfo.info.wakeReason) + } + + /** + * Creates a runnable that will remove [displayInfo] in [timeout] ms from now. + * + * @param onViewTimeout an optional runnable that will be run if the view times out. + * @return a runnable that, when run, will *cancel* the view's timeout. + */ + private fun updateTimeout(displayInfo: DisplayInfo, timeout: Int, onViewTimeout: Runnable?) { + val cancelViewTimeout = mainExecutor.executeDelayed( { - removeView(id, REMOVAL_REASON_TIMEOUT) + removeView(displayInfo.info.id, REMOVAL_REASON_TIMEOUT) onViewTimeout?.run() }, timeout.toLong() ) + + displayInfo.onViewTimeout = onViewTimeout + // Cancel old view timeout and re-set it. + displayInfo.cancelViewTimeout?.run() + displayInfo.cancelViewTimeout = cancelViewTimeout } - /** Inflates a new view, updates it with [newInfo], and adds the view to the window. */ - private fun inflateAndUpdateView(newInfo: T) { + /** Inflates a new view, updates it with [DisplayInfo.info], and adds the view to the window. */ + private fun inflateAndUpdateView(displayInfo: DisplayInfo) { + val newInfo = displayInfo.info val newView = LayoutInflater .from(context) .inflate(viewLayoutRes, null) as ViewGroup - val newViewController = TouchableRegionViewController(newView, this::getTouchableRegion) - newViewController.init() + displayInfo.view = newView // We don't need to hold on to the view controller since we never set anything additional // on it -- it will be automatically cleaned up when the view is detached. - val newDisplayInfo = DisplayInfo(newView, newInfo) - displayInfo = newDisplayInfo - updateView(newDisplayInfo.info, newDisplayInfo.view) + val newViewController = TouchableRegionViewController(newView, this::getTouchableRegion) + newViewController.init() + + updateView(newInfo, newView) val paramsWithTitle = WindowManager.LayoutParams().also { it.copyFrom(windowLayoutParams) @@ -206,11 +260,15 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora } /** Removes then re-inflates the view. */ + @Synchronized private fun reinflateView() { - val currentViewInfo = displayInfo ?: return + val currentDisplayInfo = getCurrentDisplayInfo() ?: return - windowManager.removeView(currentViewInfo.view) - inflateAndUpdateView(currentViewInfo.info) + val view = checkNotNull(currentDisplayInfo.view) { + "First item in activeViews list must have a valid view" + } + windowManager.removeView(view) + inflateAndUpdateView(currentDisplayInfo) } private val displayScaleListener = object : ConfigurationController.ConfigurationListener { @@ -219,68 +277,109 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora } } + private fun addCallbacks() { + configurationController.addCallback(displayScaleListener) + } + + private fun removeCallbacks() { + configurationController.removeCallback(displayScaleListener) + } + /** - * Hides the view given its [id]. + * Completely removes the view for the given [id], both visually and from our internal store. * * @param id the id of the device responsible of displaying the temp view. * @param removalReason a short string describing why the view was removed (timeout, state * change, etc.) */ + @Synchronized fun removeView(id: String, removalReason: String) { - val currentDisplayInfo = displayInfo ?: return + logger.logViewRemoval(id, removalReason) - val removalPosition = findAndRemoveFromActiveViewsList(id) - if (removalPosition == null) { - logger.logViewRemovalIgnored(id, "view not found in the list") + val displayInfo = activeViews.firstOrNull { it.info.id == id } + if (displayInfo == null) { + logger.logViewRemovalIgnored(id, "View not found in list") return } - if (removalPosition != 0) { - logger.logViewRemovalIgnored(id, "most recent view is being displayed.") + + val currentlyDisplayedView = activeViews[0] + // Remove immediately (instead as part of the animation end runnable) so that if a new view + // event comes in while this view is animating out, we still display the new view + // appropriately. + activeViews.remove(displayInfo) + + // No need to time the view out since it's already gone + displayInfo.cancelViewTimeout?.run() + + if (displayInfo.view == null) { + logger.logViewRemovalIgnored(id, "No view to remove") return } - logger.logViewRemoval(id, removalReason) - val newViewToDisplay = if (activeViews.isEmpty()) { - null - } else { - activeViews[0].second + if (currentlyDisplayedView.info.id != id) { + logger.logViewRemovalIgnored(id, "View isn't the currently displayed view") + return } - val currentView = currentDisplayInfo.view - animateViewOut(currentView) { - windowManager.removeView(currentView) - wakeLock?.release(wakeReasonAcquired) - } + removeViewFromWindow(displayInfo) - configurationController.removeCallback(displayScaleListener) - // Re-set to null immediately (instead as part of the animation end runnable) so - // that if a new view event comes in while this view is animating out, we still display - // the new view appropriately. - displayInfo = null - // No need to time the view out since it's already gone - cancelViewTimeout?.run() + // Prune anything that's already timed out before determining if we should re-display a + // different chipbar. + removeTimedOutViews() + val newViewToDisplay = getCurrentDisplayInfo() if (newViewToDisplay != null) { - mainExecutor.executeDelayed({ displayView(newViewToDisplay)}, DISPLAY_VIEW_DELAY) + val timeout = newViewToDisplay.timeExpirationMillis - systemClock.currentTimeMillis() + // TODO(b/258019006): We may want to have a delay before showing the new view so + // that the UI translation looks a bit smoother. But, we expect this to happen + // rarely so it may not be worth the extra complexity. + showNewView(newViewToDisplay, timeout.toInt()) + } else { + removeCallbacks() } } /** - * Finds and removes the active view with the given [id] from the stack, or null if there is no - * active view with that ID - * - * @param id that temporary view belonged to. - * - * @return index of the view in the stack , otherwise null. + * Hides the view from the window, but keeps [displayInfo] around in [activeViews] in case it + * should be re-displayed later. */ - private fun findAndRemoveFromActiveViewsList(id: String): Int? { - for (i in 0 until activeViews.size) { - if (activeViews[i].first == id) { - activeViews.removeAt(i) - return i - } + private fun hideView(displayInfo: DisplayInfo) { + logger.logViewHidden(displayInfo.info) + removeViewFromWindow(displayInfo) + } + + private fun removeViewFromWindow(displayInfo: DisplayInfo) { + val view = displayInfo.view + if (view == null) { + logger.logViewRemovalIgnored(displayInfo.info.id, "View is null") + return + } + displayInfo.view = null // Need other places?? + animateViewOut(view) { + windowManager.removeView(view) + displayInfo.wakeLock?.release(displayInfo.info.wakeReason) + } + } + + @Synchronized + private fun removeTimedOutViews() { + val invalidViews = activeViews + .filter { it.timeExpirationMillis < + systemClock.currentTimeMillis() + MIN_REQUIRED_TIME_FOR_REDISPLAY } + + invalidViews.forEach { + activeViews.remove(it) + logger.logViewExpiration(it.info) + } + } + + @Synchronized + private fun removeFromActivesIfNeeded(id: String) { + val toRemove = activeViews.find { it.info.id == id } + toRemove?.let { + it.cancelViewTimeout?.run() + activeViews.remove(it) } - return null } /** @@ -311,17 +410,47 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora } /** A container for all the display-related state objects. */ - private inner class DisplayInfo( - /** The view currently being displayed. */ - val view: ViewGroup, - - /** The info currently being displayed. */ + inner class DisplayInfo( + /** + * The view currently being displayed. + * + * Null if this info isn't currently being displayed. + */ + var view: ViewGroup?, + + /** The info that should be displayed if/when this is the highest priority view. */ var info: T, + + /** + * The system time at which this display info should expire and never be displayed again. + */ + var timeExpirationMillis: Long, + + /** + * The wake lock currently held by this view. Must be released when the view disappears. + * + * Null if this info isn't currently being displayed. + */ + var wakeLock: WakeLock?, + + /** + * See [displayView]. + */ + var onViewTimeout: Runnable?, + + /** + * A runnable that, when run, will cancel this view's timeout. + * + * Null if this info isn't currently being displayed. + */ + var cancelViewTimeout: Runnable?, ) + + // TODO(b/258019006): Add a dump method that dumps the currently active views. } private const val REMOVAL_REASON_TIMEOUT = "TIMEOUT" -const val DISPLAY_VIEW_DELAY = 50L +private const val MIN_REQUIRED_TIME_FOR_REDISPLAY = 1000 private data class IconInfo( val iconName: String, diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt index df8396051dda..5596cf68b4bc 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt @@ -42,6 +42,20 @@ abstract class TemporaryViewInfo { * The id of the temporary view. */ abstract val id: String + + /** The priority for this view. */ + abstract val priority: ViewPriority } const val DEFAULT_TIMEOUT_MILLIS = 10000 + +/** + * The priority of the view being displayed. + * + * Must be ordered from lowest priority to highest priority. (CRITICAL is currently the highest + * priority.) + */ +enum class ViewPriority { + NORMAL, + CRITICAL, +} diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt index 133a384e7e17..ec6965a83b5a 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt @@ -20,20 +20,79 @@ import com.android.systemui.plugins.log.LogBuffer import com.android.systemui.plugins.log.LogLevel /** A logger for temporary view changes -- see [TemporaryViewDisplayController]. */ -open class TemporaryViewLogger( +open class TemporaryViewLogger<T : TemporaryViewInfo>( internal val buffer: LogBuffer, internal val tag: String, ) { - /** Logs that we added the view with the given [id] in a window titled [windowTitle]. */ - fun logViewAddition(id: String, windowTitle: String) { + fun logViewExpiration(info: T) { buffer.log( tag, LogLevel.DEBUG, { - str1 = windowTitle - str2 = id + str1 = info.id + str2 = info.windowTitle + str3 = info.priority.name + }, + { "View timeout has already expired; removing. id=$str1 window=$str2 priority=$str3" } + ) + } + + fun logViewUpdate(info: T) { + buffer.log( + tag, + LogLevel.DEBUG, + { + str1 = info.id + str2 = info.windowTitle + str3 = info.priority.name }, - { "View added. window=$str1 id=$str2" } + { "Existing view updated with new data. id=$str1 window=$str2 priority=$str3" } + ) + } + + fun logViewAdditionDelayed(info: T) { + buffer.log( + tag, + LogLevel.DEBUG, + { + str1 = info.id + str2 = info.windowTitle + str3 = info.priority.name + }, + { + "New view can't be displayed because higher priority view is currently " + + "displayed. New view id=$str1 window=$str2 priority=$str3" + } + ) + } + + /** Logs that we added the view with the given information. */ + fun logViewAddition(info: T) { + buffer.log( + tag, + LogLevel.DEBUG, + { + str1 = info.id + str2 = info.windowTitle + str3 = info.priority.name + }, + { "View added. id=$str1 window=$str2 priority=$str3" } + ) + } + + fun logViewHidden(info: T) { + buffer.log( + tag, + LogLevel.DEBUG, + { + str1 = info.id + str2 = info.windowTitle + str3 = info.priority.name + }, + { + "View hidden in favor of newer view. " + + "Hidden view id=$str1 window=$str2 priority=$str3" + } ) } diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt index 4d91e35856dc..14ba63a2738f 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt @@ -43,6 +43,7 @@ import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.temporarydisplay.TemporaryViewDisplayController import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.time.SystemClock import com.android.systemui.util.view.ViewUtil import com.android.systemui.util.wakelock.WakeLock import javax.inject.Inject @@ -77,6 +78,7 @@ open class ChipbarCoordinator @Inject constructor( private val viewUtil: ViewUtil, private val vibratorHelper: VibratorHelper, wakeLockBuilder: WakeLock.Builder, + systemClock: SystemClock, ) : TemporaryViewDisplayController<ChipbarInfo, ChipbarLogger>( context, logger, @@ -87,6 +89,7 @@ open class ChipbarCoordinator @Inject constructor( powerManager, R.layout.chipbar, wakeLockBuilder, + systemClock, ) { private lateinit var parent: ChipbarRootView diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt index a3eef8032b3b..dd4bd26e3bcd 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt @@ -22,6 +22,7 @@ import androidx.annotation.AttrRes import com.android.systemui.common.shared.model.Text import com.android.systemui.common.shared.model.TintedIcon import com.android.systemui.temporarydisplay.TemporaryViewInfo +import com.android.systemui.temporarydisplay.ViewPriority /** * A container for all the state needed to display a chipbar via [ChipbarCoordinator]. @@ -42,6 +43,7 @@ data class ChipbarInfo( override val wakeReason: String, override val timeoutMs: Int, override val id: String, + override val priority: ViewPriority, ) : TemporaryViewInfo() { companion object { @AttrRes const val DEFAULT_ICON_TINT_ATTR = android.R.attr.textColorPrimary diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt index e477cd68673a..fcfbe0aeedf6 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt @@ -29,7 +29,7 @@ class ChipbarLogger @Inject constructor( @ChipbarLog buffer: LogBuffer, -) : TemporaryViewLogger(buffer, "ChipbarLog") { +) : TemporaryViewLogger<ChipbarInfo>(buffer, "ChipbarLog") { /** * Logs that the chipbar was updated to display in a window named [windowTitle], with [text] and * [endItemDesc]. diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java index 8bbaf3dff1e5..10595439200a 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java @@ -19,6 +19,7 @@ package com.android.keyguard; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; @@ -87,6 +88,7 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase { when(mAbsKeyInputView.isAttachedToWindow()).thenReturn(true); when(mAbsKeyInputView.requireViewById(R.id.bouncer_message_area)) .thenReturn(mKeyguardMessageArea); + when(mAbsKeyInputView.getResources()).thenReturn(getContext().getResources()); mKeyguardAbsKeyInputViewController = new KeyguardAbsKeyInputViewController(mAbsKeyInputView, mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback, mKeyguardMessageAreaControllerFactory, mLatencyTracker, mFalsingCollector, @@ -99,6 +101,11 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase { public void onResume(int reason) { super.onResume(reason); } + + @Override + protected int getInitialMessageResId() { + return 0; + } }; mKeyguardAbsKeyInputViewController.init(); reset(mKeyguardMessageAreaController); // Clear out implicit call to init. @@ -125,4 +132,22 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase { verifyZeroInteractions(mKeyguardSecurityCallback); verifyZeroInteractions(mKeyguardMessageAreaController); } + + @Test + public void onPromptReasonNone_doesNotSetMessage() { + mKeyguardAbsKeyInputViewController.showPromptReason(0); + verify(mKeyguardMessageAreaController, never()).setMessage( + getContext().getResources().getString(R.string.kg_prompt_reason_restart_password), + false); + } + + @Test + public void onPromptReason_setsMessage() { + when(mAbsKeyInputView.getPromptReasonStringRes(1)).thenReturn( + R.string.kg_prompt_reason_restart_password); + mKeyguardAbsKeyInputViewController.showPromptReason(1); + verify(mKeyguardMessageAreaController).setMessage( + getContext().getResources().getString(R.string.kg_prompt_reason_restart_password), + false); + } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index 61c7bb500e6a..c8e753844c64 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java @@ -29,7 +29,6 @@ import static org.mockito.Mockito.when; import android.content.res.Resources; import android.database.ContentObserver; -import android.graphics.Rect; import android.net.Uri; import android.os.UserHandle; import android.provider.Settings; @@ -47,6 +46,8 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.plugins.ClockAnimations; import com.android.systemui.plugins.ClockController; +import com.android.systemui.plugins.ClockEvents; +import com.android.systemui.plugins.ClockFaceController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.clocks.AnimatableClockView; import com.android.systemui.shared.clocks.ClockRegistry; @@ -88,7 +89,15 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { @Mock KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; @Mock - private ClockController mClock; + private ClockController mClockController; + @Mock + private ClockFaceController mLargeClockController; + @Mock + private ClockFaceController mSmallClockController; + @Mock + private ClockAnimations mClockAnimations; + @Mock + private ClockEvents mClockEvents; @Mock DumpManager mDumpManager; @Mock @@ -97,10 +106,12 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { @Mock private NotificationIconContainer mNotificationIcons; @Mock - private AnimatableClockView mClockView; + private AnimatableClockView mSmallClockView; @Mock private AnimatableClockView mLargeClockView; @Mock + private FrameLayout mSmallClockFrame; + @Mock private FrameLayout mLargeClockFrame; @Mock private SecureSettings mSecureSettings; @@ -121,9 +132,14 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { mock(RelativeLayout.LayoutParams.class)); when(mView.getContext()).thenReturn(getContext()); when(mView.getResources()).thenReturn(mResources); + when(mResources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin)) + .thenReturn(100); + when(mResources.getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin)) + .thenReturn(-200); when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame); - when(mClockView.getContext()).thenReturn(getContext()); + when(mView.findViewById(R.id.lockscreen_clock_view)).thenReturn(mSmallClockFrame); + when(mSmallClockView.getContext()).thenReturn(getContext()); when(mLargeClockView.getContext()).thenReturn(getContext()); when(mView.isAttachedToWindow()).thenReturn(true); @@ -144,7 +160,14 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { ); when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE); - when(mClockRegistry.createCurrentClock()).thenReturn(mClock); + when(mLargeClockController.getView()).thenReturn(mLargeClockView); + when(mSmallClockController.getView()).thenReturn(mSmallClockView); + when(mClockController.getLargeClock()).thenReturn(mLargeClockController); + when(mClockController.getSmallClock()).thenReturn(mSmallClockController); + when(mClockController.getEvents()).thenReturn(mClockEvents); + when(mClockController.getAnimations()).thenReturn(mClockAnimations); + when(mClockRegistry.createCurrentClock()).thenReturn(mClockController); + when(mClockEventController.getClock()).thenReturn(mClockController); mSliceView = new View(getContext()); when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView); @@ -203,8 +226,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture()); listenerArgumentCaptor.getValue().onClockChanged(); - verify(mView, times(2)).setClock(mClock, StatusBarState.SHADE); - verify(mClockEventController, times(2)).setClock(mClock); + verify(mView, times(2)).setClock(mClockController, StatusBarState.SHADE); + verify(mClockEventController, times(2)).setClock(mClockController); } @Test @@ -262,17 +285,40 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { @Test public void testGetClockAnimationsForwardsToClock() { - ClockController mockClockController = mock(ClockController.class); - ClockAnimations mockClockAnimations = mock(ClockAnimations.class); - when(mClockEventController.getClock()).thenReturn(mockClockController); - when(mockClockController.getAnimations()).thenReturn(mockClockAnimations); - - Rect r1 = new Rect(1, 2, 3, 4); - Rect r2 = new Rect(5, 6, 7, 8); - mController.getClockAnimations().onPositionUpdated(r1, r2, 0.2f); - verify(mockClockAnimations).onPositionUpdated(r1, r2, 0.2f); + assertEquals(mClockAnimations, mController.getClockAnimations()); + } + + @Test + public void testGetLargeClockBottom_returnsExpectedValue() { + when(mLargeClockFrame.getVisibility()).thenReturn(View.VISIBLE); + when(mLargeClockFrame.getHeight()).thenReturn(100); + when(mSmallClockFrame.getHeight()).thenReturn(50); + when(mLargeClockView.getHeight()).thenReturn(40); + when(mSmallClockView.getHeight()).thenReturn(20); + mController.init(); + + assertEquals(170, mController.getClockBottom(1000)); } + @Test + public void testGetSmallLargeClockBottom_returnsExpectedValue() { + when(mLargeClockFrame.getVisibility()).thenReturn(View.GONE); + when(mLargeClockFrame.getHeight()).thenReturn(100); + when(mSmallClockFrame.getHeight()).thenReturn(50); + when(mLargeClockView.getHeight()).thenReturn(40); + when(mSmallClockView.getHeight()).thenReturn(20); + mController.init(); + + assertEquals(1120, mController.getClockBottom(1000)); + } + + @Test + public void testGetClockBottom_nullClock_returnsZero() { + when(mClockEventController.getClock()).thenReturn(null); + assertEquals(0, mController.getClockBottom(10)); + } + + private void verifyAttachment(VerificationMode times) { verify(mClockRegistry, times).registerClockChangeListener( any(ClockRegistry.ClockChangeListener.class)); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt index d20be56d6c6b..d91279399341 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt @@ -30,64 +30,54 @@ import com.android.systemui.util.concurrency.DelayableExecutor import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock import org.mockito.Mockito -import org.mockito.Mockito.`when` import org.mockito.Mockito.never import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper class KeyguardPasswordViewControllerTest : SysuiTestCase() { - @Mock - private lateinit var keyguardPasswordView: KeyguardPasswordView - @Mock - private lateinit var passwordEntry: EditText - @Mock - lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor - @Mock - lateinit var securityMode: KeyguardSecurityModel.SecurityMode - @Mock - lateinit var lockPatternUtils: LockPatternUtils - @Mock - lateinit var keyguardSecurityCallback: KeyguardSecurityCallback - @Mock - lateinit var messageAreaControllerFactory: KeyguardMessageAreaController.Factory - @Mock - lateinit var latencyTracker: LatencyTracker - @Mock - lateinit var inputMethodManager: InputMethodManager - @Mock - lateinit var emergencyButtonController: EmergencyButtonController - @Mock - lateinit var mainExecutor: DelayableExecutor - @Mock - lateinit var falsingCollector: FalsingCollector - @Mock - lateinit var keyguardViewController: KeyguardViewController - @Mock - private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea - @Mock - private lateinit var mKeyguardMessageAreaController: - KeyguardMessageAreaController<BouncerKeyguardMessageArea> + @Mock private lateinit var keyguardPasswordView: KeyguardPasswordView + @Mock private lateinit var passwordEntry: EditText + @Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor + @Mock lateinit var securityMode: KeyguardSecurityModel.SecurityMode + @Mock lateinit var lockPatternUtils: LockPatternUtils + @Mock lateinit var keyguardSecurityCallback: KeyguardSecurityCallback + @Mock lateinit var messageAreaControllerFactory: KeyguardMessageAreaController.Factory + @Mock lateinit var latencyTracker: LatencyTracker + @Mock lateinit var inputMethodManager: InputMethodManager + @Mock lateinit var emergencyButtonController: EmergencyButtonController + @Mock lateinit var mainExecutor: DelayableExecutor + @Mock lateinit var falsingCollector: FalsingCollector + @Mock lateinit var keyguardViewController: KeyguardViewController + @Mock private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea + @Mock + private lateinit var mKeyguardMessageAreaController: + KeyguardMessageAreaController<BouncerKeyguardMessageArea> - private lateinit var keyguardPasswordViewController: KeyguardPasswordViewController + private lateinit var keyguardPasswordViewController: KeyguardPasswordViewController - @Before - fun setup() { - MockitoAnnotations.initMocks(this) - Mockito.`when`( - keyguardPasswordView - .requireViewById<BouncerKeyguardMessageArea>(R.id.bouncer_message_area) - ).thenReturn(mKeyguardMessageArea) - Mockito.`when`(messageAreaControllerFactory.create(mKeyguardMessageArea)) - .thenReturn(mKeyguardMessageAreaController) - Mockito.`when`(keyguardPasswordView.passwordTextViewId).thenReturn(R.id.passwordEntry) - Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry) - ).thenReturn(passwordEntry) - keyguardPasswordViewController = KeyguardPasswordViewController( + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + Mockito.`when`( + keyguardPasswordView.requireViewById<BouncerKeyguardMessageArea>( + R.id.bouncer_message_area)) + .thenReturn(mKeyguardMessageArea) + Mockito.`when`(messageAreaControllerFactory.create(mKeyguardMessageArea)) + .thenReturn(mKeyguardMessageAreaController) + Mockito.`when`(keyguardPasswordView.passwordTextViewId).thenReturn(R.id.passwordEntry) + Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry)) + .thenReturn(passwordEntry) + `when`(keyguardPasswordView.resources).thenReturn(context.resources) + keyguardPasswordViewController = + KeyguardPasswordViewController( keyguardPasswordView, keyguardUpdateMonitor, securityMode, @@ -100,51 +90,48 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() { mainExecutor, mContext.resources, falsingCollector, - keyguardViewController - ) - } + keyguardViewController) + } - @Test - fun testFocusWhenBouncerIsShown() { - Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(true) - Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true) - keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED) - keyguardPasswordView.post { - verify(keyguardPasswordView).requestFocus() - verify(keyguardPasswordView).showKeyboard() - } + @Test + fun testFocusWhenBouncerIsShown() { + Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(true) + Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true) + keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED) + keyguardPasswordView.post { + verify(keyguardPasswordView).requestFocus() + verify(keyguardPasswordView).showKeyboard() } + } - @Test - fun testDoNotFocusWhenBouncerIsHidden() { - Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(false) - Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true) - keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED) - verify(keyguardPasswordView, never()).requestFocus() - } + @Test + fun testDoNotFocusWhenBouncerIsHidden() { + Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(false) + Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true) + keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED) + verify(keyguardPasswordView, never()).requestFocus() + } - @Test - fun testHideKeyboardWhenOnPause() { - keyguardPasswordViewController.onPause() - keyguardPasswordView.post { - verify(keyguardPasswordView).clearFocus() - verify(keyguardPasswordView).hideKeyboard() - } + @Test + fun testHideKeyboardWhenOnPause() { + keyguardPasswordViewController.onPause() + keyguardPasswordView.post { + verify(keyguardPasswordView).clearFocus() + verify(keyguardPasswordView).hideKeyboard() } + } - @Test - fun startAppearAnimation() { - keyguardPasswordViewController.startAppearAnimation() - verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_password) - } + @Test + fun startAppearAnimation() { + keyguardPasswordViewController.startAppearAnimation() + verify(mKeyguardMessageAreaController) + .setMessage(context.resources.getString(R.string.keyguard_enter_your_password), false) + } - @Test - fun startAppearAnimation_withExistingMessage() { - `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.") - keyguardPasswordViewController.startAppearAnimation() - verify( - mKeyguardMessageAreaController, - never() - ).setMessage(R.string.keyguard_enter_your_password) - } + @Test + fun startAppearAnimation_withExistingMessage() { + `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.") + keyguardPasswordViewController.startAppearAnimation() + verify(mKeyguardMessageAreaController, never()).setMessage(anyString(), anyBoolean()) + } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt index b3d1c8f909d8..85dbdb8330a3 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt @@ -30,97 +30,93 @@ import com.android.systemui.statusbar.policy.DevicePostureController import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock +import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Mockito.`when` -import org.mockito.Mockito.never import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper class KeyguardPatternViewControllerTest : SysuiTestCase() { - @Mock - private lateinit var mKeyguardPatternView: KeyguardPatternView + @Mock private lateinit var mKeyguardPatternView: KeyguardPatternView - @Mock - private lateinit var mKeyguardUpdateMonitor: KeyguardUpdateMonitor + @Mock private lateinit var mKeyguardUpdateMonitor: KeyguardUpdateMonitor - @Mock - private lateinit var mSecurityMode: KeyguardSecurityModel.SecurityMode + @Mock private lateinit var mSecurityMode: KeyguardSecurityModel.SecurityMode - @Mock - private lateinit var mLockPatternUtils: LockPatternUtils + @Mock private lateinit var mLockPatternUtils: LockPatternUtils - @Mock - private lateinit var mKeyguardSecurityCallback: KeyguardSecurityCallback + @Mock private lateinit var mKeyguardSecurityCallback: KeyguardSecurityCallback - @Mock - private lateinit var mLatencyTracker: LatencyTracker - private var mFalsingCollector: FalsingCollector = FalsingCollectorFake() + @Mock private lateinit var mLatencyTracker: LatencyTracker + private var mFalsingCollector: FalsingCollector = FalsingCollectorFake() - @Mock - private lateinit var mEmergencyButtonController: EmergencyButtonController + @Mock private lateinit var mEmergencyButtonController: EmergencyButtonController - @Mock - private lateinit - var mKeyguardMessageAreaControllerFactory: KeyguardMessageAreaController.Factory + @Mock + private lateinit var mKeyguardMessageAreaControllerFactory: KeyguardMessageAreaController.Factory - @Mock - private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea + @Mock private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea - @Mock - private lateinit var mKeyguardMessageAreaController: - KeyguardMessageAreaController<BouncerKeyguardMessageArea> + @Mock + private lateinit var mKeyguardMessageAreaController: + KeyguardMessageAreaController<BouncerKeyguardMessageArea> - @Mock - private lateinit var mLockPatternView: LockPatternView + @Mock private lateinit var mLockPatternView: LockPatternView - @Mock - private lateinit var mPostureController: DevicePostureController + @Mock private lateinit var mPostureController: DevicePostureController - private lateinit var mKeyguardPatternViewController: KeyguardPatternViewController + private lateinit var mKeyguardPatternViewController: KeyguardPatternViewController - @Before - fun setup() { - MockitoAnnotations.initMocks(this) - `when`(mKeyguardPatternView.isAttachedToWindow).thenReturn(true) - `when`(mKeyguardPatternView - .requireViewById<BouncerKeyguardMessageArea>(R.id.bouncer_message_area)) - .thenReturn(mKeyguardMessageArea) - `when`(mKeyguardPatternView.findViewById<LockPatternView>(R.id.lockPatternView)) - .thenReturn(mLockPatternView) - `when`(mKeyguardMessageAreaControllerFactory.create(mKeyguardMessageArea)) - .thenReturn(mKeyguardMessageAreaController) - mKeyguardPatternViewController = KeyguardPatternViewController( + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + `when`(mKeyguardPatternView.isAttachedToWindow).thenReturn(true) + `when`( + mKeyguardPatternView.requireViewById<BouncerKeyguardMessageArea>( + R.id.bouncer_message_area)) + .thenReturn(mKeyguardMessageArea) + `when`(mKeyguardPatternView.findViewById<LockPatternView>(R.id.lockPatternView)) + .thenReturn(mLockPatternView) + `when`(mKeyguardMessageAreaControllerFactory.create(mKeyguardMessageArea)) + .thenReturn(mKeyguardMessageAreaController) + `when`(mKeyguardPatternView.resources).thenReturn(context.resources) + mKeyguardPatternViewController = + KeyguardPatternViewController( mKeyguardPatternView, - mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback, - mLatencyTracker, mFalsingCollector, mEmergencyButtonController, - mKeyguardMessageAreaControllerFactory, mPostureController - ) - } - - @Test - fun onPause_resetsText() { - mKeyguardPatternViewController.init() - mKeyguardPatternViewController.onPause() - verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern) - } - - - @Test - fun startAppearAnimation() { - mKeyguardPatternViewController.startAppearAnimation() - verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern) - } - - @Test - fun startAppearAnimation_withExistingMessage() { - `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.") - mKeyguardPatternViewController.startAppearAnimation() - verify( - mKeyguardMessageAreaController, - never() - ).setMessage(R.string.keyguard_enter_your_password) - } + mKeyguardUpdateMonitor, + mSecurityMode, + mLockPatternUtils, + mKeyguardSecurityCallback, + mLatencyTracker, + mFalsingCollector, + mEmergencyButtonController, + mKeyguardMessageAreaControllerFactory, + mPostureController) + } + + @Test + fun onPause_resetsText() { + mKeyguardPatternViewController.init() + mKeyguardPatternViewController.onPause() + verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern) + } + + @Test + fun startAppearAnimation() { + mKeyguardPatternViewController.startAppearAnimation() + verify(mKeyguardMessageAreaController) + .setMessage(context.resources.getString(R.string.keyguard_enter_your_pattern), false) + } + + @Test + fun startAppearAnimation_withExistingMessage() { + `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.") + mKeyguardPatternViewController.startAppearAnimation() + verify(mKeyguardMessageAreaController, never()).setMessage(anyString(), anyBoolean()) + } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java index ce1101f389c0..b7421001b57e 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java @@ -16,6 +16,8 @@ package com.android.keyguard; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -113,4 +115,9 @@ public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase { mKeyguardPinViewController.onResume(KeyguardSecurityView.SCREEN_ON); verify(mPasswordEntry).requestFocus(); } + + @Test + public void testGetInitialMessageResId() { + assertThat(mKeyguardPinViewController.getInitialMessageResId()).isNotEqualTo(0); + } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt index 8bcfe6f2b6f5..cdb7bbb9f823 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt @@ -31,10 +31,13 @@ import com.android.systemui.statusbar.policy.DevicePostureController import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.any import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @@ -79,6 +82,7 @@ class KeyguardPinViewControllerTest : SysuiTestCase() { keyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea::class.java)) ) .thenReturn(keyguardMessageAreaController) + `when`(keyguardPinView.resources).thenReturn(context.resources) pinViewController = KeyguardPinViewController( keyguardPinView, @@ -98,14 +102,14 @@ class KeyguardPinViewControllerTest : SysuiTestCase() { @Test fun startAppearAnimation() { pinViewController.startAppearAnimation() - verify(keyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pin) + verify(keyguardMessageAreaController) + .setMessage(context.resources.getString(R.string.keyguard_enter_your_pin), false) } @Test fun startAppearAnimation_withExistingMessage() { Mockito.`when`(keyguardMessageAreaController.message).thenReturn("Unlock to continue.") pinViewController.startAppearAnimation() - verify(keyguardMessageAreaController, Mockito.never()) - .setMessage(R.string.keyguard_enter_your_password) + verify(keyguardMessageAreaController, Mockito.never()).setMessage(anyString(), anyBoolean()) } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 40542d25689d..849ff08ac84c 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -2084,6 +2084,96 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); } + @Test + public void fingerprintFailure_requestActiveUnlock_dismissKeyguard() + throws RemoteException { + // GIVEN shouldTriggerActiveUnlock + bouncerFullyVisible(); + when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true); + + // GIVEN active unlock triggers on biometric failures + when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin( + ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL)) + .thenReturn(true); + + // WHEN fingerprint fails + mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback.onAuthenticationFailed(); + + // ALWAYS request unlock with a keyguard dismissal + verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()), + eq(true)); + } + + @Test + public void faceNonBypassFailure_requestActiveUnlock_doesNotDismissKeyguard() + throws RemoteException { + // GIVEN shouldTriggerActiveUnlock + when(mAuthController.isUdfpsFingerDown()).thenReturn(false); + keyguardIsVisible(); + keyguardNotGoingAway(); + statusBarShadeIsNotLocked(); + when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true); + + // GIVEN active unlock triggers on biometric failures + when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin( + ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL)) + .thenReturn(true); + + // WHEN face fails & bypass is not allowed + lockscreenBypassIsNotAllowed(); + mKeyguardUpdateMonitor.mFaceAuthenticationCallback.onAuthenticationFailed(); + + // THEN request unlock with NO keyguard dismissal + verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()), + eq(false)); + } + + @Test + public void faceBypassFailure_requestActiveUnlock_dismissKeyguard() + throws RemoteException { + // GIVEN shouldTriggerActiveUnlock + when(mAuthController.isUdfpsFingerDown()).thenReturn(false); + keyguardIsVisible(); + keyguardNotGoingAway(); + statusBarShadeIsNotLocked(); + when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true); + + // GIVEN active unlock triggers on biometric failures + when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin( + ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL)) + .thenReturn(true); + + // WHEN face fails & bypass is not allowed + lockscreenBypassIsAllowed(); + mKeyguardUpdateMonitor.mFaceAuthenticationCallback.onAuthenticationFailed(); + + // THEN request unlock with a keyguard dismissal + verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()), + eq(true)); + } + + @Test + public void faceNonBypassFailure_requestActiveUnlock_dismissKeyguard() + throws RemoteException { + // GIVEN shouldTriggerActiveUnlock + when(mAuthController.isUdfpsFingerDown()).thenReturn(false); + lockscreenBypassIsNotAllowed(); + when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true); + + // GIVEN active unlock triggers on biometric failures + when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin( + ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL)) + .thenReturn(true); + + // WHEN face fails & on the bouncer + bouncerFullyVisible(); + mKeyguardUpdateMonitor.mFaceAuthenticationCallback.onAuthenticationFailed(); + + // THEN request unlock with a keyguard dismissal + verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()), + eq(true)); + } + private void userDeviceLockDown() { when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false); when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId)) @@ -2101,6 +2191,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } private void mockCanBypassLockscreen(boolean canBypass) { + // force update the isFaceEnrolled cache: + mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(getCurrentUser()); + mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController); when(mKeyguardBypassController.canBypass()).thenReturn(canBypass); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt index ca94ea826782..262b4b889f84 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt @@ -301,7 +301,7 @@ class CameraGestureHelperTest : SysuiTestCase() { val intent = intentCaptor.value assertThat(CameraIntents.isSecureCameraIntent(intent)).isEqualTo(isSecure) - assertThat(intent.getIntExtra(CameraGestureHelper.EXTRA_CAMERA_LAUNCH_SOURCE, -1)) + assertThat(intent.getIntExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, -1)) .isEqualTo(source) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt index 779788aa0075..d172c9a2e630 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt @@ -38,6 +38,7 @@ import com.android.systemui.controls.CustomIconCache import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.controller.StructureInfo import com.android.systemui.controls.management.ControlsListingController +import com.android.systemui.controls.management.ControlsProviderSelectorActivity import com.android.systemui.controls.settings.FakeControlsSettingsRepository import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.ActivityStarter @@ -53,6 +54,7 @@ import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.android.wm.shell.TaskView import com.android.wm.shell.TaskViewFactory @@ -322,6 +324,45 @@ class ControlsUiControllerImplTest : SysuiTestCase() { .isFalse() } + @Test + fun testResolveActivityWhileSeeding_ControlsActivity() { + whenever(controlsController.addSeedingFavoritesCallback(any())).thenReturn(true) + assertThat(underTest.resolveActivity()).isEqualTo(ControlsActivity::class.java) + } + + @Test + fun testResolveActivityNotSeedingNoFavoritesNoPanels_ControlsProviderSelectorActivity() { + whenever(controlsController.addSeedingFavoritesCallback(any())).thenReturn(false) + whenever(controlsController.getFavorites()).thenReturn(emptyList()) + + val selectedItems = + listOf( + SelectedItem.StructureItem( + StructureInfo(ComponentName.unflattenFromString("pkg/.cls1"), "a", ArrayList()) + ), + ) + sharedPreferences + .edit() + .putString("controls_component", selectedItems[0].componentName.flattenToString()) + .putString("controls_structure", selectedItems[0].name.toString()) + .commit() + + assertThat(underTest.resolveActivity()) + .isEqualTo(ControlsProviderSelectorActivity::class.java) + } + + @Test + fun testResolveActivityNotSeedingNoDefaultNoFavoritesPanel_ControlsActivity() { + val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls")) + val activity = ComponentName("pkg", "activity") + val csi = ControlsServiceInfo(panel.componentName, panel.appName, activity) + whenever(controlsController.addSeedingFavoritesCallback(any())).thenReturn(true) + whenever(controlsController.getFavorites()).thenReturn(emptyList()) + whenever(controlsListingController.getCurrentServices()).thenReturn(listOf(csi)) + + assertThat(underTest.resolveActivity()).isEqualTo(ControlsActivity::class.java) + } + private fun setUpPanel(panel: SelectedItem.PanelItem): ControlsServiceInfo { val activity = ComponentName("pkg", "activity") sharedPreferences diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/PanelTaskViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/PanelTaskViewControllerTest.kt index 5cd2ace4604a..de04ef810dd0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/PanelTaskViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/PanelTaskViewControllerTest.kt @@ -75,6 +75,7 @@ class PanelTaskViewControllerTest : SysuiTestCase() { uiExecutor.execute(it.arguments[0] as Runnable) true } + whenever(activityContext.resources).thenReturn(context.resources) uiExecutor = FakeExecutor(FakeSystemClock()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt index 99406ed44606..8e689cf8f17e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt @@ -23,11 +23,11 @@ import org.mockito.MockitoAnnotations class DreamOverlayAnimationsControllerTest : SysuiTestCase() { companion object { + private const val DREAM_BLUR_RADIUS = 50 private const val DREAM_IN_BLUR_ANIMATION_DURATION = 1L - private const val DREAM_IN_BLUR_ANIMATION_DELAY = 2L private const val DREAM_IN_COMPLICATIONS_ANIMATION_DURATION = 3L - private const val DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY = 4L - private const val DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY = 5L + private const val DREAM_IN_TRANSLATION_Y_DISTANCE = 6 + private const val DREAM_IN_TRANSLATION_Y_DURATION = 7L private const val DREAM_OUT_TRANSLATION_Y_DISTANCE = 6 private const val DREAM_OUT_TRANSLATION_Y_DURATION = 7L private const val DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM = 8L @@ -54,11 +54,11 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() { hostViewController, statusBarViewController, stateController, + DREAM_BLUR_RADIUS, DREAM_IN_BLUR_ANIMATION_DURATION, - DREAM_IN_BLUR_ANIMATION_DELAY, DREAM_IN_COMPLICATIONS_ANIMATION_DURATION, - DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY, - DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY, + DREAM_IN_TRANSLATION_Y_DISTANCE, + DREAM_IN_TRANSLATION_Y_DURATION, DREAM_OUT_TRANSLATION_Y_DISTANCE, DREAM_OUT_TRANSLATION_Y_DURATION, DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM, diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java index c21c7a2aacbe..ee989d1ddab6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java @@ -63,7 +63,7 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { @Test public void testStateChange_overlayActive() { final DreamOverlayStateController stateController = new DreamOverlayStateController( - mExecutor); + mExecutor, true); stateController.addCallback(mCallback); stateController.setOverlayActive(true); mExecutor.runAllReady(); @@ -85,7 +85,7 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { @Test public void testCallback() { final DreamOverlayStateController stateController = new DreamOverlayStateController( - mExecutor); + mExecutor, true); stateController.addCallback(mCallback); // Add complication and verify callback is notified. @@ -111,7 +111,7 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { @Test public void testNotifyOnCallbackAdd() { final DreamOverlayStateController stateController = - new DreamOverlayStateController(mExecutor); + new DreamOverlayStateController(mExecutor, true); stateController.addComplication(mComplication); mExecutor.runAllReady(); @@ -123,9 +123,24 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { } @Test + public void testNotifyOnCallbackAddOverlayDisabled() { + final DreamOverlayStateController stateController = + new DreamOverlayStateController(mExecutor, false); + + stateController.addComplication(mComplication); + mExecutor.runAllReady(); + + // Verify callback occurs on add when an overlay is already present. + stateController.addCallback(mCallback); + mExecutor.runAllReady(); + verify(mCallback, never()).onComplicationsChanged(); + } + + + @Test public void testComplicationFilteringWhenShouldShowComplications() { final DreamOverlayStateController stateController = - new DreamOverlayStateController(mExecutor); + new DreamOverlayStateController(mExecutor, true); stateController.setShouldShowComplications(true); final Complication alwaysAvailableComplication = Mockito.mock(Complication.class); @@ -165,7 +180,7 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { @Test public void testComplicationFilteringWhenShouldHideComplications() { final DreamOverlayStateController stateController = - new DreamOverlayStateController(mExecutor); + new DreamOverlayStateController(mExecutor, true); stateController.setShouldShowComplications(true); final Complication alwaysAvailableComplication = Mockito.mock(Complication.class); @@ -212,7 +227,7 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { public void testComplicationWithNoTypeNotFiltered() { final Complication complication = Mockito.mock(Complication.class); final DreamOverlayStateController stateController = - new DreamOverlayStateController(mExecutor); + new DreamOverlayStateController(mExecutor, true); stateController.addComplication(complication); mExecutor.runAllReady(); assertThat(stateController.getComplications(true).contains(complication)) @@ -222,7 +237,7 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { @Test public void testNotifyLowLightChanged() { final DreamOverlayStateController stateController = - new DreamOverlayStateController(mExecutor); + new DreamOverlayStateController(mExecutor, true); stateController.addCallback(mCallback); mExecutor.runAllReady(); @@ -238,7 +253,7 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase { @Test public void testNotifyEntryAnimationsFinishedChanged() { final DreamOverlayStateController stateController = - new DreamOverlayStateController(mExecutor); + new DreamOverlayStateController(mExecutor, true); stateController.addCallback(mCallback); mExecutor.runAllReady(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java index b477592f8fbc..dcd8736711f6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java @@ -15,6 +15,8 @@ */ package com.android.systemui.dreams.complication; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -139,6 +141,21 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase { } @Test + public void testMalformedComplicationAddition() { + final Observer<Collection<ComplicationViewModel>> observer = + captureComplicationViewModelsObserver(); + + // Add a complication and ensure it is added to the view. + final HashSet<ComplicationViewModel> complications = new HashSet<>( + Collections.singletonList(mComplicationViewModel)); + when(mViewHolder.getView()).thenReturn(null); + observer.onChanged(complications); + + verify(mLayoutEngine, never()).addComplication(any(), any(), any(), anyInt()); + + } + + @Test public void testNewComplicationsBeforeEntryAnimationsFinishSetToInvisible() { final Observer<Collection<ComplicationViewModel>> observer = captureComplicationViewModelsObserver(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutParamsTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutParamsTest.java index fdb4cc4480da..e414942afb56 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutParamsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutParamsTest.java @@ -17,6 +17,10 @@ package com.android.systemui.dreams.complication; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + import android.testing.AndroidTestingRunner; import androidx.test.filters.SmallTest; @@ -29,6 +33,7 @@ import org.junit.runner.RunWith; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.function.Consumer; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -197,4 +202,19 @@ public class ComplicationLayoutParamsTest extends SysuiTestCase { assertThat(paramsWithConstraint.constraintSpecified()).isTrue(); assertThat(paramsWithConstraint.getConstraint()).isEqualTo(constraint); } + + @Test + public void testIteratePositions() { + final int positions = ComplicationLayoutParams.POSITION_TOP + | ComplicationLayoutParams.POSITION_START + | ComplicationLayoutParams.POSITION_END; + final Consumer<Integer> consumer = mock(Consumer.class); + + ComplicationLayoutParams.iteratePositions(consumer, positions); + + verify(consumer).accept(ComplicationLayoutParams.POSITION_TOP); + verify(consumer).accept(ComplicationLayoutParams.POSITION_START); + verify(consumer).accept(ComplicationLayoutParams.POSITION_END); + verify(consumer, never()).accept(ComplicationLayoutParams.POSITION_BOTTOM); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java index e6d3a69593cd..89c728082cc5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamHomeControlsComplicationTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.ComponentName; import android.content.Context; import android.testing.AndroidTestingRunner; import android.view.View; @@ -54,6 +55,7 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -147,6 +149,19 @@ public class DreamHomeControlsComplicationTest extends SysuiTestCase { } @Test + public void complicationAvailability_serviceAvailable_noFavorites_panel_addComplication() { + final DreamHomeControlsComplication.Registrant registrant = + new DreamHomeControlsComplication.Registrant(mComplication, + mDreamOverlayStateController, mControlsComponent); + registrant.start(); + + setHaveFavorites(false); + setServiceWithPanel(); + + verify(mDreamOverlayStateController).addComplication(mComplication); + } + + @Test public void complicationAvailability_serviceNotAvailable_haveFavorites_doNotAddComplication() { final DreamHomeControlsComplication.Registrant registrant = new DreamHomeControlsComplication.Registrant(mComplication, @@ -232,6 +247,15 @@ public class DreamHomeControlsComplicationTest extends SysuiTestCase { triggerControlsListingCallback(serviceInfos); } + private void setServiceWithPanel() { + final List<ControlsServiceInfo> serviceInfos = new ArrayList<>(); + ControlsServiceInfo csi = mock(ControlsServiceInfo.class); + serviceInfos.add(csi); + when(csi.getPanelActivity()).thenReturn(new ComponentName("a", "b")); + when(mControlsListingController.getCurrentServices()).thenReturn(serviceInfos); + triggerControlsListingCallback(serviceInfos); + } + private void setDreamOverlayActive(boolean value) { when(mDreamOverlayStateController.isOverlayActive()).thenReturn(value); verify(mDreamOverlayStateController).addCallback(mStateCallbackCaptor.capture()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt index cef452b8ec22..09c8e6ac1268 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt @@ -20,7 +20,13 @@ package com.android.systemui.keyguard import android.content.ContentValues import android.content.pm.PackageManager import android.content.pm.ProviderInfo +import android.os.Bundle +import android.os.Handler +import android.os.IBinder import android.os.UserHandle +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.view.SurfaceControlViewHost import androidx.test.filters.SmallTest import com.android.internal.widget.LockPatternUtils import com.android.systemui.SystemUIAppComponentFactoryBase @@ -36,6 +42,9 @@ import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor +import com.android.systemui.keyguard.ui.preview.KeyguardPreviewRenderer +import com.android.systemui.keyguard.ui.preview.KeyguardPreviewRendererFactory +import com.android.systemui.keyguard.ui.preview.KeyguardRemotePreviewManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.settings.UserFileManager import com.android.systemui.settings.UserTracker @@ -43,40 +52,53 @@ import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordance import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract as Contract import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.FakeSharedPreferences +import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.android.systemui.util.settings.FakeSettings import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +@OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { @Mock private lateinit var lockPatternUtils: LockPatternUtils @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var activityStarter: ActivityStarter + @Mock private lateinit var previewRendererFactory: KeyguardPreviewRendererFactory + @Mock private lateinit var previewRenderer: KeyguardPreviewRenderer + @Mock private lateinit var backgroundHandler: Handler + @Mock private lateinit var previewSurfacePackage: SurfaceControlViewHost.SurfacePackage private lateinit var underTest: KeyguardQuickAffordanceProvider + private lateinit var testScope: TestScope + @Before fun setUp() { MockitoAnnotations.initMocks(this) + whenever(previewRenderer.surfacePackage).thenReturn(previewSurfacePackage) + whenever(previewRendererFactory.create(any())).thenReturn(previewRenderer) + whenever(backgroundHandler.looper).thenReturn(TestableLooper.get(this).looper) underTest = KeyguardQuickAffordanceProvider() - val scope = CoroutineScope(IMMEDIATE) + val testDispatcher = StandardTestDispatcher() + testScope = TestScope(testDispatcher) val localUserSelectionManager = KeyguardQuickAffordanceLocalUserSelectionManager( context = context, @@ -96,7 +118,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { ) val remoteUserSelectionManager = KeyguardQuickAffordanceRemoteUserSelectionManager( - scope = scope, + scope = testScope.backgroundScope, userTracker = userTracker, clientFactory = FakeKeyguardQuickAffordanceProviderClientFactory(userTracker), userHandle = UserHandle.SYSTEM, @@ -104,7 +126,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { val quickAffordanceRepository = KeyguardQuickAffordanceRepository( appContext = context, - scope = scope, + scope = testScope.backgroundScope, localUserSelectionManager = localUserSelectionManager, remoteUserSelectionManager = remoteUserSelectionManager, userTracker = userTracker, @@ -123,8 +145,8 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { ), legacySettingSyncer = KeyguardQuickAffordanceLegacySettingSyncer( - scope = scope, - backgroundDispatcher = IMMEDIATE, + scope = testScope.backgroundScope, + backgroundDispatcher = testDispatcher, secureSettings = FakeSettings(), selectionsManager = localUserSelectionManager, ), @@ -148,6 +170,12 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { }, repository = { quickAffordanceRepository }, ) + underTest.previewManager = + KeyguardRemotePreviewManager( + previewRendererFactory = previewRendererFactory, + mainDispatcher = testDispatcher, + backgroundHandler = backgroundHandler, + ) underTest.attachInfoForTesting( context, @@ -190,7 +218,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { @Test fun `insert and query selection`() = - runBlocking(IMMEDIATE) { + testScope.runTest { val slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START val affordanceId = AFFORDANCE_2 val affordanceName = AFFORDANCE_2_NAME @@ -214,7 +242,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { @Test fun `query slots`() = - runBlocking(IMMEDIATE) { + testScope.runTest { assertThat(querySlots()) .isEqualTo( listOf( @@ -232,7 +260,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { @Test fun `query affordances`() = - runBlocking(IMMEDIATE) { + testScope.runTest { assertThat(queryAffordances()) .isEqualTo( listOf( @@ -252,7 +280,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { @Test fun `delete and query selection`() = - runBlocking(IMMEDIATE) { + testScope.runTest { insertSelection( slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, affordanceId = AFFORDANCE_1, @@ -286,7 +314,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { @Test fun `delete all selections in a slot`() = - runBlocking(IMMEDIATE) { + testScope.runTest { insertSelection( slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, affordanceId = AFFORDANCE_1, @@ -316,6 +344,23 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { ) } + @Test + fun preview() = + testScope.runTest { + val hostToken: IBinder = mock() + whenever(previewRenderer.hostToken).thenReturn(hostToken) + val extras = Bundle() + + val result = underTest.call("whatever", "anything", extras) + + verify(previewRenderer).render() + verify(hostToken).linkToDeath(any(), anyInt()) + assertThat(result!!).isNotNull() + assertThat(result.get(KeyguardRemotePreviewManager.KEY_PREVIEW_SURFACE_PACKAGE)) + .isEqualTo(previewSurfacePackage) + assertThat(result.containsKey(KeyguardRemotePreviewManager.KEY_PREVIEW_CALLBACK)) + } + private fun insertSelection( slotId: String, affordanceId: String, @@ -451,7 +496,6 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() { ) companion object { - private val IMMEDIATE = Dispatchers.Main.immediate private const val AFFORDANCE_1 = "affordance_1" private const val AFFORDANCE_2 = "affordance_2" private const val AFFORDANCE_1_NAME = "affordance_1_name" 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 798839dcc1f6..804960dc3b18 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -168,6 +168,45 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { } @Test + @TestableLooper.RunWithLooper(setAsMainLooper = true) + public void testOnStartedWakingUp_whileSleeping_ifWakeAndUnlocking_doesNotShowKeyguard() { + when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false); + when(mLockPatternUtils.getPowerButtonInstantlyLocks(anyInt())).thenReturn(true); + mViewMediator.onSystemReady(); + TestableLooper.get(this).processAllMessages(); + + mViewMediator.setShowingLocked(false); + TestableLooper.get(this).processAllMessages(); + + mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER); + mViewMediator.onWakeAndUnlocking(); + mViewMediator.onStartedWakingUp(OFF_BECAUSE_OF_USER, false); + TestableLooper.get(this).processAllMessages(); + + assertFalse(mViewMediator.isShowingAndNotOccluded()); + verify(mKeyguardStateController, never()).notifyKeyguardState(eq(true), anyBoolean()); + } + + @Test + @TestableLooper.RunWithLooper(setAsMainLooper = true) + public void testOnStartedWakingUp_whileSleeping_ifNotWakeAndUnlocking_showsKeyguard() { + when(mLockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false); + when(mLockPatternUtils.getPowerButtonInstantlyLocks(anyInt())).thenReturn(true); + mViewMediator.onSystemReady(); + TestableLooper.get(this).processAllMessages(); + + mViewMediator.setShowingLocked(false); + TestableLooper.get(this).processAllMessages(); + + mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER); + mViewMediator.onStartedWakingUp(OFF_BECAUSE_OF_USER, false); + + TestableLooper.get(this).processAllMessages(); + + assertTrue(mViewMediator.isShowingAndNotOccluded()); + } + + @Test public void testRegisterDumpable() { verify(mDumpManager).registerDumpable(KeyguardViewMediator.class.getName(), mViewMediator); verify(mStatusBarKeyguardViewManager, never()).setKeyguardGoingAwayState(anyBoolean()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt index 322014a61a73..f8cb40885d21 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt @@ -20,13 +20,14 @@ package com.android.systemui.keyguard.data.quickaffordance import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.dagger.ControlsComponent import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import java.util.* +import java.util.Optional import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -50,20 +51,22 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes companion object { @Parameters( name = - "feature enabled = {0}, has favorites = {1}, has service infos = {2}, can show" + - " while locked = {3}, visibility is AVAILABLE {4} - expected visible = {5}" + "feature enabled = {0}, has favorites = {1}, has panels = {2}, " + + "has service infos = {3}, can show while locked = {4}, " + + "visibility is AVAILABLE {5} - expected visible = {6}" ) @JvmStatic fun data() = - (0 until 32) + (0 until 64) .map { combination -> arrayOf( - /* isFeatureEnabled= */ combination and 0b10000 != 0, - /* hasFavorites= */ combination and 0b01000 != 0, - /* hasServiceInfos= */ combination and 0b00100 != 0, - /* canShowWhileLocked= */ combination and 0b00010 != 0, - /* visibilityAvailable= */ combination and 0b00001 != 0, - /* isVisible= */ combination == 0b11111, + /* isFeatureEnabled= */ combination and 0b100000 != 0, + /* hasFavorites = */ combination and 0b010000 != 0, + /* hasPanels = */ combination and 0b001000 != 0, + /* hasServiceInfos= */ combination and 0b000100 != 0, + /* canShowWhileLocked= */ combination and 0b000010 != 0, + /* visibilityAvailable= */ combination and 0b000001 != 0, + /* isVisible= */ combination in setOf(0b111111, 0b110111, 0b101111), ) } .toList() @@ -72,6 +75,7 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes @Mock private lateinit var component: ControlsComponent @Mock private lateinit var controlsController: ControlsController @Mock private lateinit var controlsListingController: ControlsListingController + @Mock private lateinit var controlsServiceInfo: ControlsServiceInfo @Captor private lateinit var callbackCaptor: ArgumentCaptor<ControlsListingController.ControlsListingCallback> @@ -80,10 +84,11 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes @JvmField @Parameter(0) var isFeatureEnabled: Boolean = false @JvmField @Parameter(1) var hasFavorites: Boolean = false - @JvmField @Parameter(2) var hasServiceInfos: Boolean = false - @JvmField @Parameter(3) var canShowWhileLocked: Boolean = false - @JvmField @Parameter(4) var isVisibilityAvailable: Boolean = false - @JvmField @Parameter(5) var isVisibleExpected: Boolean = false + @JvmField @Parameter(2) var hasPanels: Boolean = false + @JvmField @Parameter(3) var hasServiceInfos: Boolean = false + @JvmField @Parameter(4) var canShowWhileLocked: Boolean = false + @JvmField @Parameter(5) var isVisibilityAvailable: Boolean = false + @JvmField @Parameter(6) var isVisibleExpected: Boolean = false @Before fun setUp() { @@ -93,10 +98,13 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes whenever(component.getControlsController()).thenReturn(Optional.of(controlsController)) whenever(component.getControlsListingController()) .thenReturn(Optional.of(controlsListingController)) + if (hasPanels) { + whenever(controlsServiceInfo.panelActivity).thenReturn(mock()) + } whenever(controlsListingController.getCurrentServices()) .thenReturn( if (hasServiceInfos) { - listOf(mock(), mock()) + listOf(controlsServiceInfo, mock()) } else { emptyList() } @@ -134,10 +142,15 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes val job = underTest.lockScreenState.onEach(values::add).launchIn(this) if (canShowWhileLocked) { + val serviceInfoMock: ControlsServiceInfo = mock { + if (hasPanels) { + whenever(panelActivity).thenReturn(mock()) + } + } verify(controlsListingController).addCallback(callbackCaptor.capture()) callbackCaptor.value.onServicesUpdated( if (hasServiceInfos) { - listOf(mock()) + listOf(serviceInfoMock) } else { emptyList() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt index 11fe905b1d1f..d97571bcd8ef 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt @@ -23,6 +23,7 @@ import com.android.internal.widget.LockPatternUtils import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon +import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys @@ -49,14 +50,10 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.android.systemui.util.settings.FakeSettings import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.runBlockingTest -import kotlinx.coroutines.yield +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -78,6 +75,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { private lateinit var underTest: KeyguardQuickAffordanceInteractor + private lateinit var testScope: TestScope private lateinit var repository: FakeKeyguardRepository private lateinit var homeControls: FakeKeyguardQuickAffordanceConfig private lateinit var quickAccessWallet: FakeKeyguardQuickAffordanceConfig @@ -99,7 +97,8 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { ) qrCodeScanner = FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER) - val scope = CoroutineScope(IMMEDIATE) + val testDispatcher = StandardTestDispatcher() + testScope = TestScope(testDispatcher) val localUserSelectionManager = KeyguardQuickAffordanceLocalUserSelectionManager( @@ -120,7 +119,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { ) val remoteUserSelectionManager = KeyguardQuickAffordanceRemoteUserSelectionManager( - scope = scope, + scope = testScope.backgroundScope, userTracker = userTracker, clientFactory = FakeKeyguardQuickAffordanceProviderClientFactory(userTracker), userHandle = UserHandle.SYSTEM, @@ -128,14 +127,14 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { val quickAffordanceRepository = KeyguardQuickAffordanceRepository( appContext = context, - scope = scope, + scope = testScope.backgroundScope, localUserSelectionManager = localUserSelectionManager, remoteUserSelectionManager = remoteUserSelectionManager, userTracker = userTracker, legacySettingSyncer = KeyguardQuickAffordanceLegacySettingSyncer( - scope = scope, - backgroundDispatcher = IMMEDIATE, + scope = testScope.backgroundScope, + backgroundDispatcher = testDispatcher, secureSettings = FakeSettings(), selectionsManager = localUserSelectionManager, ), @@ -175,88 +174,76 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { } @Test - fun `quickAffordance - bottom start affordance is visible`() = runBlockingTest { - val configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS - homeControls.setState( - KeyguardQuickAffordanceConfig.LockScreenState.Visible( - icon = ICON, - activationState = ActivationState.Active, + fun `quickAffordance - bottom start affordance is visible`() = + testScope.runTest { + val configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS + homeControls.setState( + KeyguardQuickAffordanceConfig.LockScreenState.Visible( + icon = ICON, + activationState = ActivationState.Active, + ) ) - ) - - var latest: KeyguardQuickAffordanceModel? = null - val job = - underTest - .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) - .onEach { latest = it } - .launchIn(this) - // The interactor has an onStart { emit(Hidden) } to cover for upstream configs that don't - // produce an initial value. We yield to give the coroutine time to emit the first real - // value from our config. - yield() - - assertThat(latest).isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java) - val visibleModel = latest as KeyguardQuickAffordanceModel.Visible - assertThat(visibleModel.configKey).isEqualTo(configKey) - assertThat(visibleModel.icon).isEqualTo(ICON) - assertThat(visibleModel.icon.contentDescription) - .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID)) - assertThat(visibleModel.activationState).isEqualTo(ActivationState.Active) - job.cancel() - } + + val collectedValue = + collectLastValue( + underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) + ) + + assertThat(collectedValue()) + .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java) + val visibleModel = collectedValue() as KeyguardQuickAffordanceModel.Visible + assertThat(visibleModel.configKey).isEqualTo(configKey) + assertThat(visibleModel.icon).isEqualTo(ICON) + assertThat(visibleModel.icon.contentDescription) + .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID)) + assertThat(visibleModel.activationState).isEqualTo(ActivationState.Active) + } @Test - fun `quickAffordance - bottom end affordance is visible`() = runBlockingTest { - val configKey = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET - quickAccessWallet.setState( - KeyguardQuickAffordanceConfig.LockScreenState.Visible( - icon = ICON, + fun `quickAffordance - bottom end affordance is visible`() = + testScope.runTest { + val configKey = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET + quickAccessWallet.setState( + KeyguardQuickAffordanceConfig.LockScreenState.Visible( + icon = ICON, + ) ) - ) - - var latest: KeyguardQuickAffordanceModel? = null - val job = - underTest - .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END) - .onEach { latest = it } - .launchIn(this) - // The interactor has an onStart { emit(Hidden) } to cover for upstream configs that don't - // produce an initial value. We yield to give the coroutine time to emit the first real - // value from our config. - yield() - - assertThat(latest).isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java) - val visibleModel = latest as KeyguardQuickAffordanceModel.Visible - assertThat(visibleModel.configKey).isEqualTo(configKey) - assertThat(visibleModel.icon).isEqualTo(ICON) - assertThat(visibleModel.icon.contentDescription) - .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID)) - assertThat(visibleModel.activationState).isEqualTo(ActivationState.NotSupported) - job.cancel() - } + + val collectedValue = + collectLastValue( + underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END) + ) + + assertThat(collectedValue()) + .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java) + val visibleModel = collectedValue() as KeyguardQuickAffordanceModel.Visible + assertThat(visibleModel.configKey).isEqualTo(configKey) + assertThat(visibleModel.icon).isEqualTo(ICON) + assertThat(visibleModel.icon.contentDescription) + .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID)) + assertThat(visibleModel.activationState).isEqualTo(ActivationState.NotSupported) + } @Test - fun `quickAffordance - bottom start affordance hidden while dozing`() = runBlockingTest { - repository.setDozing(true) - homeControls.setState( - KeyguardQuickAffordanceConfig.LockScreenState.Visible( - icon = ICON, + fun `quickAffordance - bottom start affordance hidden while dozing`() = + testScope.runTest { + repository.setDozing(true) + homeControls.setState( + KeyguardQuickAffordanceConfig.LockScreenState.Visible( + icon = ICON, + ) ) - ) - - var latest: KeyguardQuickAffordanceModel? = null - val job = - underTest - .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) - .onEach { latest = it } - .launchIn(this) - assertThat(latest).isEqualTo(KeyguardQuickAffordanceModel.Hidden) - job.cancel() - } + + val collectedValue = + collectLastValue( + underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) + ) + assertThat(collectedValue()).isEqualTo(KeyguardQuickAffordanceModel.Hidden) + } @Test fun `quickAffordance - bottom start affordance hidden when lockscreen is not showing`() = - runBlockingTest { + testScope.runTest { repository.setKeyguardShowing(false) homeControls.setState( KeyguardQuickAffordanceConfig.LockScreenState.Visible( @@ -264,19 +251,45 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { ) ) - var latest: KeyguardQuickAffordanceModel? = null - val job = - underTest - .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) - .onEach { latest = it } - .launchIn(this) - assertThat(latest).isEqualTo(KeyguardQuickAffordanceModel.Hidden) - job.cancel() + val collectedValue = + collectLastValue( + underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) + ) + assertThat(collectedValue()).isEqualTo(KeyguardQuickAffordanceModel.Hidden) + } + + @Test + fun `quickAffordanceAlwaysVisible - even when lock screen not showing and dozing`() = + testScope.runTest { + repository.setKeyguardShowing(false) + repository.setDozing(true) + val configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS + homeControls.setState( + KeyguardQuickAffordanceConfig.LockScreenState.Visible( + icon = ICON, + activationState = ActivationState.Active, + ) + ) + + val collectedValue = + collectLastValue( + underTest.quickAffordanceAlwaysVisible( + KeyguardQuickAffordancePosition.BOTTOM_START + ) + ) + assertThat(collectedValue()) + .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java) + val visibleModel = collectedValue() as KeyguardQuickAffordanceModel.Visible + assertThat(visibleModel.configKey).isEqualTo(configKey) + assertThat(visibleModel.icon).isEqualTo(ICON) + assertThat(visibleModel.icon.contentDescription) + .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID)) + assertThat(visibleModel.activationState).isEqualTo(ActivationState.Active) } @Test fun select() = - runBlocking(IMMEDIATE) { + testScope.runTest { featureFlags.set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true) homeControls.setState( KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON) @@ -296,23 +309,18 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { ) ) - var startConfig: KeyguardQuickAffordanceModel? = null - val job1 = - underTest - .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) - .onEach { startConfig = it } - .launchIn(this) - var endConfig: KeyguardQuickAffordanceModel? = null - val job2 = - underTest - .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END) - .onEach { endConfig = it } - .launchIn(this) + val startConfig = + collectLastValue( + underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) + ) + val endConfig = + collectLastValue( + underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END) + ) underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, homeControls.key) - yield() - yield() - assertThat(startConfig) + + assertThat(startConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Visible( configKey = @@ -322,7 +330,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { activationState = ActivationState.NotSupported, ) ) - assertThat(endConfig) + assertThat(endConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Hidden, ) @@ -345,9 +353,8 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, quickAccessWallet.key ) - yield() - yield() - assertThat(startConfig) + + assertThat(startConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Visible( configKey = @@ -357,7 +364,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { activationState = ActivationState.NotSupported, ) ) - assertThat(endConfig) + assertThat(endConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Hidden, ) @@ -377,9 +384,8 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { ) underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, qrCodeScanner.key) - yield() - yield() - assertThat(startConfig) + + assertThat(startConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Visible( configKey = @@ -389,7 +395,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { activationState = ActivationState.NotSupported, ) ) - assertThat(endConfig) + assertThat(endConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Visible( configKey = @@ -420,14 +426,11 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { ), ) ) - - job1.cancel() - job2.cancel() } @Test fun `unselect - one`() = - runBlocking(IMMEDIATE) { + testScope.runTest { featureFlags.set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true) homeControls.setState( KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON) @@ -439,34 +442,23 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON) ) - var startConfig: KeyguardQuickAffordanceModel? = null - val job1 = - underTest - .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) - .onEach { startConfig = it } - .launchIn(this) - var endConfig: KeyguardQuickAffordanceModel? = null - val job2 = - underTest - .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END) - .onEach { endConfig = it } - .launchIn(this) + val startConfig = + collectLastValue( + underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) + ) + val endConfig = + collectLastValue( + underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END) + ) underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, homeControls.key) - yield() - yield() underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, quickAccessWallet.key) - yield() - yield() - underTest.unselect(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, homeControls.key) - yield() - yield() - assertThat(startConfig) + assertThat(startConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Hidden, ) - assertThat(endConfig) + assertThat(endConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Visible( configKey = @@ -495,14 +487,12 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, quickAccessWallet.key ) - yield() - yield() - assertThat(startConfig) + assertThat(startConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Hidden, ) - assertThat(endConfig) + assertThat(endConfig()) .isEqualTo( KeyguardQuickAffordanceModel.Hidden, ) @@ -513,14 +503,11 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to emptyList(), ) ) - - job1.cancel() - job2.cancel() } @Test fun `unselect - all`() = - runBlocking(IMMEDIATE) { + testScope.runTest { featureFlags.set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true) homeControls.setState( KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = ICON) @@ -533,15 +520,8 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { ) underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, homeControls.key) - yield() - yield() underTest.select(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, quickAccessWallet.key) - yield() - yield() - underTest.unselect(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, null) - yield() - yield() assertThat(underTest.getSelections()) .isEqualTo( @@ -562,8 +542,6 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, null, ) - yield() - yield() assertThat(underTest.getSelections()) .isEqualTo( @@ -584,6 +562,5 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { ) } private const val CONTENT_DESCRIPTION_RESOURCE_ID = 1337 - private val IMMEDIATE = Dispatchers.Main.immediate } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt index 83a5d0e90c84..0abff88b5faf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt @@ -23,6 +23,7 @@ import com.android.internal.widget.LockPatternUtils import com.android.systemui.SysuiTestCase import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon +import com.android.systemui.coroutines.collectLastValue import com.android.systemui.doze.util.BurnInHelperWrapper import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags @@ -44,20 +45,21 @@ import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAfforda import com.android.systemui.plugins.ActivityStarter import com.android.systemui.settings.UserFileManager import com.android.systemui.settings.UserTracker +import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.FakeSharedPreferences import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever import com.android.systemui.util.settings.FakeSettings import com.google.common.truth.Truth.assertThat import kotlin.math.max import kotlin.math.min -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.test.runBlockingTest -import kotlinx.coroutines.yield +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -67,9 +69,9 @@ import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.verifyZeroInteractions -import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations +@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(JUnit4::class) class KeyguardBottomAreaViewModelTest : SysuiTestCase() { @@ -83,6 +85,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { private lateinit var underTest: KeyguardBottomAreaViewModel + private lateinit var testScope: TestScope private lateinit var repository: FakeKeyguardRepository private lateinit var registry: FakeKeyguardQuickAffordanceRegistry private lateinit var homeControlsQuickAffordanceConfig: FakeKeyguardQuickAffordanceConfig @@ -123,7 +126,8 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { whenever(userTracker.userHandle).thenReturn(mock()) whenever(lockPatternUtils.getStrongAuthForUser(anyInt())) .thenReturn(LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED) - val scope = CoroutineScope(IMMEDIATE) + val testDispatcher = StandardTestDispatcher() + testScope = TestScope(testDispatcher) val localUserSelectionManager = KeyguardQuickAffordanceLocalUserSelectionManager( context = context, @@ -143,7 +147,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { ) val remoteUserSelectionManager = KeyguardQuickAffordanceRemoteUserSelectionManager( - scope = scope, + scope = testScope.backgroundScope, userTracker = userTracker, clientFactory = FakeKeyguardQuickAffordanceProviderClientFactory(userTracker), userHandle = UserHandle.SYSTEM, @@ -151,14 +155,14 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { val quickAffordanceRepository = KeyguardQuickAffordanceRepository( appContext = context, - scope = scope, + scope = testScope.backgroundScope, localUserSelectionManager = localUserSelectionManager, remoteUserSelectionManager = remoteUserSelectionManager, userTracker = userTracker, legacySettingSyncer = KeyguardQuickAffordanceLegacySettingSyncer( - scope = scope, - backgroundDispatcher = IMMEDIATE, + scope = testScope.backgroundScope, + backgroundDispatcher = testDispatcher, secureSettings = FakeSettings(), selectionsManager = localUserSelectionManager, ), @@ -194,366 +198,394 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { } @Test - fun `startButton - present - visible model - starts activity on click`() = runBlockingTest { - repository.setKeyguardShowing(true) - var latest: KeyguardQuickAffordanceViewModel? = null - val job = underTest.startButton.onEach { latest = it }.launchIn(this) - - val testConfig = - TestConfig( - isVisible = true, - isClickable = true, - isActivated = true, - icon = mock(), - canShowWhileLocked = false, - intent = Intent("action"), - ) - val configKey = - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, + fun `startButton - present - visible model - starts activity on click`() = + testScope.runTest { + repository.setKeyguardShowing(true) + val latest = collectLastValue(underTest.startButton) + + val testConfig = + TestConfig( + isVisible = true, + isClickable = true, + isActivated = true, + icon = mock(), + canShowWhileLocked = false, + intent = Intent("action"), + ) + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = testConfig, + ) + + assertQuickAffordanceViewModel( + viewModel = latest(), testConfig = testConfig, + configKey = configKey, ) - - assertQuickAffordanceViewModel( - viewModel = latest, - testConfig = testConfig, - configKey = configKey, - ) - job.cancel() - } + } @Test - fun `endButton - present - visible model - do nothing on click`() = runBlockingTest { - repository.setKeyguardShowing(true) - var latest: KeyguardQuickAffordanceViewModel? = null - val job = underTest.endButton.onEach { latest = it }.launchIn(this) + fun `startButton - in preview mode - visible even when keyguard not showing`() = + testScope.runTest { + underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START) + repository.setKeyguardShowing(false) + val latest = collectLastValue(underTest.startButton) + + val icon: Icon = mock() + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = + TestConfig( + isVisible = true, + isClickable = true, + isActivated = true, + icon = icon, + canShowWhileLocked = false, + intent = Intent("action"), + ), + ) - val config = - TestConfig( - isVisible = true, - isClickable = true, - icon = mock(), - canShowWhileLocked = false, - intent = null, // This will cause it to tell the system that the click was handled. + assertQuickAffordanceViewModel( + viewModel = latest(), + testConfig = + TestConfig( + isVisible = true, + isClickable = false, + isActivated = true, + icon = icon, + canShowWhileLocked = false, + intent = Intent("action"), + ), + configKey = configKey, ) - val configKey = - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_END, + assertThat(latest()?.isSelected).isTrue() + } + + @Test + fun `endButton - present - visible model - do nothing on click`() = + testScope.runTest { + repository.setKeyguardShowing(true) + val latest = collectLastValue(underTest.endButton) + + val config = + TestConfig( + isVisible = true, + isClickable = true, + icon = mock(), + canShowWhileLocked = false, + intent = + null, // This will cause it to tell the system that the click was handled. + ) + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_END, + testConfig = config, + ) + + assertQuickAffordanceViewModel( + viewModel = latest(), testConfig = config, + configKey = configKey, ) - - assertQuickAffordanceViewModel( - viewModel = latest, - testConfig = config, - configKey = configKey, - ) - job.cancel() - } + } @Test - fun `startButton - not present - model is hidden`() = runBlockingTest { - var latest: KeyguardQuickAffordanceViewModel? = null - val job = underTest.startButton.onEach { latest = it }.launchIn(this) + fun `startButton - not present - model is hidden`() = + testScope.runTest { + val latest = collectLastValue(underTest.startButton) - val config = - TestConfig( - isVisible = false, - ) - val configKey = - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, + val config = + TestConfig( + isVisible = false, + ) + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = config, + ) + + assertQuickAffordanceViewModel( + viewModel = latest(), testConfig = config, + configKey = configKey, ) - - assertQuickAffordanceViewModel( - viewModel = latest, - testConfig = config, - configKey = configKey, - ) - job.cancel() - } + } @Test - fun animateButtonReveal() = runBlockingTest { - repository.setKeyguardShowing(true) - val testConfig = - TestConfig( - isVisible = true, - isClickable = true, - icon = mock(), - canShowWhileLocked = false, - intent = Intent("action"), + fun animateButtonReveal() = + testScope.runTest { + repository.setKeyguardShowing(true) + val testConfig = + TestConfig( + isVisible = true, + isClickable = true, + icon = mock(), + canShowWhileLocked = false, + intent = Intent("action"), + ) + + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = testConfig, ) - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, - testConfig = testConfig, - ) + val value = collectLastValue(underTest.startButton.map { it.animateReveal }) - val values = mutableListOf<Boolean>() - val job = underTest.startButton.onEach { values.add(it.animateReveal) }.launchIn(this) + assertThat(value()).isFalse() + repository.setAnimateDozingTransitions(true) + assertThat(value()).isTrue() + repository.setAnimateDozingTransitions(false) + assertThat(value()).isFalse() + } - repository.setAnimateDozingTransitions(true) - yield() - repository.setAnimateDozingTransitions(false) - yield() + @Test + fun isOverlayContainerVisible() = + testScope.runTest { + val value = collectLastValue(underTest.isOverlayContainerVisible) + + assertThat(value()).isTrue() + repository.setDozing(true) + assertThat(value()).isFalse() + repository.setDozing(false) + assertThat(value()).isTrue() + } - // Note the extra false value in the beginning. This is to cover for the initial value - // inserted by the quick affordance interactor which it does to cover for config - // implementations that don't emit an initial value. - assertThat(values).isEqualTo(listOf(false, false, true, false)) - job.cancel() - } + @Test + fun alpha() = + testScope.runTest { + val value = collectLastValue(underTest.alpha) + + assertThat(value()).isEqualTo(1f) + repository.setBottomAreaAlpha(0.1f) + assertThat(value()).isEqualTo(0.1f) + repository.setBottomAreaAlpha(0.5f) + assertThat(value()).isEqualTo(0.5f) + repository.setBottomAreaAlpha(0.2f) + assertThat(value()).isEqualTo(0.2f) + repository.setBottomAreaAlpha(0f) + assertThat(value()).isEqualTo(0f) + } @Test - fun isOverlayContainerVisible() = runBlockingTest { - val values = mutableListOf<Boolean>() - val job = underTest.isOverlayContainerVisible.onEach(values::add).launchIn(this) + fun `alpha - in preview mode - does not change`() = + testScope.runTest { + underTest.enablePreviewMode(null) + val value = collectLastValue(underTest.alpha) + + assertThat(value()).isEqualTo(1f) + repository.setBottomAreaAlpha(0.1f) + assertThat(value()).isEqualTo(1f) + repository.setBottomAreaAlpha(0.5f) + assertThat(value()).isEqualTo(1f) + repository.setBottomAreaAlpha(0.2f) + assertThat(value()).isEqualTo(1f) + repository.setBottomAreaAlpha(0f) + assertThat(value()).isEqualTo(1f) + } - repository.setDozing(true) - repository.setDozing(false) + @Test + fun isIndicationAreaPadded() = + testScope.runTest { + repository.setKeyguardShowing(true) + val value = collectLastValue(underTest.isIndicationAreaPadded) - assertThat(values).isEqualTo(listOf(true, false, true)) - job.cancel() - } + assertThat(value()).isFalse() + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = + TestConfig( + isVisible = true, + isClickable = true, + icon = mock(), + canShowWhileLocked = true, + ) + ) + assertThat(value()).isTrue() + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_END, + testConfig = + TestConfig( + isVisible = true, + isClickable = true, + icon = mock(), + canShowWhileLocked = false, + ) + ) + assertThat(value()).isTrue() + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = + TestConfig( + isVisible = false, + ) + ) + assertThat(value()).isTrue() + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_END, + testConfig = + TestConfig( + isVisible = false, + ) + ) + assertThat(value()).isFalse() + } @Test - fun alpha() = runBlockingTest { - val values = mutableListOf<Float>() - val job = underTest.alpha.onEach(values::add).launchIn(this) - - repository.setBottomAreaAlpha(0.1f) - repository.setBottomAreaAlpha(0.5f) - repository.setBottomAreaAlpha(0.2f) - repository.setBottomAreaAlpha(0f) + fun indicationAreaTranslationX() = + testScope.runTest { + val value = collectLastValue(underTest.indicationAreaTranslationX) + + assertThat(value()).isEqualTo(0f) + repository.setClockPosition(100, 100) + assertThat(value()).isEqualTo(100f) + repository.setClockPosition(200, 100) + assertThat(value()).isEqualTo(200f) + repository.setClockPosition(200, 200) + assertThat(value()).isEqualTo(200f) + repository.setClockPosition(300, 100) + assertThat(value()).isEqualTo(300f) + } - assertThat(values).isEqualTo(listOf(1f, 0.1f, 0.5f, 0.2f, 0f)) - job.cancel() - } + @Test + fun indicationAreaTranslationY() = + testScope.runTest { + val value = + collectLastValue(underTest.indicationAreaTranslationY(DEFAULT_BURN_IN_OFFSET)) + + // Negative 0 - apparently there's a difference in floating point arithmetic - FML + assertThat(value()).isEqualTo(-0f) + val expected1 = setDozeAmountAndCalculateExpectedTranslationY(0.1f) + assertThat(value()).isEqualTo(expected1) + val expected2 = setDozeAmountAndCalculateExpectedTranslationY(0.2f) + assertThat(value()).isEqualTo(expected2) + val expected3 = setDozeAmountAndCalculateExpectedTranslationY(0.5f) + assertThat(value()).isEqualTo(expected3) + val expected4 = setDozeAmountAndCalculateExpectedTranslationY(1f) + assertThat(value()).isEqualTo(expected4) + } @Test - fun isIndicationAreaPadded() = runBlockingTest { - repository.setKeyguardShowing(true) - val values = mutableListOf<Boolean>() - val job = underTest.isIndicationAreaPadded.onEach(values::add).launchIn(this) - - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, - testConfig = - TestConfig( - isVisible = true, - isClickable = true, - icon = mock(), - canShowWhileLocked = true, - ) - ) - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_END, - testConfig = + fun `isClickable - true when alpha at threshold`() = + testScope.runTest { + repository.setKeyguardShowing(true) + repository.setBottomAreaAlpha( + KeyguardBottomAreaViewModel.AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD + ) + + val testConfig = TestConfig( isVisible = true, isClickable = true, icon = mock(), canShowWhileLocked = false, + intent = Intent("action"), ) - ) - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, - testConfig = - TestConfig( - isVisible = false, - ) - ) - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_END, - testConfig = - TestConfig( - isVisible = false, - ) - ) - - assertThat(values) - .isEqualTo( - listOf( - // Initially, no button is visible so the indication area is not padded. - false, - // Once we add the first visible button, the indication area becomes padded. - // This - // continues to be true after we add the second visible button and even after we - // make the first button not visible anymore. - true, - // Once both buttons are not visible, the indication area is, again, not padded. - false, + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = testConfig, ) - ) - job.cancel() - } - - @Test - fun indicationAreaTranslationX() = runBlockingTest { - val values = mutableListOf<Float>() - val job = underTest.indicationAreaTranslationX.onEach(values::add).launchIn(this) - repository.setClockPosition(100, 100) - repository.setClockPosition(200, 100) - repository.setClockPosition(200, 200) - repository.setClockPosition(300, 100) + val latest = collectLastValue(underTest.startButton) - assertThat(values).isEqualTo(listOf(0f, 100f, 200f, 300f)) - job.cancel() - } + assertQuickAffordanceViewModel( + viewModel = latest(), + testConfig = testConfig, + configKey = configKey, + ) + } @Test - fun indicationAreaTranslationY() = runBlockingTest { - val values = mutableListOf<Float>() - val job = - underTest - .indicationAreaTranslationY(DEFAULT_BURN_IN_OFFSET) - .onEach(values::add) - .launchIn(this) - - val expectedTranslationValues = - listOf( - -0f, // Negative 0 - apparently there's a difference in floating point arithmetic - - // FML - setDozeAmountAndCalculateExpectedTranslationY(0.1f), - setDozeAmountAndCalculateExpectedTranslationY(0.2f), - setDozeAmountAndCalculateExpectedTranslationY(0.5f), - setDozeAmountAndCalculateExpectedTranslationY(1f), + fun `isClickable - true when alpha above threshold`() = + testScope.runTest { + repository.setKeyguardShowing(true) + val latest = collectLastValue(underTest.startButton) + repository.setBottomAreaAlpha( + min(1f, KeyguardBottomAreaViewModel.AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD + 0.1f), ) - assertThat(values).isEqualTo(expectedTranslationValues) - job.cancel() - } + val testConfig = + TestConfig( + isVisible = true, + isClickable = true, + icon = mock(), + canShowWhileLocked = false, + intent = Intent("action"), + ) + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = testConfig, + ) - @Test - fun `isClickable - true when alpha at threshold`() = runBlockingTest { - repository.setKeyguardShowing(true) - repository.setBottomAreaAlpha( - KeyguardBottomAreaViewModel.AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD - ) - - val testConfig = - TestConfig( - isVisible = true, - isClickable = true, - icon = mock(), - canShowWhileLocked = false, - intent = Intent("action"), - ) - val configKey = - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, + assertQuickAffordanceViewModel( + viewModel = latest(), testConfig = testConfig, + configKey = configKey, ) - - var latest: KeyguardQuickAffordanceViewModel? = null - val job = underTest.startButton.onEach { latest = it }.launchIn(this) - // The interactor has an onStart { emit(Hidden) } to cover for upstream configs that don't - // produce an initial value. We yield to give the coroutine time to emit the first real - // value from our config. - yield() - - assertQuickAffordanceViewModel( - viewModel = latest, - testConfig = testConfig, - configKey = configKey, - ) - job.cancel() - } + } @Test - fun `isClickable - true when alpha above threshold`() = runBlockingTest { - repository.setKeyguardShowing(true) - var latest: KeyguardQuickAffordanceViewModel? = null - val job = underTest.startButton.onEach { latest = it }.launchIn(this) - repository.setBottomAreaAlpha( - min(1f, KeyguardBottomAreaViewModel.AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD + 0.1f), - ) - - val testConfig = - TestConfig( - isVisible = true, - isClickable = true, - icon = mock(), - canShowWhileLocked = false, - intent = Intent("action"), - ) - val configKey = - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, - testConfig = testConfig, + fun `isClickable - false when alpha below threshold`() = + testScope.runTest { + repository.setKeyguardShowing(true) + val latest = collectLastValue(underTest.startButton) + repository.setBottomAreaAlpha( + max(0f, KeyguardBottomAreaViewModel.AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD - 0.1f), ) - assertQuickAffordanceViewModel( - viewModel = latest, - testConfig = testConfig, - configKey = configKey, - ) - job.cancel() - } + val testConfig = + TestConfig( + isVisible = true, + isClickable = false, + icon = mock(), + canShowWhileLocked = false, + intent = Intent("action"), + ) + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = testConfig, + ) - @Test - fun `isClickable - false when alpha below threshold`() = runBlockingTest { - repository.setKeyguardShowing(true) - var latest: KeyguardQuickAffordanceViewModel? = null - val job = underTest.startButton.onEach { latest = it }.launchIn(this) - repository.setBottomAreaAlpha( - max(0f, KeyguardBottomAreaViewModel.AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD - 0.1f), - ) - - val testConfig = - TestConfig( - isVisible = true, - isClickable = false, - icon = mock(), - canShowWhileLocked = false, - intent = Intent("action"), - ) - val configKey = - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, + assertQuickAffordanceViewModel( + viewModel = latest(), testConfig = testConfig, + configKey = configKey, ) - - assertQuickAffordanceViewModel( - viewModel = latest, - testConfig = testConfig, - configKey = configKey, - ) - job.cancel() - } + } @Test - fun `isClickable - false when alpha at zero`() = runBlockingTest { - repository.setKeyguardShowing(true) - var latest: KeyguardQuickAffordanceViewModel? = null - val job = underTest.startButton.onEach { latest = it }.launchIn(this) - repository.setBottomAreaAlpha(0f) - - val testConfig = - TestConfig( - isVisible = true, - isClickable = false, - icon = mock(), - canShowWhileLocked = false, - intent = Intent("action"), - ) - val configKey = - setUpQuickAffordanceModel( - position = KeyguardQuickAffordancePosition.BOTTOM_START, + fun `isClickable - false when alpha at zero`() = + testScope.runTest { + repository.setKeyguardShowing(true) + val latest = collectLastValue(underTest.startButton) + repository.setBottomAreaAlpha(0f) + + val testConfig = + TestConfig( + isVisible = true, + isClickable = false, + icon = mock(), + canShowWhileLocked = false, + intent = Intent("action"), + ) + val configKey = + setUpQuickAffordanceModel( + position = KeyguardQuickAffordancePosition.BOTTOM_START, + testConfig = testConfig, + ) + + assertQuickAffordanceViewModel( + viewModel = latest(), testConfig = testConfig, + configKey = configKey, ) + } - assertQuickAffordanceViewModel( - viewModel = latest, - testConfig = testConfig, - configKey = configKey, - ) - job.cancel() - } - - private suspend fun setDozeAmountAndCalculateExpectedTranslationY(dozeAmount: Float): Float { + private fun setDozeAmountAndCalculateExpectedTranslationY(dozeAmount: Float): Float { repository.setDozeAmount(dozeAmount) return dozeAmount * (RETURNED_BURN_IN_OFFSET - DEFAULT_BURN_IN_OFFSET) } @@ -583,7 +615,6 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { when (testConfig.isActivated) { true -> ActivationState.Active false -> ActivationState.Inactive - null -> ActivationState.NotSupported } ) } else { @@ -636,6 +667,5 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { companion object { private const val DEFAULT_BURN_IN_OFFSET = 5 private const val RETURNED_BURN_IN_OFFSET = 3 - private val IMMEDIATE = Dispatchers.Main.immediate } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt index e009e8651f2a..0e7bf8d9d465 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt @@ -22,6 +22,7 @@ import com.android.systemui.dump.DumpManager import com.android.systemui.log.LogBufferFactory import com.android.systemui.plugins.log.LogBuffer import com.android.systemui.plugins.log.LogcatEchoTracker +import com.android.systemui.temporarydisplay.TemporaryViewInfo import com.google.common.truth.Truth.assertThat import java.io.PrintWriter import java.io.StringWriter @@ -33,7 +34,7 @@ import org.mockito.Mockito.mock class MediaTttLoggerTest : SysuiTestCase() { private lateinit var buffer: LogBuffer - private lateinit var logger: MediaTttLogger + private lateinit var logger: MediaTttLogger<TemporaryViewInfo> @Before fun setUp () { diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt index cce3e369c0b8..561867f78e60 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt @@ -25,6 +25,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription import com.android.systemui.common.shared.model.Icon +import com.android.systemui.temporarydisplay.TemporaryViewInfo import com.android.systemui.util.mockito.any import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -40,7 +41,7 @@ class MediaTttUtilsTest : SysuiTestCase() { private lateinit var appIconFromPackageName: Drawable @Mock private lateinit var packageManager: PackageManager @Mock private lateinit var applicationInfo: ApplicationInfo - @Mock private lateinit var logger: MediaTttLogger + @Mock private lateinit var logger: MediaTttLogger<TemporaryViewInfo> @Before fun setUp() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt index 4aa982ed1609..bad3f0374a31 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt @@ -27,13 +27,14 @@ import com.android.systemui.media.taptotransfer.common.MediaTttLogger import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.time.SystemClock import com.android.systemui.util.view.ViewUtil import com.android.systemui.util.wakelock.WakeLock class FakeMediaTttChipControllerReceiver( commandQueue: CommandQueue, context: Context, - logger: MediaTttLogger, + logger: MediaTttLogger<ChipReceiverInfo>, windowManager: WindowManager, mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, @@ -44,6 +45,7 @@ class FakeMediaTttChipControllerReceiver( uiEventLogger: MediaTttReceiverUiEventLogger, viewUtil: ViewUtil, wakeLockBuilder: WakeLock.Builder, + systemClock: SystemClock, ) : MediaTttChipControllerReceiver( commandQueue, @@ -59,6 +61,7 @@ class FakeMediaTttChipControllerReceiver( uiEventLogger, viewUtil, wakeLockBuilder, + systemClock, ) { override fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) { // Just bypass the animation in tests diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt index 23f7cdb45026..ef0bfb7b6700 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt @@ -67,7 +67,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { @Mock private lateinit var applicationInfo: ApplicationInfo @Mock - private lateinit var logger: MediaTttLogger + private lateinit var logger: MediaTttLogger<ChipReceiverInfo> @Mock private lateinit var accessibilityManager: AccessibilityManager @Mock @@ -128,6 +128,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { receiverUiEventLogger, viewUtil, fakeWakeLockBuilder, + fakeClock, ) controllerReceiver.start() @@ -155,6 +156,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { receiverUiEventLogger, viewUtil, fakeWakeLockBuilder, + fakeClock, ) controllerReceiver.start() @@ -193,6 +195,36 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { } @Test + fun commandQueueCallback_transferToReceiverSucceeded_noChipShown() { + commandQueueCallback.updateMediaTapToTransferReceiverDisplay( + StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, + routeInfo, + null, + null + ) + + verify(windowManager, never()).addView(any(), any()) + assertThat(uiEventLoggerFake.eventId(0)).isEqualTo( + MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_TRANSFER_TO_RECEIVER_SUCCEEDED.id + ) + } + + @Test + fun commandQueueCallback_transferToReceiverFailed_noChipShown() { + commandQueueCallback.updateMediaTapToTransferReceiverDisplay( + StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_FAILED, + routeInfo, + null, + null + ) + + verify(windowManager, never()).addView(any(), any()) + assertThat(uiEventLoggerFake.eventId(0)).isEqualTo( + MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_TRANSFER_TO_RECEIVER_FAILED.id + ) + } + + @Test fun commandQueueCallback_closeThenFar_chipShownThenHidden() { commandQueueCallback.updateMediaTapToTransferReceiverDisplay( StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER, @@ -214,6 +246,48 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { } @Test + fun commandQueueCallback_closeThenSucceeded_chipShownThenHidden() { + commandQueueCallback.updateMediaTapToTransferReceiverDisplay( + StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER, + routeInfo, + null, + null + ) + + commandQueueCallback.updateMediaTapToTransferReceiverDisplay( + StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, + routeInfo, + null, + null + ) + + val viewCaptor = ArgumentCaptor.forClass(View::class.java) + verify(windowManager).addView(viewCaptor.capture(), any()) + verify(windowManager).removeView(viewCaptor.value) + } + + @Test + fun commandQueueCallback_closeThenFailed_chipShownThenHidden() { + commandQueueCallback.updateMediaTapToTransferReceiverDisplay( + StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER, + routeInfo, + null, + null + ) + + commandQueueCallback.updateMediaTapToTransferReceiverDisplay( + StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_TRANSFER_TO_RECEIVER_FAILED, + routeInfo, + null, + null + ) + + val viewCaptor = ArgumentCaptor.forClass(View::class.java) + verify(windowManager).addView(viewCaptor.capture(), any()) + verify(windowManager).removeView(viewCaptor.value) + } + + @Test fun commandQueueCallback_closeThenFar_wakeLockAcquiredThenReleased() { commandQueueCallback.updateMediaTapToTransferReceiverDisplay( StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt index 311740e17310..b03a545f787f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt @@ -45,6 +45,7 @@ import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator +import com.android.systemui.temporarydisplay.chipbar.ChipbarInfo import com.android.systemui.temporarydisplay.chipbar.ChipbarLogger import com.android.systemui.temporarydisplay.chipbar.FakeChipbarCoordinator import com.android.systemui.util.concurrency.FakeExecutor @@ -83,7 +84,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Mock private lateinit var falsingManager: FalsingManager @Mock private lateinit var falsingCollector: FalsingCollector @Mock private lateinit var chipbarLogger: ChipbarLogger - @Mock private lateinit var logger: MediaTttLogger + @Mock private lateinit var logger: MediaTttLogger<ChipbarInfo> @Mock private lateinit var mediaTttFlags: MediaTttFlags @Mock private lateinit var packageManager: PackageManager @Mock private lateinit var powerManager: PowerManager @@ -142,6 +143,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { viewUtil, vibratorHelper, fakeWakeLockBuilder, + fakeClock, ) chipbarCoordinator.start() diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt index 9f28708a388e..5e082f686ea3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt @@ -1,9 +1,12 @@ package com.android.systemui.qs +import android.content.res.Configuration import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner +import android.testing.TestableResources import com.android.internal.logging.MetricsLogger import com.android.internal.logging.UiEventLogger +import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlags @@ -26,10 +29,11 @@ import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.any +import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations +import org.mockito.Mockito.`when` as whenever @SmallTest @RunWith(AndroidTestingRunner::class) @@ -54,8 +58,11 @@ class QSPanelControllerTest : SysuiTestCase() { @Mock private lateinit var otherTile: QSTile @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager @Mock private lateinit var featureFlags: FeatureFlags + @Mock private lateinit var configuration: Configuration + @Mock private lateinit var pagedTileLayout: PagedTileLayout private lateinit var controller: QSPanelController + private val testableResources: TestableResources = mContext.orCreateTestableResources @Before fun setUp() { @@ -63,7 +70,9 @@ class QSPanelControllerTest : SysuiTestCase() { whenever(brightnessSliderFactory.create(any(), any())).thenReturn(brightnessSlider) whenever(brightnessControllerFactory.create(any())).thenReturn(brightnessController) - whenever(qsPanel.resources).thenReturn(mContext.orCreateTestableResources.resources) + testableResources.addOverride(R.bool.config_use_split_notification_shade, false) + whenever(qsPanel.resources).thenReturn(testableResources.resources) + whenever(qsPanel.getOrCreateTileLayout()).thenReturn(pagedTileLayout) whenever(statusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false) whenever(qsPanel.setListening(anyBoolean())).then { whenever(qsPanel.isListening).thenReturn(it.getArgument(0)) @@ -121,4 +130,15 @@ class QSPanelControllerTest : SysuiTestCase() { whenever(statusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false) assertThat(controller.isBouncerInTransit()).isEqualTo(false) } + + @Test + fun configurationChange_onlySplitShadeConfigChanges_tileAreRedistributed() { + testableResources.addOverride(R.bool.config_use_split_notification_shade, false) + controller.mOnConfigurationChangedListener.onConfigurationChange(configuration) + verify(pagedTileLayout, never()).forceTilesRedistribution() + + testableResources.addOverride(R.bool.config_use_split_notification_shade, true) + controller.mOnConfigurationChangedListener.onConfigurationChange(configuration) + verify(pagedTileLayout).forceTilesRedistribution() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java index 8c8fdc5bf126..be0ad6e19a02 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java @@ -84,7 +84,8 @@ public class InternetDialogTest extends SysuiTestCase { private View mDialogView; private View mSubTitle; private LinearLayout mEthernet; - private LinearLayout mMobileDataToggle; + private LinearLayout mMobileDataLayout; + private Switch mMobileToggleSwitch; private LinearLayout mWifiToggle; private Switch mWifiToggleSwitch; private TextView mWifiToggleSummary; @@ -133,7 +134,8 @@ public class InternetDialogTest extends SysuiTestCase { mDialogView = mInternetDialog.mDialogView; mSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle); mEthernet = mDialogView.requireViewById(R.id.ethernet_layout); - mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_network_layout); + mMobileDataLayout = mDialogView.requireViewById(R.id.mobile_network_layout); + mMobileToggleSwitch = mDialogView.requireViewById(R.id.mobile_toggle); mWifiToggle = mDialogView.requireViewById(R.id.turn_on_wifi_layout); mWifiToggleSwitch = mDialogView.requireViewById(R.id.wifi_toggle); mWifiToggleSummary = mDialogView.requireViewById(R.id.wifi_toggle_summary); @@ -234,7 +236,7 @@ public class InternetDialogTest extends SysuiTestCase { mInternetDialog.updateDialog(true); - assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE); + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE); } @Test @@ -246,7 +248,7 @@ public class InternetDialogTest extends SysuiTestCase { mInternetDialog.updateDialog(true); - assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE); + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE); // Carrier network should be visible if airplane mode ON and Wi-Fi is ON. when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); @@ -255,7 +257,7 @@ public class InternetDialogTest extends SysuiTestCase { mInternetDialog.updateDialog(true); - assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE); } @Test @@ -265,7 +267,7 @@ public class InternetDialogTest extends SysuiTestCase { mInternetDialog.updateDialog(true); - assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE); + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE); } @Test @@ -277,7 +279,7 @@ public class InternetDialogTest extends SysuiTestCase { mInternetDialog.updateDialog(true); - assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE); assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.VISIBLE); } @@ -314,6 +316,30 @@ public class InternetDialogTest extends SysuiTestCase { } @Test + public void updateDialog_mobileDataIsEnabled_checkMobileDataSwitch() { + doReturn(true).when(mInternetDialogController).hasActiveSubId(); + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); + when(mInternetDialogController.isMobileDataEnabled()).thenReturn(true); + mMobileToggleSwitch.setChecked(false); + + mInternetDialog.updateDialog(true); + + assertThat(mMobileToggleSwitch.isChecked()).isTrue(); + } + + @Test + public void updateDialog_mobileDataIsNotChanged_checkMobileDataSwitch() { + doReturn(true).when(mInternetDialogController).hasActiveSubId(); + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); + when(mInternetDialogController.isMobileDataEnabled()).thenReturn(false); + mMobileToggleSwitch.setChecked(false); + + mInternetDialog.updateDialog(true); + + assertThat(mMobileToggleSwitch.isChecked()).isFalse(); + } + + @Test public void updateDialog_wifiOnAndHasInternetWifi_showConnectedWifi() { mInternetDialog.dismissDialog(); doReturn(true).when(mInternetDialogController).hasActiveSubId(); @@ -694,7 +720,7 @@ public class InternetDialogTest extends SysuiTestCase { private void setNetworkVisible(boolean ethernetVisible, boolean mobileDataVisible, boolean connectedWifiVisible) { mEthernet.setVisibility(ethernetVisible ? View.VISIBLE : View.GONE); - mMobileDataToggle.setVisibility(mobileDataVisible ? View.VISIBLE : View.GONE); + mMobileDataLayout.setVisibility(mobileDataVisible ? View.VISIBLE : View.GONE); mConnectedWifi.setVisibility(connectedWifiVisible ? View.VISIBLE : View.GONE); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java index 0302dade0a8c..351274913323 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java @@ -1102,6 +1102,17 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mStatusBarStateController.setState(KEYGUARD); + assertThat(mNotificationPanelViewController.isQsExpanded()).isEqualTo(false); + assertThat(mNotificationPanelViewController.isQsExpandImmediate()).isEqualTo(false); + } + + @Test + public void testLockedSplitShadeTransitioningToKeyguard_closesQS() { + enableSplitShade(true); + mStatusBarStateController.setState(SHADE_LOCKED); + mNotificationPanelViewController.setQsExpanded(true); + + mStatusBarStateController.setState(KEYGUARD); assertThat(mNotificationPanelViewController.isQsExpanded()).isEqualTo(false); assertThat(mNotificationPanelViewController.isQsExpandImmediate()).isEqualTo(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt index aa1114b8736e..cb4f119dce0a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt @@ -23,6 +23,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.logcatLogBuffer import com.android.systemui.statusbar.NotificationRemoteInputManager +import com.android.systemui.statusbar.notification.NotifPipelineFlags import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -38,6 +39,7 @@ import com.android.systemui.statusbar.notification.collection.provider.LaunchFul import com.android.systemui.statusbar.notification.collection.render.NodeController import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider +import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider.FullScreenIntentDecision import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback import com.android.systemui.statusbar.phone.NotificationGroupTestHelper import com.android.systemui.statusbar.policy.HeadsUpManager @@ -88,6 +90,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { private val mEndLifetimeExtension: OnEndLifetimeExtensionCallback = mock() private val mHeaderController: NodeController = mock() private val mLaunchFullScreenIntentProvider: LaunchFullScreenIntentProvider = mock() + private val mFlags: NotifPipelineFlags = mock() private lateinit var mEntry: NotificationEntry private lateinit var mGroupSummary: NotificationEntry @@ -113,6 +116,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { mNotificationInterruptStateProvider, mRemoteInputManager, mLaunchFullScreenIntentProvider, + mFlags, mHeaderController, mExecutor) mCoordinator.attach(mNotifPipeline) @@ -246,14 +250,14 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { @Test fun testOnEntryAdded_shouldFullScreen() { - setShouldFullScreen(mEntry) + setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_EXPECTED_NOT_TO_HUN) mCollectionListener.onEntryAdded(mEntry) verify(mLaunchFullScreenIntentProvider).launchFullScreenIntent(mEntry) } @Test fun testOnEntryAdded_shouldNotFullScreen() { - setShouldFullScreen(mEntry, should = false) + setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FULL_SCREEN_INTENT) mCollectionListener.onEntryAdded(mEntry) verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any()) } @@ -805,15 +809,96 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { verify(mHeadsUpManager, never()).showNotification(any()) } + @Test + fun testOnRankingApplied_noFSIOnUpdateWhenFlagOff() { + // Ensure the feature flag is off + whenever(mFlags.fsiOnDNDUpdate()).thenReturn(false) + + // GIVEN that mEntry was previously suppressed from full-screen only by DND + setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) + mCollectionListener.onEntryAdded(mEntry) + + // and it is then updated to allow full screen + setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE) + whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry)) + mCollectionListener.onRankingApplied() + + // THEN it should not full screen because the feature is off + verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry) + } + + @Test + fun testOnRankingApplied_updateToFullScreen() { + // Turn on the feature + whenever(mFlags.fsiOnDNDUpdate()).thenReturn(true) + + // GIVEN that mEntry was previously suppressed from full-screen only by DND + setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) + mCollectionListener.onEntryAdded(mEntry) + + // at this point, it should not have full screened + verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry) + + // and it is then updated to allow full screen AND HUN + setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE) + setShouldHeadsUp(mEntry) + whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry)) + mCollectionListener.onRankingApplied() + mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry)) + mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry)) + + // THEN it should full screen but it should NOT HUN + verify(mLaunchFullScreenIntentProvider).launchFullScreenIntent(mEntry) + verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any()) + verify(mHeadsUpManager, never()).showNotification(any()) + } + + @Test + fun testOnRankingApplied_noFSIWhenAlsoSuppressedForOtherReasons() { + // Feature on + whenever(mFlags.fsiOnDNDUpdate()).thenReturn(true) + + // GIVEN that mEntry is suppressed by DND (functionally), but not *only* DND + setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_BY_DND) + mCollectionListener.onEntryAdded(mEntry) + + // and it is updated to full screen later + setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE) + mCollectionListener.onRankingApplied() + + // THEN it should still not full screen because something else was blocking it before + verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry) + } + + @Test + fun testOnRankingApplied_noFSIWhenTooOld() { + // Feature on + whenever(mFlags.fsiOnDNDUpdate()).thenReturn(true) + + // GIVEN that mEntry is suppressed only by DND + setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) + mCollectionListener.onEntryAdded(mEntry) + + // but it's >10s old + mCoordinator.addForFSIReconsideration(mEntry, mSystemClock.currentTimeMillis() - 10000) + + // and it is updated to full screen later + setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_EXPECTED_NOT_TO_HUN) + mCollectionListener.onRankingApplied() + + // THEN it should still not full screen because it's too old + verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry) + } + private fun setShouldHeadsUp(entry: NotificationEntry, should: Boolean = true) { whenever(mNotificationInterruptStateProvider.shouldHeadsUp(entry)).thenReturn(should) whenever(mNotificationInterruptStateProvider.checkHeadsUp(eq(entry), any())) .thenReturn(should) } - private fun setShouldFullScreen(entry: NotificationEntry, should: Boolean = true) { - whenever(mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) - .thenReturn(should) + private fun setShouldFullScreen(entry: NotificationEntry, decision: FullScreenIntentDecision) { + whenever(mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry)) + .thenReturn(decision) } private fun finishBind(entry: NotificationEntry) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt index 4d9db8c28e07..58325697a408 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt @@ -518,7 +518,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { val childHunView = createHunViewMock( isShadeOpen = true, fullyVisible = false, - headerVisibleAmount = 1f + headerVisibleAmount = 1f, ) val algorithmState = StackScrollAlgorithm.StackScrollAlgorithmState() algorithmState.visibleChildren.add(childHunView) @@ -526,7 +526,6 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, - /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -546,7 +545,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { val childHunView = createHunViewMock( isShadeOpen = true, fullyVisible = false, - headerVisibleAmount = 1f + headerVisibleAmount = 1f, ) // Use half of the HUN's height as overlap childHunView.viewState.yTranslation = (childHunView.viewState.height + 1 shr 1).toFloat() @@ -556,7 +555,6 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, - /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -580,7 +578,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { val childHunView = createHunViewMock( isShadeOpen = true, fullyVisible = true, - headerVisibleAmount = 1f + headerVisibleAmount = 1f, ) // HUN doesn't overlap with QQS Panel childHunView.viewState.yTranslation = ambientState.topPadding + @@ -591,7 +589,6 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, - /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -611,7 +608,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { val childHunView = createHunViewMock( isShadeOpen = false, fullyVisible = false, - headerVisibleAmount = 0f + headerVisibleAmount = 0f, ) childHunView.viewState.yTranslation = 0f // Shade is closed, thus childHunView's headerVisibleAmount is 0 @@ -622,7 +619,6 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, - /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -642,7 +638,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { val childHunView = createHunViewMock( isShadeOpen = false, fullyVisible = false, - headerVisibleAmount = 0.5f + headerVisibleAmount = 0.5f, ) childHunView.viewState.yTranslation = 0f // Shade is being opened, thus childHunView's headerVisibleAmount is between 0 and 1 @@ -654,7 +650,6 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, - /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -669,7 +664,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { private fun createHunViewMock( isShadeOpen: Boolean, fullyVisible: Boolean, - headerVisibleAmount: Float + headerVisibleAmount: Float, ) = mock<ExpandableNotificationRow>().apply { val childViewStateMock = createHunChildViewState(isShadeOpen, fullyVisible) @@ -680,7 +675,10 @@ class StackScrollAlgorithmTest : SysuiTestCase() { } - private fun createHunChildViewState(isShadeOpen: Boolean, fullyVisible: Boolean) = + private fun createHunChildViewState( + isShadeOpen: Boolean, + fullyVisible: Boolean, + ) = ExpandableViewState().apply { // Mock the HUN's height with ambientState.topPadding + // ambientState.stackTranslation 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 d1957acb9fd5..74f8c61ad186 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 @@ -89,8 +89,6 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { @Mock private KeyguardViewMediator mKeyguardViewMediator; @Mock - private ScrimController mScrimController; - @Mock private BiometricUnlockController.BiometricModeListener mBiometricModeListener; @Mock private ShadeController mShadeController; @@ -140,7 +138,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { when(mVibratorHelper.hasVibrator()).thenReturn(true); mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager); mBiometricUnlockController = new BiometricUnlockController(mDozeScrimController, - mKeyguardViewMediator, mScrimController, mShadeController, + mKeyguardViewMediator, mShadeController, mNotificationShadeWindowController, mKeyguardStateController, mHandler, mUpdateMonitor, res.getResources(), mKeyguardBypassController, mMetricsLogger, mDumpManager, mPowerManager, mLogger, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt index 3d9fd961222f..22c0ea117b66 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt @@ -16,11 +16,14 @@ package com.android.systemui.statusbar.pipeline.wifi.ui.view +import android.content.res.ColorStateList +import android.graphics.Rect import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper import android.testing.ViewUtils import android.view.View +import android.widget.ImageView import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase @@ -44,6 +47,7 @@ import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiIntera import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel +import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -229,10 +233,43 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() { ViewUtils.detachView(view) } + @Test + fun onDarkChanged_iconHasNewColor() { + whenever(statusBarPipelineFlags.useWifiDebugColoring()).thenReturn(false) + val view = ModernStatusBarWifiView.constructAndBind(context, SLOT_NAME, viewModel) + ViewUtils.attachView(view) + testableLooper.processAllMessages() + + val areas = ArrayList(listOf(Rect(0, 0, 1000, 1000))) + val color = 0x12345678 + view.onDarkChanged(areas, 1.0f, color) + testableLooper.processAllMessages() + + assertThat(view.getIconView().imageTintList).isEqualTo(ColorStateList.valueOf(color)) + } + + @Test + fun setStaticDrawableColor_iconHasNewColor() { + whenever(statusBarPipelineFlags.useWifiDebugColoring()).thenReturn(false) + val view = ModernStatusBarWifiView.constructAndBind(context, SLOT_NAME, viewModel) + ViewUtils.attachView(view) + testableLooper.processAllMessages() + + val color = 0x23456789 + view.setStaticDrawableColor(color) + testableLooper.processAllMessages() + + assertThat(view.getIconView().imageTintList).isEqualTo(ColorStateList.valueOf(color)) + } + private fun View.getIconGroupView(): View { return this.requireViewById(R.id.wifi_group) } + private fun View.getIconView(): ImageView { + return this.requireViewById(R.id.wifi_signal) + } + private fun View.getDotView(): View { return this.requireViewById(R.id.status_bar_dot) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt index 09f0d4a10410..82153d5610a5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt @@ -35,6 +35,7 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.time.FakeSystemClock +import com.android.systemui.util.time.SystemClock import com.android.systemui.util.wakelock.WakeLock import com.android.systemui.util.wakelock.WakeLockFake import com.google.common.truth.Truth.assertThat @@ -59,7 +60,7 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { private lateinit var fakeWakeLock: WakeLockFake @Mock - private lateinit var logger: TemporaryViewLogger + private lateinit var logger: TemporaryViewLogger<ViewInfo> @Mock private lateinit var accessibilityManager: AccessibilityManager @Mock @@ -74,7 +75,7 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())) - .thenReturn(TIMEOUT_MS.toInt()) + .thenAnswer { it.arguments[0] } fakeClock = FakeSystemClock() fakeExecutor = FakeExecutor(fakeClock) @@ -84,14 +85,15 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { fakeWakeLockBuilder.setWakeLock(fakeWakeLock) underTest = TestController( - context, - logger, - windowManager, - fakeExecutor, - accessibilityManager, - configurationController, - powerManager, - fakeWakeLockBuilder, + context, + logger, + windowManager, + fakeExecutor, + accessibilityManager, + configurationController, + powerManager, + fakeWakeLockBuilder, + fakeClock, ) underTest.start() } @@ -112,14 +114,14 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { @Test fun displayView_logged() { - underTest.displayView( - ViewInfo( - name = "name", - windowTitle = "Fake Window Title", - ) + val info = ViewInfo( + name = "name", + windowTitle = "Fake Window Title", ) - verify(logger).logViewAddition("id", "Fake Window Title") + underTest.displayView(info) + + verify(logger).logViewAddition(info) } @Test @@ -168,10 +170,11 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { } @Test - fun displayView_twiceWithDifferentWindowTitles_oldViewRemovedNewViewAdded() { + fun displayView_twiceWithDifferentIds_oldViewRemovedNewViewAdded() { underTest.displayView( ViewInfo( name = "name", + id = "First", windowTitle = "First Fake Window Title", ) ) @@ -179,6 +182,7 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { underTest.displayView( ViewInfo( name = "name", + id = "Second", windowTitle = "Second Fake Window Title", ) ) @@ -263,19 +267,69 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { } @Test + fun viewUpdatedWithNewOnViewTimeoutRunnable_newRunnableUsed() { + var runnable1Run = false + underTest.displayView(ViewInfo(name = "name", id = "id1", windowTitle = "1")) { + runnable1Run = true + } + + var runnable2Run = false + underTest.displayView(ViewInfo(name = "name", id = "id1", windowTitle = "1")) { + runnable2Run = true + } + + fakeClock.advanceTime(TIMEOUT_MS + 1) + + assertThat(runnable1Run).isFalse() + assertThat(runnable2Run).isTrue() + } + + @Test + fun multipleViewsWithDifferentIds_moreRecentReplacesOlder() { + underTest.displayView( + ViewInfo( + name = "name", + windowTitle = "First Fake Window Title", + id = "id1" + ) + ) + + underTest.displayView( + ViewInfo( + name = "name", + windowTitle = "Second Fake Window Title", + id = "id2" + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + + verify(windowManager, times(2)).addView(capture(viewCaptor), capture(windowParamsCaptor)) + + assertThat(windowParamsCaptor.allValues[0].title).isEqualTo("First Fake Window Title") + assertThat(windowParamsCaptor.allValues[1].title).isEqualTo("Second Fake Window Title") + verify(windowManager).removeView(viewCaptor.allValues[0]) + verify(configurationController, never()).removeCallback(any()) + } + + @Test fun multipleViewsWithDifferentIds_recentActiveViewIsDisplayed() { underTest.displayView(ViewInfo("First name", id = "id1")) verify(windowManager).addView(any(), any()) - reset(windowManager) + underTest.displayView(ViewInfo("Second name", id = "id2")) - underTest.removeView("id2", "test reason") verify(windowManager).removeView(any()) + verify(windowManager).addView(any(), any()) + reset(windowManager) - fakeClock.advanceTime(DISPLAY_VIEW_DELAY + 1) + underTest.removeView("id2", "test reason") + verify(windowManager).removeView(any()) + verify(windowManager).addView(any(), any()) assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id1") assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("First name") @@ -284,6 +338,7 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { verify(windowManager).removeView(any()) assertThat(underTest.activeViews.size).isEqualTo(0) + verify(configurationController).removeCallback(any()) } @Test @@ -291,19 +346,28 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { underTest.displayView(ViewInfo("First name", id = "id1")) verify(windowManager).addView(any(), any()) - reset(windowManager) + underTest.displayView(ViewInfo("Second name", id = "id2")) + + verify(windowManager).removeView(any()) + verify(windowManager).addView(any(), any()) + reset(windowManager) + + // WHEN an old view is removed underTest.removeView("id1", "test reason") + // THEN we don't update anything verify(windowManager, never()).removeView(any()) assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id2") assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("Second name") + verify(configurationController, never()).removeCallback(any()) fakeClock.advanceTime(TIMEOUT_MS + 1) verify(windowManager).removeView(any()) assertThat(underTest.activeViews.size).isEqualTo(0) + verify(configurationController).removeCallback(any()) } @Test @@ -312,33 +376,31 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { underTest.displayView(ViewInfo("Second name", id = "id2")) underTest.displayView(ViewInfo("Third name", id = "id3")) - verify(windowManager).addView(any(), any()) + verify(windowManager, times(3)).addView(any(), any()) + verify(windowManager, times(2)).removeView(any()) reset(windowManager) underTest.removeView("id3", "test reason") verify(windowManager).removeView(any()) - - fakeClock.advanceTime(DISPLAY_VIEW_DELAY + 1) - assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id2") assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("Second name") + verify(configurationController, never()).removeCallback(any()) reset(windowManager) underTest.removeView("id2", "test reason") verify(windowManager).removeView(any()) - - fakeClock.advanceTime(DISPLAY_VIEW_DELAY + 1) - assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id1") assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("First name") + verify(configurationController, never()).removeCallback(any()) reset(windowManager) fakeClock.advanceTime(TIMEOUT_MS + 1) verify(windowManager).removeView(any()) assertThat(underTest.activeViews.size).isEqualTo(0) + verify(configurationController).removeCallback(any()) } @Test @@ -347,18 +409,21 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { underTest.displayView(ViewInfo("New name", id = "id1")) verify(windowManager).addView(any(), any()) - reset(windowManager) + underTest.displayView(ViewInfo("Second name", id = "id2")) - underTest.removeView("id2", "test reason") verify(windowManager).removeView(any()) + verify(windowManager).addView(any(), any()) + reset(windowManager) - fakeClock.advanceTime(DISPLAY_VIEW_DELAY + 1) + underTest.removeView("id2", "test reason") + verify(windowManager).removeView(any()) + verify(windowManager).addView(any(), any()) assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id1") assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("New name") - assertThat(underTest.activeViews[0].second.name).isEqualTo("New name") + assertThat(underTest.activeViews[0].info.name).isEqualTo("New name") reset(windowManager) fakeClock.advanceTime(TIMEOUT_MS + 1) @@ -368,19 +433,523 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { } @Test - fun multipleViewsWithDifferentIds_viewsTimeouts_noViewLeftToDisplay() { - underTest.displayView(ViewInfo("First name", id = "id1")) - fakeClock.advanceTime(TIMEOUT_MS / 3) - underTest.displayView(ViewInfo("Second name", id = "id2")) - fakeClock.advanceTime(TIMEOUT_MS / 3) - underTest.displayView(ViewInfo("Third name", id = "id3")) + fun multipleViews_mostRecentViewRemoved_otherViewsTimedOutAndNotDisplayed() { + underTest.displayView(ViewInfo("First name", id = "id1", timeoutMs = 4000)) + fakeClock.advanceTime(1000) + underTest.displayView(ViewInfo("Second name", id = "id2", timeoutMs = 4000)) + fakeClock.advanceTime(1000) + underTest.displayView(ViewInfo("Third name", id = "id3", timeoutMs = 20000)) reset(windowManager) - fakeClock.advanceTime(TIMEOUT_MS + 1) + fakeClock.advanceTime(20000 + 1) verify(windowManager).removeView(any()) verify(windowManager, never()).addView(any(), any()) assertThat(underTest.activeViews.size).isEqualTo(0) + verify(configurationController).removeCallback(any()) + } + + @Test + fun multipleViews_mostRecentViewRemoved_viewWithShortTimeLeftNotDisplayed() { + underTest.displayView(ViewInfo("First name", id = "id1", timeoutMs = 4000)) + fakeClock.advanceTime(1000) + underTest.displayView(ViewInfo("Second name", id = "id2", timeoutMs = 2500)) + + reset(windowManager) + fakeClock.advanceTime(2500 + 1) + // At this point, 3501ms have passed, so id1 only has 499ms left which is not enough. + // So, it shouldn't be displayed. + + verify(windowManager, never()).addView(any(), any()) + assertThat(underTest.activeViews.size).isEqualTo(0) + verify(configurationController).removeCallback(any()) + } + + @Test + fun lowerThenHigherPriority_higherReplacesLower() { + underTest.displayView( + ViewInfo( + name = "normal", + windowTitle = "Normal Window Title", + id = "normal", + priority = ViewPriority.NORMAL, + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title") + reset(windowManager) + + underTest.displayView( + ViewInfo( + name = "critical", + windowTitle = "Critical Window Title", + id = "critical", + priority = ViewPriority.CRITICAL, + ) + ) + + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Critical Window Title") + verify(configurationController, never()).removeCallback(any()) + } + + @Test + fun lowerThenHigherPriority_lowerPriorityRedisplayed() { + underTest.displayView( + ViewInfo( + name = "normal", + windowTitle = "Normal Window Title", + id = "normal", + priority = ViewPriority.NORMAL, + timeoutMs = 10000 + ) + ) + + underTest.displayView( + ViewInfo( + name = "critical", + windowTitle = "Critical Window Title", + id = "critical", + priority = ViewPriority.CRITICAL, + timeoutMs = 2000 + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager, times(2)).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.allValues[0].title).isEqualTo("Normal Window Title") + assertThat(windowParamsCaptor.allValues[1].title).isEqualTo("Critical Window Title") + verify(windowManager).removeView(viewCaptor.allValues[0]) + + reset(windowManager) + + // WHEN the critical's timeout has expired + fakeClock.advanceTime(2000 + 1) + + // THEN the normal view is re-displayed + verify(windowManager).removeView(viewCaptor.allValues[1]) + verify(windowManager).addView(any(), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title") + verify(configurationController, never()).removeCallback(any()) + } + + @Test + fun lowerThenHigherPriority_lowerPriorityNotRedisplayedBecauseTimedOut() { + underTest.displayView( + ViewInfo( + name = "normal", + windowTitle = "Normal Window Title", + id = "normal", + priority = ViewPriority.NORMAL, + timeoutMs = 1000 + ) + ) + + underTest.displayView( + ViewInfo( + name = "critical", + windowTitle = "Critical Window Title", + id = "critical", + priority = ViewPriority.CRITICAL, + timeoutMs = 2000 + ) + ) + reset(windowManager) + + // WHEN the critical's timeout has expired + fakeClock.advanceTime(2000 + 1) + + // THEN the normal view is not re-displayed since it already timed out + verify(windowManager).removeView(any()) + verify(windowManager, never()).addView(any(), any()) + assertThat(underTest.activeViews).isEmpty() + verify(configurationController).removeCallback(any()) + } + + @Test + fun higherThenLowerPriority_higherStaysDisplayed() { + underTest.displayView( + ViewInfo( + name = "critical", + windowTitle = "Critical Window Title", + id = "critical", + priority = ViewPriority.CRITICAL, + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Critical Window Title") + reset(windowManager) + + underTest.displayView( + ViewInfo( + name = "normal", + windowTitle = "Normal Window Title", + id = "normal", + priority = ViewPriority.NORMAL, + ) + ) + + verify(windowManager, never()).removeView(viewCaptor.value) + verify(windowManager, never()).addView(any(), any()) + assertThat(underTest.activeViews.size).isEqualTo(2) + verify(configurationController, never()).removeCallback(any()) + } + + @Test + fun higherThenLowerPriority_lowerEventuallyDisplayed() { + underTest.displayView( + ViewInfo( + name = "critical", + windowTitle = "Critical Window Title", + id = "critical", + priority = ViewPriority.CRITICAL, + timeoutMs = 3000, + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Critical Window Title") + reset(windowManager) + + underTest.displayView( + ViewInfo( + name = "normal", + windowTitle = "Normal Window Title", + id = "normal", + priority = ViewPriority.NORMAL, + timeoutMs = 5000, + ) + ) + + verify(windowManager, never()).removeView(viewCaptor.value) + verify(windowManager, never()).addView(any(), any()) + assertThat(underTest.activeViews.size).isEqualTo(2) + + // WHEN the first critical view has timed out + fakeClock.advanceTime(3000 + 1) + + // THEN the second normal view is displayed + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title") + assertThat(underTest.activeViews.size).isEqualTo(1) + verify(configurationController, never()).removeCallback(any()) + } + + @Test + fun higherThenLowerPriority_lowerNotDisplayedBecauseTimedOut() { + underTest.displayView( + ViewInfo( + name = "critical", + windowTitle = "Critical Window Title", + id = "critical", + priority = ViewPriority.CRITICAL, + timeoutMs = 3000, + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Critical Window Title") + reset(windowManager) + + underTest.displayView( + ViewInfo( + name = "normal", + windowTitle = "Normal Window Title", + id = "normal", + priority = ViewPriority.NORMAL, + timeoutMs = 200, + ) + ) + + verify(windowManager, never()).removeView(viewCaptor.value) + verify(windowManager, never()).addView(any(), any()) + assertThat(underTest.activeViews.size).isEqualTo(2) + reset(windowManager) + + // WHEN the first critical view has timed out + fakeClock.advanceTime(3000 + 1) + + // THEN the second normal view is not displayed because it's already timed out + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager, never()).addView(any(), any()) + assertThat(underTest.activeViews).isEmpty() + verify(configurationController).removeCallback(any()) + } + + @Test + fun criticalThenNewCritical_newCriticalDisplayed() { + underTest.displayView( + ViewInfo( + name = "critical 1", + windowTitle = "Critical Window Title 1", + id = "critical1", + priority = ViewPriority.CRITICAL, + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Critical Window Title 1") + reset(windowManager) + + underTest.displayView( + ViewInfo( + name = "critical 2", + windowTitle = "Critical Window Title 2", + id = "critical2", + priority = ViewPriority.CRITICAL, + ) + ) + + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Critical Window Title 2") + assertThat(underTest.activeViews.size).isEqualTo(2) + verify(configurationController, never()).removeCallback(any()) + } + + @Test + fun normalThenNewNormal_newNormalDisplayed() { + underTest.displayView( + ViewInfo( + name = "normal 1", + windowTitle = "Normal Window Title 1", + id = "normal1", + priority = ViewPriority.NORMAL, + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title 1") + reset(windowManager) + + underTest.displayView( + ViewInfo( + name = "normal 2", + windowTitle = "Normal Window Title 2", + id = "normal2", + priority = ViewPriority.NORMAL, + ) + ) + + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title 2") + assertThat(underTest.activeViews.size).isEqualTo(2) + verify(configurationController, never()).removeCallback(any()) + } + + @Test + fun lowerPriorityViewUpdatedWhileHigherPriorityDisplayed_eventuallyDisplaysUpdated() { + // First, display a lower priority view + underTest.displayView( + ViewInfo( + name = "normal", + windowTitle = "Normal Window Title", + id = "normal", + priority = ViewPriority.NORMAL, + // At the end of the test, we'll verify that this information isn't re-displayed. + // Use a super long timeout so that, when we verify it wasn't re-displayed, we know + // that it wasn't because the view just timed out. + timeoutMs = 100000, + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title") + reset(windowManager) + + // Then, display a higher priority view + fakeClock.advanceTime(1000) + underTest.displayView( + ViewInfo( + name = "critical", + windowTitle = "Critical Window Title", + id = "critical", + priority = ViewPriority.CRITICAL, + timeoutMs = 3000, + ) + ) + + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Critical Window Title") + assertThat(underTest.activeViews.size).isEqualTo(2) + reset(windowManager) + + // While the higher priority view is displayed, update the lower priority view with new + // information + fakeClock.advanceTime(1000) + val updatedViewInfo = ViewInfo( + name = "normal with update", + windowTitle = "Normal Window Title", + id = "normal", + priority = ViewPriority.NORMAL, + timeoutMs = 4000, + ) + underTest.displayView(updatedViewInfo) + + verify(windowManager, never()).removeView(viewCaptor.value) + verify(windowManager, never()).addView(any(), any()) + assertThat(underTest.activeViews.size).isEqualTo(2) + reset(windowManager) + + // WHEN the higher priority view times out + fakeClock.advanceTime(2001) + + // THEN the higher priority view disappears and the lower priority view *with the updated + // information* gets displayed. + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title") + assertThat(underTest.activeViews.size).isEqualTo(1) + assertThat(underTest.mostRecentViewInfo).isEqualTo(updatedViewInfo) + reset(windowManager) + + // WHEN the updated view times out + fakeClock.advanceTime(2001) + + // THEN the old information is never displayed + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager, never()).addView(any(), any()) + assertThat(underTest.activeViews.size).isEqualTo(0) + } + + @Test + fun oldViewUpdatedWhileNewViewDisplayed_eventuallyDisplaysUpdated() { + // First, display id1 view + underTest.displayView( + ViewInfo( + name = "name 1", + windowTitle = "Name 1 Title", + id = "id1", + priority = ViewPriority.NORMAL, + // At the end of the test, we'll verify that this information isn't re-displayed. + // Use a super long timeout so that, when we verify it wasn't re-displayed, we know + // that it wasn't because the view just timed out. + timeoutMs = 100000, + ) + ) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Name 1 Title") + reset(windowManager) + + // Then, display a new id2 view + fakeClock.advanceTime(1000) + underTest.displayView( + ViewInfo( + name = "name 2", + windowTitle = "Name 2 Title", + id = "id2", + priority = ViewPriority.NORMAL, + timeoutMs = 3000, + ) + ) + + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Name 2 Title") + assertThat(underTest.activeViews.size).isEqualTo(2) + reset(windowManager) + + // While the id2 view is displayed, re-display the id1 view with new information + fakeClock.advanceTime(1000) + val updatedViewInfo = ViewInfo( + name = "name 1 with update", + windowTitle = "Name 1 Title", + id = "id1", + priority = ViewPriority.NORMAL, + timeoutMs = 3000, + ) + underTest.displayView(updatedViewInfo) + + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Name 1 Title") + assertThat(underTest.activeViews.size).isEqualTo(2) + reset(windowManager) + + // WHEN the id1 view with new information times out + fakeClock.advanceTime(3001) + + // THEN the id1 view disappears and the old id1 information is never displayed + verify(windowManager).removeView(viewCaptor.value) + verify(windowManager, never()).addView(any(), any()) + assertThat(underTest.activeViews.size).isEqualTo(0) + } + + @Test + fun oldViewUpdatedWhileNewViewDisplayed_usesNewTimeout() { + // First, display id1 view + underTest.displayView( + ViewInfo( + name = "name 1", + windowTitle = "Name 1 Title", + id = "id1", + priority = ViewPriority.NORMAL, + timeoutMs = 5000, + ) + ) + + // Then, display a new id2 view + fakeClock.advanceTime(1000) + underTest.displayView( + ViewInfo( + name = "name 2", + windowTitle = "Name 2 Title", + id = "id2", + priority = ViewPriority.NORMAL, + timeoutMs = 3000, + ) + ) + reset(windowManager) + + // While the id2 view is displayed, re-display the id1 view with new information *and a + // longer timeout* + fakeClock.advanceTime(1000) + val updatedViewInfo = ViewInfo( + name = "name 1 with update", + windowTitle = "Name 1 Title", + id = "id1", + priority = ViewPriority.NORMAL, + timeoutMs = 30000, + ) + underTest.displayView(updatedViewInfo) + + val viewCaptor = argumentCaptor<View>() + val windowParamsCaptor = argumentCaptor<WindowManager.LayoutParams>() + verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor)) + assertThat(windowParamsCaptor.value.title).isEqualTo("Name 1 Title") + assertThat(underTest.activeViews.size).isEqualTo(2) + reset(windowManager) + + // WHEN id1's *old* timeout occurs + fakeClock.advanceTime(3001) + + // THEN id1 is still displayed because it was updated with a new timeout + verify(windowManager, never()).removeView(viewCaptor.value) + assertThat(underTest.activeViews.size).isEqualTo(1) } @Test @@ -395,6 +964,7 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { verify(windowManager).removeView(any()) verify(logger).logViewRemoval(deviceId, reason) + verify(configurationController).removeCallback(any()) } @Test @@ -414,14 +984,15 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { inner class TestController( context: Context, - logger: TemporaryViewLogger, + logger: TemporaryViewLogger<ViewInfo>, windowManager: WindowManager, @Main mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, powerManager: PowerManager, wakeLockBuilder: WakeLock.Builder, - ) : TemporaryViewDisplayController<ViewInfo, TemporaryViewLogger>( + systemClock: SystemClock, + ) : TemporaryViewDisplayController<ViewInfo, TemporaryViewLogger<ViewInfo>>( context, logger, windowManager, @@ -431,6 +1002,7 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { powerManager, R.layout.chipbar, wakeLockBuilder, + systemClock, ) { var mostRecentViewInfo: ViewInfo? = null @@ -447,12 +1019,13 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() { override fun start() {} } - inner class ViewInfo( + data class ViewInfo( val name: String, override val windowTitle: String = "Window Title", override val wakeReason: String = "WAKE_REASON", - override val timeoutMs: Int = 1, + override val timeoutMs: Int = TIMEOUT_MS.toInt(), override val id: String = "id", + override val priority: ViewPriority = ViewPriority.NORMAL, ) : TemporaryViewInfo() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt index 116b8fe62b37..2e66b205bfd5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt @@ -32,7 +32,7 @@ import org.mockito.Mockito @SmallTest class TemporaryViewLoggerTest : SysuiTestCase() { private lateinit var buffer: LogBuffer - private lateinit var logger: TemporaryViewLogger + private lateinit var logger: TemporaryViewLogger<TemporaryViewInfo> @Before fun setUp() { @@ -44,13 +44,22 @@ class TemporaryViewLoggerTest : SysuiTestCase() { @Test fun logViewAddition_bufferHasLog() { - logger.logViewAddition("test id", "Test Window Title") + val info = + object : TemporaryViewInfo() { + override val id: String = "test id" + override val priority: ViewPriority = ViewPriority.CRITICAL + override val windowTitle: String = "Test Window Title" + override val wakeReason: String = "wake reason" + } + + logger.logViewAddition(info) val stringWriter = StringWriter() buffer.dump(PrintWriter(stringWriter), tailLength = 0) val actualString = stringWriter.toString() assertThat(actualString).contains(TAG) + assertThat(actualString).contains("test id") assertThat(actualString).contains("Test Window Title") } diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt index 7014f93fba4a..2e4d8e74ad6e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt @@ -39,6 +39,7 @@ import com.android.systemui.common.shared.model.TintedIcon import com.android.systemui.plugins.FalsingManager import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.temporarydisplay.ViewPriority import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq @@ -105,6 +106,7 @@ class ChipbarCoordinatorTest : SysuiTestCase() { viewUtil, vibratorHelper, fakeWakeLockBuilder, + fakeClock, ) underTest.start() } @@ -408,6 +410,7 @@ class ChipbarCoordinatorTest : SysuiTestCase() { wakeReason = WAKE_REASON, timeoutMs = TIMEOUT, id = DEVICE_ID, + priority = ViewPriority.NORMAL, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt index beedf9f337bc..d5167b3890b9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt @@ -26,6 +26,7 @@ import com.android.systemui.plugins.FalsingManager import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.time.SystemClock import com.android.systemui.util.view.ViewUtil import com.android.systemui.util.wakelock.WakeLock @@ -43,6 +44,7 @@ class FakeChipbarCoordinator( viewUtil: ViewUtil, vibratorHelper: VibratorHelper, wakeLockBuilder: WakeLock.Builder, + systemClock: SystemClock, ) : ChipbarCoordinator( context, @@ -57,6 +59,7 @@ class FakeChipbarCoordinator( viewUtil, vibratorHelper, wakeLockBuilder, + systemClock, ) { override fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) { // Just bypass the animation in tests diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index 2be2d584f9a3..401d184dd7fb 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -36,16 +36,19 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.display.BrightnessSynchronizer; import com.android.server.display.config.AutoBrightness; +import com.android.server.display.config.BlockingZoneConfig; import com.android.server.display.config.BrightnessThresholds; import com.android.server.display.config.BrightnessThrottlingMap; import com.android.server.display.config.BrightnessThrottlingPoint; import com.android.server.display.config.Density; +import com.android.server.display.config.DisplayBrightnessPoint; import com.android.server.display.config.DisplayConfiguration; import com.android.server.display.config.DisplayQuirks; import com.android.server.display.config.HbmTiming; import com.android.server.display.config.HighBrightnessMode; import com.android.server.display.config.NitsMap; import com.android.server.display.config.Point; +import com.android.server.display.config.RefreshRateConfigs; import com.android.server.display.config.RefreshRateRange; import com.android.server.display.config.SdrHdrRatioMap; import com.android.server.display.config.SdrHdrRatioPoint; @@ -130,6 +133,35 @@ import javax.xml.datatype.DatatypeConfigurationException; * </brightnessThrottlingMap> * </thermalThrottling> * + * <refreshRate> + * <lowerBlockingZoneConfigs> + * <defaultRefreshRate>75</defaultRefreshRate> + * <blockingZoneThreshold> + * <displayBrightnessPoint> + * <lux>50</lux> + * <nits>45.3</nits> + * </displayBrightnessPoint> + * <displayBrightnessPoint> + * <lux>60</lux> + * <nits>55.2</nits> + * </displayBrightnessPoint> + * </blockingZoneThreshold> + * </lowerBlockingZoneConfigs> + * <higherBlockingZoneConfigs> + * <defaultRefreshRate>90</defaultRefreshRate> + * <blockingZoneThreshold> + * <displayBrightnessPoint> + * <lux>500</lux> + * <nits>245.3</nits> + * </displayBrightnessPoint> + * <displayBrightnessPoint> + * <lux>600</lux> + * <nits>232.3</nits> + * </displayBrightnessPoint> + * </blockingZoneThreshold> + * </higherBlockingZoneConfigs> + * </refreshRate> + * * <highBrightnessMode enabled="true"> * <transitionPoint>0.62</transitionPoint> * <minimumLux>10000</minimumLux> @@ -358,6 +390,9 @@ public class DisplayDeviceConfig { private static final String STABLE_ID_SUFFIX_FORMAT = "id_%d"; private static final String NO_SUFFIX_FORMAT = "%d"; private static final long STABLE_FLAG = 1L << 62; + private static final int DEFAULT_LOW_REFRESH_RATE = 60; + private static final int DEFAULT_HIGH_REFRESH_RATE = 0; + private static final int[] DEFAULT_BRIGHTNESS_THRESHOLDS = new int[]{}; private static final float[] DEFAULT_AMBIENT_THRESHOLD_LEVELS = new float[]{0f}; private static final float[] DEFAULT_AMBIENT_BRIGHTENING_THRESHOLDS = new float[]{100f}; @@ -512,6 +547,49 @@ public class DisplayDeviceConfig { // This stores the raw value loaded from the config file - true if not written. private boolean mDdcAutoBrightnessAvailable = true; + /** + * The default peak refresh rate for a given device. This value prevents the framework from + * using higher refresh rates, even if display modes with higher refresh rates are available + * from hardware composer. Only has an effect if the value is non-zero. + */ + private int mDefaultHighRefreshRate = DEFAULT_HIGH_REFRESH_RATE; + + /** + * The default refresh rate for a given device. This value sets the higher default + * refresh rate. If the hardware composer on the device supports display modes with + * a higher refresh rate than the default value specified here, the framework may use those + * higher refresh rate modes if an app chooses one by setting preferredDisplayModeId or calling + * setFrameRate(). We have historically allowed fallback to mDefaultHighRefreshRate if + * mDefaultLowRefreshRate is set to 0, but this is not supported anymore. + */ + private int mDefaultLowRefreshRate = DEFAULT_LOW_REFRESH_RATE; + + /** + * The display uses different gamma curves for different refresh rates. It's hard for panel + * vendors to tune the curves to have exact same brightness for different refresh rate. So + * brightness flickers could be observed at switch time. The issue is worse at the gamma lower + * end. In addition, human eyes are more sensitive to the flicker at darker environment. To + * prevent flicker, we only support higher refresh rates if the display brightness is above a + * threshold. For example, no higher refresh rate if display brightness <= disp0 && ambient + * brightness <= amb0 || display brightness <= disp1 && ambient brightness <= amb1 + */ + private int[] mLowDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; + private int[] mLowAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; + + /** + * The display uses different gamma curves for different refresh rates. It's hard for panel + * vendors to tune the curves to have exact same brightness for different refresh rate. So + * brightness flickers could be observed at switch time. The issue can be observed on the screen + * with even full white content at the high brightness. To prevent flickering, we support fixed + * refresh rates if the display and ambient brightness are equal to or above the provided + * thresholds. You can define multiple threshold levels as higher brightness environments may + * have lower display brightness requirements for the flickering is visible. For example, fixed + * refresh rate if display brightness >= disp0 && ambient brightness >= amb0 || display + * brightness >= disp1 && ambient brightness >= amb1 + */ + private int[] mHighDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; + private int[] mHighAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; + // Brightness Throttling data may be updated via the DeviceConfig. Here we store the original // data, which comes from the ddc, and the current one, which may be the DeviceConfig // overwritten value. @@ -1196,15 +1274,15 @@ public class DisplayDeviceConfig { /** * @return Default peak refresh rate of the associated display */ - public int getDefaultPeakRefreshRate() { - return mContext.getResources().getInteger(R.integer.config_defaultPeakRefreshRate); + public int getDefaultHighRefreshRate() { + return mDefaultHighRefreshRate; } /** * @return Default refresh rate of the associated display */ - public int getDefaultRefreshRate() { - return mContext.getResources().getInteger(R.integer.config_defaultRefreshRate); + public int getDefaultLowRefreshRate() { + return mDefaultLowRefreshRate; } /** @@ -1213,8 +1291,7 @@ public class DisplayDeviceConfig { * allowed */ public int[] getLowDisplayBrightnessThresholds() { - return mContext.getResources().getIntArray( - R.array.config_brightnessThresholdsOfPeakRefreshRate); + return mLowDisplayBrightnessThresholds; } /** @@ -1223,8 +1300,7 @@ public class DisplayDeviceConfig { * allowed */ public int[] getLowAmbientBrightnessThresholds() { - return mContext.getResources().getIntArray( - R.array.config_ambientThresholdsOfPeakRefreshRate); + return mLowAmbientBrightnessThresholds; } /** @@ -1233,8 +1309,7 @@ public class DisplayDeviceConfig { * allowed */ public int[] getHighDisplayBrightnessThresholds() { - return mContext.getResources().getIntArray( - R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate); + return mHighDisplayBrightnessThresholds; } /** @@ -1243,8 +1318,7 @@ public class DisplayDeviceConfig { * allowed */ public int[] getHighAmbientBrightnessThresholds() { - return mContext.getResources().getIntArray( - R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate); + return mHighAmbientBrightnessThresholds; } @Override @@ -1336,6 +1410,17 @@ public class DisplayDeviceConfig { + ", mBrightnessLevelsNits= " + Arrays.toString(mBrightnessLevelsNits) + ", mDdcAutoBrightnessAvailable= " + mDdcAutoBrightnessAvailable + ", mAutoBrightnessAvailable= " + mAutoBrightnessAvailable + + "\n" + + ", mDefaultRefreshRate= " + mDefaultLowRefreshRate + + ", mDefaultPeakRefreshRate= " + mDefaultHighRefreshRate + + ", mLowDisplayBrightnessThresholds= " + + Arrays.toString(mLowDisplayBrightnessThresholds) + + ", mLowAmbientBrightnessThresholds= " + + Arrays.toString(mLowAmbientBrightnessThresholds) + + ", mHighDisplayBrightnessThresholds= " + + Arrays.toString(mHighDisplayBrightnessThresholds) + + ", mHighAmbientBrightnessThresholds= " + + Arrays.toString(mHighAmbientBrightnessThresholds) + "}"; } @@ -1393,6 +1478,7 @@ public class DisplayDeviceConfig { loadAmbientHorizonFromDdc(config); loadBrightnessChangeThresholds(config); loadAutoBrightnessConfigValues(config); + loadRefreshRateSetting(config); } else { Slog.w(TAG, "DisplayDeviceConfig file is null"); } @@ -1415,6 +1501,7 @@ public class DisplayDeviceConfig { useFallbackProxSensor(); loadAutoBrightnessConfigsFromConfigXml(); loadAutoBrightnessAvailableFromConfigXml(); + loadRefreshRateSetting(null); mLoadedFrom = "<config.xml>"; } @@ -1625,6 +1712,143 @@ public class DisplayDeviceConfig { } } + private void loadRefreshRateSetting(DisplayConfiguration config) { + final RefreshRateConfigs refreshRateConfigs = + (config == null) ? null : config.getRefreshRate(); + BlockingZoneConfig lowerBlockingZoneConfig = + (refreshRateConfigs == null) ? null + : refreshRateConfigs.getLowerBlockingZoneConfigs(); + BlockingZoneConfig higherBlockingZoneConfig = + (refreshRateConfigs == null) ? null + : refreshRateConfigs.getHigherBlockingZoneConfigs(); + loadLowerRefreshRateBlockingZones(lowerBlockingZoneConfig); + loadHigherRefreshRateBlockingZones(higherBlockingZoneConfig); + } + + + /** + * Loads the refresh rate configurations pertaining to the upper blocking zones. + */ + private void loadLowerRefreshRateBlockingZones(BlockingZoneConfig lowerBlockingZoneConfig) { + loadLowerBlockingZoneDefaultRefreshRate(lowerBlockingZoneConfig); + loadLowerBrightnessThresholds(lowerBlockingZoneConfig); + } + + /** + * Loads the refresh rate configurations pertaining to the upper blocking zones. + */ + private void loadHigherRefreshRateBlockingZones(BlockingZoneConfig upperBlockingZoneConfig) { + loadHigherBlockingZoneDefaultRefreshRate(upperBlockingZoneConfig); + loadHigherBrightnessThresholds(upperBlockingZoneConfig); + } + + /** + * Loads the default peak refresh rate. Internally, this takes care of loading + * the value from the display config, and if not present, falls back to config.xml. + */ + private void loadHigherBlockingZoneDefaultRefreshRate( + BlockingZoneConfig upperBlockingZoneConfig) { + if (upperBlockingZoneConfig == null) { + mDefaultHighRefreshRate = mContext.getResources().getInteger( + com.android.internal.R.integer.config_defaultPeakRefreshRate); + } else { + mDefaultHighRefreshRate = + upperBlockingZoneConfig.getDefaultRefreshRate().intValue(); + } + } + + /** + * Loads the default refresh rate. Internally, this takes care of loading + * the value from the display config, and if not present, falls back to config.xml. + */ + private void loadLowerBlockingZoneDefaultRefreshRate( + BlockingZoneConfig lowerBlockingZoneConfig) { + if (lowerBlockingZoneConfig == null) { + mDefaultLowRefreshRate = mContext.getResources().getInteger( + com.android.internal.R.integer.config_defaultRefreshRate); + } else { + mDefaultLowRefreshRate = + lowerBlockingZoneConfig.getDefaultRefreshRate().intValue(); + } + } + + /** + * Loads the lower brightness thresholds for refresh rate switching. Internally, this takes care + * of loading the value from the display config, and if not present, falls back to config.xml. + */ + private void loadLowerBrightnessThresholds(BlockingZoneConfig lowerBlockingZoneConfig) { + if (lowerBlockingZoneConfig == null) { + mLowDisplayBrightnessThresholds = mContext.getResources().getIntArray( + R.array.config_brightnessThresholdsOfPeakRefreshRate); + mLowAmbientBrightnessThresholds = mContext.getResources().getIntArray( + R.array.config_ambientThresholdsOfPeakRefreshRate); + if (mLowDisplayBrightnessThresholds == null || mLowAmbientBrightnessThresholds == null + || mLowDisplayBrightnessThresholds.length + != mLowAmbientBrightnessThresholds.length) { + throw new RuntimeException("display low brightness threshold array and ambient " + + "brightness threshold array have different length: " + + "mLowDisplayBrightnessThresholds=" + + Arrays.toString(mLowDisplayBrightnessThresholds) + + ", mLowAmbientBrightnessThresholds=" + + Arrays.toString(mLowAmbientBrightnessThresholds)); + } + } else { + List<DisplayBrightnessPoint> lowerThresholdDisplayBrightnessPoints = + lowerBlockingZoneConfig.getBlockingZoneThreshold().getDisplayBrightnessPoint(); + int size = lowerThresholdDisplayBrightnessPoints.size(); + mLowDisplayBrightnessThresholds = new int[size]; + mLowAmbientBrightnessThresholds = new int[size]; + for (int i = 0; i < size; i++) { + // We are explicitly casting this value to an integer to be able to reuse the + // existing DisplayBrightnessPoint type. It is fine to do this because the round off + // will have the negligible and unnoticeable impact on the loaded thresholds. + mLowDisplayBrightnessThresholds[i] = (int) lowerThresholdDisplayBrightnessPoints + .get(i).getNits().floatValue(); + mLowAmbientBrightnessThresholds[i] = lowerThresholdDisplayBrightnessPoints + .get(i).getLux().intValue(); + } + } + } + + /** + * Loads the higher brightness thresholds for refresh rate switching. Internally, this takes + * care of loading the value from the display config, and if not present, falls back to + * config.xml. + */ + private void loadHigherBrightnessThresholds(BlockingZoneConfig blockingZoneConfig) { + if (blockingZoneConfig == null) { + mHighDisplayBrightnessThresholds = mContext.getResources().getIntArray( + R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate); + mHighAmbientBrightnessThresholds = mContext.getResources().getIntArray( + R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate); + if (mHighAmbientBrightnessThresholds == null || mHighDisplayBrightnessThresholds == null + || mHighAmbientBrightnessThresholds.length + != mHighDisplayBrightnessThresholds.length) { + throw new RuntimeException("display high brightness threshold array and ambient " + + "brightness threshold array have different length: " + + "mHighDisplayBrightnessThresholds=" + + Arrays.toString(mHighDisplayBrightnessThresholds) + + ", mHighAmbientBrightnessThresholds=" + + Arrays.toString(mHighAmbientBrightnessThresholds)); + } + } else { + List<DisplayBrightnessPoint> higherThresholdDisplayBrightnessPoints = + blockingZoneConfig.getBlockingZoneThreshold().getDisplayBrightnessPoint(); + int size = higherThresholdDisplayBrightnessPoints.size(); + mHighDisplayBrightnessThresholds = new int[size]; + mHighAmbientBrightnessThresholds = new int[size]; + for (int i = 0; i < size; i++) { + // We are explicitly casting this value to an integer to be able to reuse the + // existing DisplayBrightnessPoint type. It is fine to do this because the round off + // will have the negligible and unnoticeable impact on the loaded thresholds. + mHighDisplayBrightnessThresholds[i] = (int) higherThresholdDisplayBrightnessPoints + .get(i).getNits().floatValue(); + mHighAmbientBrightnessThresholds[i] = higherThresholdDisplayBrightnessPoints + .get(i).getLux().intValue(); + } + } + } + private void loadAutoBrightnessConfigValues(DisplayConfiguration config) { final AutoBrightness autoBrightness = config.getAutoBrightness(); loadAutoBrightnessBrighteningLightDebounce(autoBrightness); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index f9c8f064de96..3da7d830a23f 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -3652,44 +3652,21 @@ public final class DisplayManagerService extends SystemService { @Override public Set<DisplayInfo> getPossibleDisplayInfo(int displayId) { synchronized (mSyncRoot) { - // Retrieve the group associated with this display id. - final int displayGroupId = - mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(displayId); - if (displayGroupId == Display.INVALID_DISPLAY_GROUP) { - Slog.w(TAG, - "Can't get possible display info since display group for " + displayId - + " does not exist"); - return new ArraySet<>(); - } - - // Assume any display in this group can be swapped out for the given display id. Set<DisplayInfo> possibleInfo = new ArraySet<>(); - final DisplayGroup group = mLogicalDisplayMapper.getDisplayGroupLocked( - displayGroupId); - for (int i = 0; i < group.getSizeLocked(); i++) { - final int id = group.getIdLocked(i); - final LogicalDisplay logical = mLogicalDisplayMapper.getDisplayLocked(id); - if (logical == null) { - Slog.w(TAG, - "Can't get possible display info since logical display for " - + "display id " + id + " does not exist, as part of group " - + displayGroupId); - } else { - possibleInfo.add(logical.getDisplayInfoLocked()); - } - } - - // For the supported device states, retrieve the DisplayInfos for the logical - // display layout. + // For each of supported device states, retrieve the display layout of that state, + // and return all of the DisplayInfos (one per state) for the given display id. if (mDeviceStateManager == null) { Slog.w(TAG, "Can't get supported states since DeviceStateManager not ready"); - } else { - final int[] supportedStates = - mDeviceStateManager.getSupportedStateIdentifiers(); - for (int state : supportedStates) { - possibleInfo.addAll( - mLogicalDisplayMapper.getDisplayInfoForStateLocked(state, displayId, - displayGroupId)); + return possibleInfo; + } + final int[] supportedStates = + mDeviceStateManager.getSupportedStateIdentifiers(); + DisplayInfo displayInfo; + for (int state : supportedStates) { + displayInfo = mLogicalDisplayMapper.getDisplayInfoForStateLocked(state, + displayId); + if (displayInfo != null) { + possibleInfo.add(displayInfo); } } return possibleInfo; diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index ecae8330d532..6331a5dd07b4 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -1163,7 +1163,7 @@ public class DisplayModeDirector { mDefaultRefreshRate = (displayDeviceConfig == null) ? (float) mContext.getResources().getInteger( R.integer.config_defaultRefreshRate) - : (float) displayDeviceConfig.getDefaultRefreshRate(); + : (float) displayDeviceConfig.getDefaultLowRefreshRate(); } public void observe() { @@ -1250,7 +1250,7 @@ public class DisplayModeDirector { defaultPeakRefreshRate = (displayDeviceConfig == null) ? (float) mContext.getResources().getInteger( R.integer.config_defaultPeakRefreshRate) - : (float) displayDeviceConfig.getDefaultPeakRefreshRate(); + : (float) displayDeviceConfig.getDefaultHighRefreshRate(); } mDefaultPeakRefreshRate = defaultPeakRefreshRate; } diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index 778e41820433..17e7340216ff 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -19,6 +19,7 @@ package com.android.server.display; import static android.view.Display.DEFAULT_DISPLAY; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.hardware.devicestate.DeviceStateManager; import android.os.Handler; @@ -28,7 +29,6 @@ import android.os.PowerManager; import android.os.SystemClock; import android.os.SystemProperties; import android.text.TextUtils; -import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; @@ -43,7 +43,6 @@ import com.android.server.display.layout.Layout; import java.io.PrintWriter; import java.util.Arrays; -import java.util.Set; import java.util.function.Consumer; /** @@ -304,58 +303,44 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { } /** - * Returns the set of {@link DisplayInfo} for this device state, only fetching the info that is - * part of the same display group as the provided display id. The DisplayInfo represent the - * logical display layouts possible for the given device state. + * Returns the {@link DisplayInfo} for this device state, indicated by the given display id. The + * DisplayInfo represents the attributes of the indicated display in the layout associated with + * this state. This is used to get display information for various displays in various states; + * e.g. to help apps preload resources for the possible display states. * * @param deviceState the state to query possible layouts for - * @param displayId the display id to apply to all displays within the group - * @param groupId the display group to filter display info for. Must be the same group as - * the display with the provided display id. + * @param displayId the display id to retrieve + * @return {@code null} if no corresponding {@link DisplayInfo} could be found, or the + * {@link DisplayInfo} with a matching display id. */ - public Set<DisplayInfo> getDisplayInfoForStateLocked(int deviceState, int displayId, - int groupId) { - Set<DisplayInfo> displayInfos = new ArraySet<>(); + @Nullable + public DisplayInfo getDisplayInfoForStateLocked(int deviceState, int displayId) { + // Retrieve the layout for this particular state. final Layout layout = mDeviceStateToLayoutMap.get(deviceState); - final int layoutSize = layout.size(); - for (int i = 0; i < layoutSize; i++) { - Layout.Display displayLayout = layout.getAt(i); - if (displayLayout == null) { - continue; - } - - // If the underlying display-device we want to use for this display - // doesn't exist, then skip it. This can happen at startup as display-devices - // trickle in one at a time. When the new display finally shows up, the layout is - // recalculated so that the display is properly added to the current layout. - final DisplayAddress address = displayLayout.getAddress(); - final DisplayDevice device = mDisplayDeviceRepo.getByAddressLocked(address); - if (device == null) { - Slog.w(TAG, "The display device (" + address + "), is not available" - + " for the display state " + deviceState); - continue; - } - - // Find or create the LogicalDisplay to map the DisplayDevice to. - final int logicalDisplayId = displayLayout.getLogicalDisplayId(); - final LogicalDisplay logicalDisplay = getDisplayLocked(logicalDisplayId); - if (logicalDisplay == null) { - Slog.w(TAG, "The logical display (" + address + "), is not available" - + " for the display state " + deviceState); - continue; - } - final DisplayInfo temp = logicalDisplay.getDisplayInfoLocked(); - DisplayInfo displayInfo = new DisplayInfo(temp); - if (displayInfo.displayGroupId != groupId) { - // Ignore any displays not in the provided group. - continue; - } - // A display in the same group can be swapped out at any point, so set the display id - // for all results to the provided display id. - displayInfo.displayId = displayId; - displayInfos.add(displayInfo); + if (layout == null) { + return null; + } + // Retrieve the details of the given display within this layout. + Layout.Display display = layout.getById(displayId); + if (display == null) { + return null; + } + // Retrieve the display info for the display that matches the display id. + final DisplayDevice device = mDisplayDeviceRepo.getByAddressLocked(display.getAddress()); + if (device == null) { + Slog.w(TAG, "The display device (" + display.getAddress() + "), is not available" + + " for the display state " + mDeviceState); + return null; + } + LogicalDisplay logicalDisplay = getDisplayLocked(device, /* includeDisabled= */ true); + if (logicalDisplay == null) { + Slog.w(TAG, "The logical display associated with address (" + display.getAddress() + + "), is not available for the display state " + mDeviceState); + return null; } - return displayInfos; + DisplayInfo displayInfo = new DisplayInfo(logicalDisplay.getDisplayInfoLocked()); + displayInfo.displayId = displayId; + return displayInfo; } public void dumpLocked(PrintWriter pw) { diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 1ea949ede03d..2f818fa10b72 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -123,6 +123,7 @@ import static android.telephony.CarrierConfigManager.KEY_DATA_RAPID_NOTIFICATION import static android.telephony.CarrierConfigManager.KEY_DATA_WARNING_NOTIFICATION_BOOL; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import static com.android.internal.util.ArrayUtils.appendInt; import static com.android.internal.util.XmlUtils.readBooleanAttribute; import static com.android.internal.util.XmlUtils.readIntAttribute; @@ -3148,7 +3149,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. */ - private static NetworkTemplate normalizeTemplate(@NonNull NetworkTemplate template, + @VisibleForTesting(visibility = PRIVATE) + static NetworkTemplate normalizeTemplate(@NonNull NetworkTemplate template, @NonNull List<String[]> mergedList) { // Now there are several types of network which uses Subscriber Id to store network // information. For instance: @@ -3158,6 +3160,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (template.getSubscriberIds().isEmpty()) return template; for (final String[] merged : mergedList) { + // In some rare cases (e.g. b/243015487), merged subscriberId list might contain + // duplicated items. Deduplication for better error handling. + final ArraySet mergedSet = new ArraySet(merged); + if (mergedSet.size() != merged.length) { + Log.wtf(TAG, "Duplicated merged list detected: " + Arrays.toString(merged)); + } // TODO: Handle incompatible subscriberIds if that happens in practice. for (final String subscriberId : template.getSubscriberIds()) { if (com.android.net.module.util.CollectionUtils.contains(merged, subscriberId)) { @@ -3165,7 +3173,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // a template that matches all merged subscribers. return new NetworkTemplate.Builder(template.getMatchRule()) .setWifiNetworkKeys(template.getWifiNetworkKeys()) - .setSubscriberIds(Set.of(merged)) + .setSubscriberIds(mergedSet) .setMeteredness(template.getMeteredness()) .build(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index b7b332621e7f..1ea09849cf61 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3211,6 +3211,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService return isPackageDeviceAdmin(packageName, UserHandle.USER_ALL); } + // TODO(b/261957226): centralise this logic in DPM boolean isPackageDeviceAdmin(String packageName, int userId) { final IDevicePolicyManager dpm = getDevicePolicyManager(); try { @@ -3237,6 +3238,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService if (dpm.packageHasActiveAdmins(packageName, users[i])) { return true; } + if (isDeviceManagementRoleHolder(packageName, users[i])) { + return true; + } } } } catch (RemoteException e) { @@ -3244,6 +3248,24 @@ public class PackageManagerService implements PackageSender, TestUtilityService return false; } + private boolean isDeviceManagementRoleHolder(String packageName, int userId) { + return Objects.equals(packageName, getDevicePolicyManagementRoleHolderPackageName(userId)); + } + + @Nullable + private String getDevicePolicyManagementRoleHolderPackageName(int userId) { + return Binder.withCleanCallingIdentity(() -> { + RoleManager roleManager = mContext.getSystemService(RoleManager.class); + List<String> roleHolders = + roleManager.getRoleHoldersAsUser( + RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, UserHandle.of(userId)); + if (roleHolders.isEmpty()) { + return null; + } + return roleHolders.get(0); + }); + } + /** Returns the device policy manager interface. */ private IDevicePolicyManager getDevicePolicyManager() { if (mDevicePolicyManager == null) { diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 15ba760dbca3..714be185c972 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -41,6 +41,7 @@ import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ComponentInfo; @@ -1133,9 +1134,14 @@ public class PackageManagerServiceUtils { continue; } - final boolean match = comp.getIntents().stream().anyMatch( - f -> IntentResolver.intentMatchesFilter(f.getIntentFilter(), intent, - resolvedType)); + boolean match = false; + for (int j = 0, size = comp.getIntents().size(); j < size; ++j) { + IntentFilter intentFilter = comp.getIntents().get(j).getIntentFilter(); + if (IntentResolver.intentMatchesFilter(intentFilter, intent, resolvedType)) { + match = true; + break; + } + } if (!match) { Slog.w(TAG, "Intent does not match component's intent filter: " + intent); Slog.w(TAG, "Access blocked: " + comp.getComponentName()); diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 2888b9a2d3cc..6c191eb3842d 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -690,7 +690,7 @@ public class TrustManagerService extends SystemService { */ public void lockUser(int userId) { mLockPatternUtils.requireStrongAuth( - StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId); + StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED, userId); try { WindowManagerGlobal.getWindowManagerService().lockNow(null); } catch (RemoteException e) { @@ -2087,7 +2087,7 @@ public class TrustManagerService extends SystemService { if (mStrongAuthTracker.isTrustAllowedForUser(mUserId)) { if (DEBUG) Slog.d(TAG, "Revoking all trust because of trust timeout"); mLockPatternUtils.requireStrongAuth( - mStrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, mUserId); + mStrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED, mUserId); } maybeLockScreen(mUserId); } diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index dd870a8905cc..79a4acf55fef 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -599,6 +599,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub * for display. */ void generateCrop(WallpaperData wallpaper) { + TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG); + t.traceBegin("WPMS.generateCrop"); + generateCropInternal(wallpaper); + t.traceEnd(); + } + + private void generateCropInternal(WallpaperData wallpaper) { boolean success = false; // Only generate crop for default display. diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index cdc8c017b823..e639866a6bab 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -671,7 +671,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private boolean mCurrentLaunchCanTurnScreenOn = true; /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */ - private boolean mLastSurfaceShowing = true; + private boolean mLastSurfaceShowing; /** * The activity is opaque and fills the entire space of this task. @@ -1239,8 +1239,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.println(prefix + "supportsEnterPipOnTaskSwitch: " + supportsEnterPipOnTaskSwitch); } - if (info.getMaxAspectRatio() != 0) { - pw.println(prefix + "maxAspectRatio=" + info.getMaxAspectRatio()); + if (getMaxAspectRatio() != 0) { + pw.println(prefix + "maxAspectRatio=" + getMaxAspectRatio()); } final float minAspectRatio = getMinAspectRatio(); if (minAspectRatio != 0) { @@ -1590,6 +1590,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A newParent.setResumedActivity(this, "onParentChanged"); mImeInsetsFrozenUntilStartInput = false; } + mLetterboxUiController.onActivityParentChanged(newParent); } if (rootTask != null && rootTask.topRunningActivity() == this) { @@ -5499,7 +5500,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // no animation but there will still be a transition set. // We still need to delay hiding the surface such that it // can be synchronized with showing the next surface in the transition. - if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) { + if (!usingShellTransitions && !isVisible() && !delayed + && !displayContent.mAppTransition.isTransitionSet()) { SurfaceControl.openTransaction(); try { forAllWindows(win -> { @@ -7438,6 +7440,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } @Override + boolean showSurfaceOnCreation() { + return false; + } + + @Override void prepareSurfaces() { final boolean show = isVisible() || isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS); @@ -7676,6 +7683,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Configuration.Orientation @Override int getRequestedConfigurationOrientation(boolean forDisplay) { + if (mLetterboxUiController.hasInheritedOrientation()) { + final RootDisplayArea root = getRootDisplayArea(); + if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) { + return ActivityInfo.reverseOrientation( + mLetterboxUiController.getInheritedOrientation()); + } else { + return mLetterboxUiController.getInheritedOrientation(); + } + } if (mOrientation == SCREEN_ORIENTATION_BEHIND && task != null) { // We use Task here because we want to be consistent with what happens in // multi-window mode where other tasks orientations are ignored. @@ -7803,6 +7819,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Nullable CompatDisplayInsets getCompatDisplayInsets() { + if (mLetterboxUiController.hasInheritedLetterboxBehavior()) { + return mLetterboxUiController.getInheritedCompatDisplayInsets(); + } return mCompatDisplayInsets; } @@ -7885,6 +7904,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer. private void updateCompatDisplayInsets() { + if (mLetterboxUiController.hasInheritedLetterboxBehavior()) { + mCompatDisplayInsets = mLetterboxUiController.getInheritedCompatDisplayInsets(); + return; + } if (mCompatDisplayInsets != null || !shouldCreateCompatDisplayInsets()) { // The override configuration is set only once in size compatibility mode. return; @@ -7946,6 +7969,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @Override float getCompatScale() { + if (mLetterboxUiController.hasInheritedLetterboxBehavior()) { + return mLetterboxUiController.getInheritedSizeCompatScale(); + } return hasSizeCompatBounds() ? mSizeCompatScale : super.getCompatScale(); } @@ -8055,6 +8081,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** + * @return The orientation to use to understand if reachability is enabled. + */ + @ActivityInfo.ScreenOrientation + int getOrientationForReachability() { + return mLetterboxUiController.hasInheritedLetterboxBehavior() + ? mLetterboxUiController.getInheritedOrientation() + : getRequestedConfigurationOrientation(); + } + + /** * Returns whether activity bounds are letterboxed. * * <p>Note that letterbox UI may not be shown even when this returns {@code true}. See {@link @@ -8094,6 +8130,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (!ignoreVisibility && !mVisibleRequested) { return APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE; } + // TODO(b/256564921): Investigate if we need new metrics for translucent activities + if (mLetterboxUiController.hasInheritedLetterboxBehavior()) { + return mLetterboxUiController.getInheritedAppCompatState(); + } if (mInSizeCompatModeForBounds) { return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE; } @@ -8564,6 +8604,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } private boolean isInSizeCompatModeForBounds(final Rect appBounds, final Rect containerBounds) { + if (mLetterboxUiController.hasInheritedLetterboxBehavior()) { + // To avoid wrong app behaviour, we decided to disable SCM when a translucent activity + // is letterboxed. + return false; + } final int appWidth = appBounds.width(); final int appHeight = appBounds.height(); final int containerAppWidth = containerBounds.width(); @@ -8584,10 +8629,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // The rest of the condition is that only one side is smaller than the container, but it // still needs to exclude the cases where the size is limited by the fixed aspect ratio. - if (info.getMaxAspectRatio() > 0) { + final float maxAspectRatio = getMaxAspectRatio(); + if (maxAspectRatio > 0) { final float aspectRatio = (0.5f + Math.max(appWidth, appHeight)) / Math.min(appWidth, appHeight); - if (aspectRatio >= info.getMaxAspectRatio()) { + if (aspectRatio >= maxAspectRatio) { // The current size has reached the max aspect ratio. return false; } @@ -8809,7 +8855,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer. private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds, Rect containingBounds, float desiredAspectRatio) { - final float maxAspectRatio = info.getMaxAspectRatio(); + final float maxAspectRatio = getMaxAspectRatio(); final Task rootTask = getRootTask(); final float minAspectRatio = getMinAspectRatio(); final TaskFragment organizedTf = getOrganizedTaskFragment(); @@ -8916,6 +8962,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * Returns the min aspect ratio of this activity. */ float getMinAspectRatio() { + if (mLetterboxUiController.hasInheritedLetterboxBehavior()) { + return mLetterboxUiController.getInheritedMinAspectRatio(); + } if (info.applicationInfo == null) { return info.getMinAspectRatio(); } @@ -8960,11 +9009,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A && parent.getWindowConfiguration().getWindowingMode() == WINDOWING_MODE_FULLSCREEN; } + float getMaxAspectRatio() { + if (mLetterboxUiController.hasInheritedLetterboxBehavior()) { + return mLetterboxUiController.getInheritedMaxAspectRatio(); + } + return info.getMaxAspectRatio(); + } + /** * Returns true if the activity has maximum or minimum aspect ratio. */ private boolean hasFixedAspectRatio() { - return info.getMaxAspectRatio() != 0 || getMinAspectRatio() != 0; + return getMaxAspectRatio() != 0 || getMinAspectRatio() != 0; } /** diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java index c19353cb2676..127a7bf1c9a5 100644 --- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java +++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.Color; +import android.provider.DeviceConfig; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -103,6 +104,10 @@ final class LetterboxConfiguration { final Context mContext; + // Responsible for the persistence of letterbox[Horizontal|Vertical]PositionMultiplier + @NonNull + private final LetterboxConfigurationPersister mLetterboxConfigurationPersister; + // Aspect ratio of letterbox for fixed orientation, values <= // MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO will be ignored. private float mFixedOrientationLetterboxAspectRatio; @@ -165,9 +170,12 @@ final class LetterboxConfiguration { // Whether using split screen aspect ratio as a default aspect ratio for unresizable apps. private boolean mIsSplitScreenAspectRatioForUnresizableAppsEnabled; - // Responsible for the persistence of letterbox[Horizontal|Vertical]PositionMultiplier - @NonNull - private final LetterboxConfigurationPersister mLetterboxConfigurationPersister; + // Whether letterboxing strategy is enabled for translucent activities. If {@value false} + // all the feature is disabled + private boolean mTranslucentLetterboxingEnabled; + + // Allows to enable letterboxing strategy for translucent activities ignoring flags. + private boolean mTranslucentLetterboxingOverrideEnabled; LetterboxConfiguration(Context systemUiContext) { this(systemUiContext, new LetterboxConfigurationPersister(systemUiContext, @@ -206,6 +214,8 @@ final class LetterboxConfiguration { R.dimen.config_letterboxDefaultMinAspectRatioForUnresizableApps)); mIsSplitScreenAspectRatioForUnresizableAppsEnabled = mContext.getResources().getBoolean( R.bool.config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled); + mTranslucentLetterboxingEnabled = mContext.getResources().getBoolean( + R.bool.config_letterboxIsEnabledForTranslucentActivities); mLetterboxConfigurationPersister = letterboxConfigurationPersister; mLetterboxConfigurationPersister.start(); } @@ -817,6 +827,32 @@ final class LetterboxConfiguration { R.bool.config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled); } + boolean isTranslucentLetterboxingEnabled() { + return mTranslucentLetterboxingOverrideEnabled || (mTranslucentLetterboxingEnabled + && isTranslucentLetterboxingAllowed()); + } + + void setTranslucentLetterboxingEnabled(boolean translucentLetterboxingEnabled) { + mTranslucentLetterboxingEnabled = translucentLetterboxingEnabled; + } + + void setTranslucentLetterboxingOverrideEnabled( + boolean translucentLetterboxingOverrideEnabled) { + mTranslucentLetterboxingOverrideEnabled = translucentLetterboxingOverrideEnabled; + setTranslucentLetterboxingEnabled(translucentLetterboxingOverrideEnabled); + } + + /** + * Resets whether we use the constraints override strategy for letterboxing when dealing + * with translucent activities {@link R.bool.config_letterboxIsEnabledForTranslucentActivities}. + */ + void resetTranslucentLetterboxingEnabled() { + final boolean newValue = mContext.getResources().getBoolean( + R.bool.config_letterboxIsEnabledForTranslucentActivities); + setTranslucentLetterboxingEnabled(newValue); + setTranslucentLetterboxingOverrideEnabled(false); + } + /** Calculates a new letterboxPositionForHorizontalReachability value and updates the store */ private void updatePositionForHorizontalReachability( Function<Integer, Integer> newHorizonalPositionFun) { @@ -839,4 +875,9 @@ final class LetterboxConfiguration { nextVerticalPosition); } + // TODO(b/262378106): Cache runtime flag and implement DeviceConfig.OnPropertiesChangedListener + static boolean isTranslucentLetterboxingAllowed() { + return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER, + "enable_translucent_activity_letterbox", false); + } } diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index bcea6f4db1dc..a53a5fc00b0c 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; @@ -27,6 +28,7 @@ import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANG import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT; import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP; import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION; +import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN; import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER; import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM; import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT; @@ -82,13 +84,44 @@ final class LetterboxUiController { private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxUiController" : TAG_ATM; + private static final float UNDEFINED_ASPECT_RATIO = 0f; + private final Point mTmpPoint = new Point(); private final LetterboxConfiguration mLetterboxConfiguration; + private final ActivityRecord mActivityRecord; + /* + * WindowContainerListener responsible to make translucent activities inherit + * constraints from the first opaque activity beneath them. It's null for not + * translucent activities. + */ + @Nullable + private WindowContainerListener mLetterboxConfigListener; + private boolean mShowWallpaperForLetterboxBackground; + // In case of transparent activities we might need to access the aspectRatio of the + // first opaque activity beneath. + private float mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO; + private float mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO; + + @Configuration.Orientation + private int mInheritedOrientation = Configuration.ORIENTATION_UNDEFINED; + + // The app compat state for the opaque activity if any + private int mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN; + + // If true it means that the opaque activity beneath a translucent one is in SizeCompatMode. + private boolean mIsInheritedInSizeCompatMode; + + // This is the SizeCompatScale of the opaque activity beneath a translucent one + private float mInheritedSizeCompatScale; + + // The CompatDisplayInsets of the opaque activity beneath the translucent one. + private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets; + @Nullable private Letterbox mLetterbox; @@ -220,7 +253,9 @@ final class LetterboxUiController { : mActivityRecord.inMultiWindowMode() ? mActivityRecord.getTask().getBounds() : mActivityRecord.getRootTask().getParent().getBounds(); - mLetterbox.layout(spaceToFill, w.getFrame(), mTmpPoint); + final Rect innerFrame = hasInheritedLetterboxBehavior() + ? mActivityRecord.getWindowConfiguration().getBounds() : w.getFrame(); + mLetterbox.layout(spaceToFill, innerFrame, mTmpPoint); } else if (mLetterbox != null) { mLetterbox.hide(); } @@ -305,7 +340,9 @@ final class LetterboxUiController { } private void handleHorizontalDoubleTap(int x) { - if (!isHorizontalReachabilityEnabled() || mActivityRecord.isInTransition()) { + // TODO(b/260857308): Investigate if enabling reachability for translucent activity + if (hasInheritedLetterboxBehavior() || !isHorizontalReachabilityEnabled() + || mActivityRecord.isInTransition()) { return; } @@ -341,7 +378,9 @@ final class LetterboxUiController { } private void handleVerticalDoubleTap(int y) { - if (!isVerticalReachabilityEnabled() || mActivityRecord.isInTransition()) { + // TODO(b/260857308): Investigate if enabling reachability for translucent activity + if (hasInheritedLetterboxBehavior() || !isVerticalReachabilityEnabled() + || mActivityRecord.isInTransition()) { return; } @@ -390,7 +429,7 @@ final class LetterboxUiController { && parentConfiguration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_FULLSCREEN && (parentConfiguration.orientation == ORIENTATION_LANDSCAPE - && mActivityRecord.getRequestedConfigurationOrientation() == ORIENTATION_PORTRAIT); + && mActivityRecord.getOrientationForReachability() == ORIENTATION_PORTRAIT); } private boolean isHorizontalReachabilityEnabled() { @@ -412,7 +451,7 @@ final class LetterboxUiController { && parentConfiguration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_FULLSCREEN && (parentConfiguration.orientation == ORIENTATION_PORTRAIT - && mActivityRecord.getRequestedConfigurationOrientation() == ORIENTATION_LANDSCAPE); + && mActivityRecord.getOrientationForReachability() == ORIENTATION_LANDSCAPE); } private boolean isVerticalReachabilityEnabled() { @@ -576,9 +615,7 @@ final class LetterboxUiController { // Rounded corners should be displayed above the taskbar. bounds.bottom = Math.min(bounds.bottom, getTaskbarInsetsSource(mainWindow).getFrame().top); - if (mActivityRecord.inSizeCompatMode() && mActivityRecord.getCompatScale() < 1.0f) { - bounds.scale(1.0f / mActivityRecord.getCompatScale()); - } + scaleIfNeeded(bounds); } private int getInsetsStateCornerRadius( @@ -788,4 +825,144 @@ final class LetterboxUiController { w.mAttrs.insetsFlags.appearance ); } + + /** + * Handles translucent activities letterboxing inheriting constraints from the + * first opaque activity beneath. + * @param parent The parent container. + */ + void onActivityParentChanged(WindowContainer<?> parent) { + if (!mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) { + return; + } + if (mLetterboxConfigListener != null) { + mLetterboxConfigListener.onRemoved(); + clearInheritedConfig(); + } + // In case mActivityRecord.getCompatDisplayInsets() is not null we don't apply the + // opaque activity constraints because we're expecting the activity is already letterboxed. + if (mActivityRecord.getTask() == null || mActivityRecord.getCompatDisplayInsets() != null + || mActivityRecord.fillsParent()) { + return; + } + final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity( + ActivityRecord::fillsParent, mActivityRecord, false /* includeBoundary */, + true /* traverseTopToBottom */); + if (firstOpaqueActivityBeneath == null + || mActivityRecord.launchedFromUid != firstOpaqueActivityBeneath.getUid()) { + // We skip letterboxing if the translucent activity doesn't have any opaque + // activities beneath of if it's launched from a different user (e.g. notification) + return; + } + inheritConfiguration(firstOpaqueActivityBeneath); + mLetterboxConfigListener = WindowContainer.overrideConfigurationPropagation( + mActivityRecord, firstOpaqueActivityBeneath, + (opaqueConfig, transparentConfig) -> { + final Configuration mutatedConfiguration = new Configuration(); + final Rect parentBounds = parent.getWindowConfiguration().getBounds(); + final Rect bounds = mutatedConfiguration.windowConfiguration.getBounds(); + final Rect letterboxBounds = opaqueConfig.windowConfiguration.getBounds(); + // We cannot use letterboxBounds directly here because the position relies on + // letterboxing. Using letterboxBounds directly, would produce a double offset. + bounds.set(parentBounds.left, parentBounds.top, + parentBounds.left + letterboxBounds.width(), + parentBounds.top + letterboxBounds.height()); + // We need to initialize appBounds to avoid NPE. The actual value will + // be set ahead when resolving the Configuration for the activity. + mutatedConfiguration.windowConfiguration.setAppBounds(new Rect()); + return mutatedConfiguration; + }); + } + + /** + * @return {@code true} if the current activity is translucent with an opaque activity + * beneath. In this case it will inherit bounds, orientation and aspect ratios from + * the first opaque activity beneath. + */ + boolean hasInheritedLetterboxBehavior() { + return mLetterboxConfigListener != null && !mActivityRecord.matchParentBounds(); + } + + /** + * @return {@code true} if the current activity is translucent with an opaque activity + * beneath and needs to inherit its orientation. + */ + boolean hasInheritedOrientation() { + // To force a different orientation, the transparent one needs to have an explicit one + // otherwise the existing one is fine and the actual orientation will depend on the + // bounds. + // To avoid wrong behaviour, we're not forcing orientation for activities with not + // fixed orientation (e.g. permission dialogs). + return hasInheritedLetterboxBehavior() + && mActivityRecord.mOrientation != SCREEN_ORIENTATION_UNSPECIFIED; + } + + float getInheritedMinAspectRatio() { + return mInheritedMinAspectRatio; + } + + float getInheritedMaxAspectRatio() { + return mInheritedMaxAspectRatio; + } + + int getInheritedAppCompatState() { + return mInheritedAppCompatState; + } + + float getInheritedSizeCompatScale() { + return mInheritedSizeCompatScale; + } + + @Configuration.Orientation + int getInheritedOrientation() { + return mInheritedOrientation; + } + + public ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() { + return mInheritedCompatDisplayInsets; + } + + private void inheritConfiguration(ActivityRecord firstOpaque) { + // To avoid wrong behaviour, we're not forcing a specific aspet ratio to activities + // which are not already providing one (e.g. permission dialogs) and presumably also + // not resizable. + if (mActivityRecord.getMinAspectRatio() != UNDEFINED_ASPECT_RATIO) { + mInheritedMinAspectRatio = firstOpaque.getMinAspectRatio(); + } + if (mActivityRecord.getMaxAspectRatio() != UNDEFINED_ASPECT_RATIO) { + mInheritedMaxAspectRatio = firstOpaque.getMaxAspectRatio(); + } + mInheritedOrientation = firstOpaque.getRequestedConfigurationOrientation(); + mInheritedAppCompatState = firstOpaque.getAppCompatState(); + mIsInheritedInSizeCompatMode = firstOpaque.inSizeCompatMode(); + mInheritedSizeCompatScale = firstOpaque.getCompatScale(); + mInheritedCompatDisplayInsets = firstOpaque.getCompatDisplayInsets(); + } + + private void clearInheritedConfig() { + mLetterboxConfigListener = null; + mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO; + mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO; + mInheritedOrientation = Configuration.ORIENTATION_UNDEFINED; + mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN; + mIsInheritedInSizeCompatMode = false; + mInheritedSizeCompatScale = 1f; + mInheritedCompatDisplayInsets = null; + } + + private void scaleIfNeeded(Rect bounds) { + if (boundsNeedToScale()) { + bounds.scale(1.0f / mActivityRecord.getCompatScale()); + } + } + + private boolean boundsNeedToScale() { + if (hasInheritedLetterboxBehavior()) { + return mIsInheritedInSizeCompatMode + && mInheritedSizeCompatScale < 1.0f; + } else { + return mActivityRecord.inSizeCompatMode() + && mActivityRecord.getCompatScale() < 1.0f; + } + } } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index ae4f8947cc86..7a3fd634ebe1 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -2223,7 +2223,8 @@ class TaskFragment extends WindowContainer<WindowContainer> { // task, because they should not be affected by insets. inOutConfig.smallestScreenWidthDp = (int) (0.5f + Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density); - } else if (isEmbedded()) { + } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW + && isEmbeddedWithBoundsOverride()) { // For embedded TFs, the smallest width should be updated. Otherwise, inherit // from the parent task would result in applications loaded wrong resource. inOutConfig.smallestScreenWidthDp = diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 7b16cccb928b..5c893de6b920 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -635,7 +635,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< if (showSurfaceOnCreation()) { getSyncTransaction().show(mSurfaceControl); } - onSurfaceShown(getSyncTransaction()); updateSurfacePositionNonOrganized(); } @@ -687,13 +686,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< scheduleAnimation(); } - /** - * Called when the surface is shown for the first time. - */ - void onSurfaceShown(Transaction t) { - // do nothing - } - // Temp. holders for a chain of containers we are currently processing. private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>(); private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>(); @@ -3946,27 +3938,54 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< unregisterConfigurationChangeListener(listener); } + static void overrideConfigurationPropagation(WindowContainer<?> receiver, + WindowContainer<?> supplier) { + overrideConfigurationPropagation(receiver, supplier, null /* configurationMerger */); + } + /** * Forces the receiver container to always use the configuration of the supplier container as * its requested override configuration. It allows to propagate configuration without changing * the relationship between child and parent. + * + * @param receiver The {@link WindowContainer<?>} which will receive the {@link + * Configuration} result of the merging operation. + * @param supplier The {@link WindowContainer<?>} which provides the initial {@link + * Configuration}. + * @param configurationMerger A {@link ConfigurationMerger} which combines the {@link + * Configuration} of the receiver and the supplier. */ - static void overrideConfigurationPropagation(WindowContainer<?> receiver, - WindowContainer<?> supplier) { + static WindowContainerListener overrideConfigurationPropagation(WindowContainer<?> receiver, + WindowContainer<?> supplier, @Nullable ConfigurationMerger configurationMerger) { final ConfigurationContainerListener listener = new ConfigurationContainerListener() { @Override public void onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig) { - receiver.onRequestedOverrideConfigurationChanged(supplier.getConfiguration()); + final Configuration mergedConfiguration = + configurationMerger != null + ? configurationMerger.merge(mergedOverrideConfig, + receiver.getConfiguration()) + : supplier.getConfiguration(); + receiver.onRequestedOverrideConfigurationChanged(mergedConfiguration); } }; supplier.registerConfigurationChangeListener(listener); - receiver.registerWindowContainerListener(new WindowContainerListener() { + final WindowContainerListener wcListener = new WindowContainerListener() { @Override public void onRemoved() { receiver.unregisterWindowContainerListener(this); supplier.unregisterConfigurationChangeListener(listener); } - }); + }; + receiver.registerWindowContainerListener(wcListener); + return wcListener; + } + + /** + * Abstraction for functions merging two {@link Configuration} objects into one. + */ + @FunctionalInterface + interface ConfigurationMerger { + Configuration merge(Configuration first, Configuration second); } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index b8cf0ad2e774..4e692e2d212a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -963,6 +963,29 @@ public class WindowManagerShellCommand extends ShellCommand { return 0; } + private int runSetTranslucentLetterboxingEnabled(PrintWriter pw) { + String arg = getNextArg(); + final boolean enabled; + switch (arg) { + case "true": + case "1": + enabled = true; + break; + case "false": + case "0": + enabled = false; + break; + default: + getErrPrintWriter().println("Error: expected true, 1, false, 0, but got " + arg); + return -1; + } + + synchronized (mInternal.mGlobalLock) { + mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(enabled); + } + return 0; + } + private int runSetLetterboxStyle(PrintWriter pw) throws RemoteException { if (peekNextArg() == null) { getErrPrintWriter().println("Error: No arguments provided."); @@ -1018,6 +1041,9 @@ public class WindowManagerShellCommand extends ShellCommand { case "--isSplitScreenAspectRatioForUnresizableAppsEnabled": runSetLetterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled(pw); break; + case "--isTranslucentLetterboxingEnabled": + runSetTranslucentLetterboxingEnabled(pw); + break; default: getErrPrintWriter().println( "Error: Unrecognized letterbox style option: " + arg); @@ -1081,6 +1107,9 @@ public class WindowManagerShellCommand extends ShellCommand { mLetterboxConfiguration .getIsSplitScreenAspectRatioForUnresizableAppsEnabled(); break; + case "isTranslucentLetterboxingEnabled": + mLetterboxConfiguration.resetTranslucentLetterboxingEnabled(); + break; default: getErrPrintWriter().println( "Error: Unrecognized letterbox style option: " + arg); @@ -1181,6 +1210,7 @@ public class WindowManagerShellCommand extends ShellCommand { mLetterboxConfiguration.resetDefaultPositionForVerticalReachability(); mLetterboxConfiguration.resetIsEducationEnabled(); mLetterboxConfiguration.resetIsSplitScreenAspectRatioForUnresizableAppsEnabled(); + mLetterboxConfiguration.resetTranslucentLetterboxingEnabled(); } } @@ -1217,7 +1247,6 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println("Is using split screen aspect ratio as aspect ratio for unresizable apps: " + mLetterboxConfiguration .getIsSplitScreenAspectRatioForUnresizableAppsEnabled()); - pw.println("Background type: " + LetterboxConfiguration.letterboxBackgroundTypeToString( mLetterboxConfiguration.getLetterboxBackgroundType())); @@ -1227,6 +1256,12 @@ public class WindowManagerShellCommand extends ShellCommand { + mLetterboxConfiguration.getLetterboxBackgroundWallpaperBlurRadius()); pw.println(" Wallpaper dark scrim alpha: " + mLetterboxConfiguration.getLetterboxBackgroundWallpaperDarkScrimAlpha()); + + if (mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) { + pw.println("Letterboxing for translucent activities: enabled"); + } else { + pw.println("Letterboxing for translucent activities: disabled"); + } } return 0; } @@ -1419,12 +1454,16 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println(" --isSplitScreenAspectRatioForUnresizableAppsEnabled [true|1|false|0]"); pw.println(" Whether using split screen aspect ratio as a default aspect ratio for"); pw.println(" unresizable apps."); + pw.println(" --isTranslucentLetterboxingEnabled [true|1|false|0]"); + pw.println(" Whether letterboxing for translucent activities is enabled."); + pw.println(" reset-letterbox-style [aspectRatio|cornerRadius|backgroundType"); pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha"); pw.println(" |horizontalPositionMultiplier|verticalPositionMultiplier"); pw.println(" |isHorizontalReachabilityEnabled|isVerticalReachabilityEnabled"); - pw.println(" isEducationEnabled||defaultPositionMultiplierForHorizontalReachability"); - pw.println(" ||defaultPositionMultiplierForVerticalReachability]"); + pw.println(" |isEducationEnabled||defaultPositionMultiplierForHorizontalReachability"); + pw.println(" |isTranslucentLetterboxingEnabled"); + pw.println(" |defaultPositionMultiplierForVerticalReachability]"); pw.println(" Resets overrides to default values for specified properties separated"); pw.println(" by space, e.g. 'reset-letterbox-style aspectRatio cornerRadius'."); pw.println(" If no arguments provided, all values will be reset."); diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd index f53a1cfcfb3c..7bc89313c75e 100644 --- a/services/core/xsd/display-device-config/display-device-config.xsd +++ b/services/core/xsd/display-device-config/display-device-config.xsd @@ -44,9 +44,11 @@ </xs:element> <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0" maxOccurs="1"/> - <xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1" /> + <xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1"/> <xs:element type="autoBrightness" name="autoBrightness" minOccurs="0" - maxOccurs="1" /> + maxOccurs="1"/> + <xs:element type="refreshRateConfigs" name="refreshRate" minOccurs="0" + maxOccurs="1"/> <xs:element type="nonNegativeDecimal" name="screenBrightnessRampFastDecrease"> <xs:annotation name="final"/> </xs:element> @@ -324,7 +326,7 @@ <xs:annotation name="final"/> </xs:element> </xs:sequence> - </xs:complexType> + </xs:complexType> <!-- Thresholds for brightness changes. --> <xs:complexType name="thresholds"> @@ -452,4 +454,35 @@ </xs:element> </xs:sequence> </xs:complexType> + + <xs:complexType name="refreshRateConfigs"> + <xs:element name="lowerBlockingZoneConfigs" type="blockingZoneConfig" + minOccurs="0" maxOccurs="1"> + <xs:annotation name="final"/> + </xs:element> + <xs:element name="higherBlockingZoneConfigs" type="blockingZoneConfig" + minOccurs="0" maxOccurs="1"> + <xs:annotation name="final"/> + </xs:element> + </xs:complexType> + + <xs:complexType name="blockingZoneConfig"> + <xs:element name="defaultRefreshRate" type="xs:nonNegativeInteger" + minOccurs="1" maxOccurs="1"> + <xs:annotation name="final"/> + </xs:element> + <xs:element name="blockingZoneThreshold" type="blockingZoneThreshold" + minOccurs="1" maxOccurs="1"> + <xs:annotation name="final"/> + </xs:element> + </xs:complexType> + + <xs:complexType name="blockingZoneThreshold"> + <xs:sequence> + <xs:element name="displayBrightnessPoint" type="displayBrightnessPoint" + minOccurs="1" maxOccurs="unbounded"> + <xs:annotation name="final"/> + </xs:element> + </xs:sequence> + </xs:complexType> </xs:schema> diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt index d89bd7cc9aa2..6276edaf3ebc 100644 --- a/services/core/xsd/display-device-config/schema/current.txt +++ b/services/core/xsd/display-device-config/schema/current.txt @@ -13,6 +13,19 @@ package com.android.server.display.config { method public void setEnabled(boolean); } + public class BlockingZoneConfig { + ctor public BlockingZoneConfig(); + method public final com.android.server.display.config.BlockingZoneThreshold getBlockingZoneThreshold(); + method public final java.math.BigInteger getDefaultRefreshRate(); + method public final void setBlockingZoneThreshold(com.android.server.display.config.BlockingZoneThreshold); + method public final void setDefaultRefreshRate(java.math.BigInteger); + } + + public class BlockingZoneThreshold { + ctor public BlockingZoneThreshold(); + method public final java.util.List<com.android.server.display.config.DisplayBrightnessPoint> getDisplayBrightnessPoint(); + } + public class BrightnessThresholds { ctor public BrightnessThresholds(); method public final com.android.server.display.config.ThresholdPoints getBrightnessThresholdPoints(); @@ -76,6 +89,7 @@ package com.android.server.display.config { method public final com.android.server.display.config.SensorDetails getLightSensor(); method public final com.android.server.display.config.SensorDetails getProxSensor(); method public com.android.server.display.config.DisplayQuirks getQuirks(); + method public com.android.server.display.config.RefreshRateConfigs getRefreshRate(); method @NonNull public final java.math.BigDecimal getScreenBrightnessDefault(); method @NonNull public final com.android.server.display.config.NitsMap getScreenBrightnessMap(); method public final java.math.BigInteger getScreenBrightnessRampDecreaseMaxMillis(); @@ -97,6 +111,7 @@ package com.android.server.display.config { method public final void setLightSensor(com.android.server.display.config.SensorDetails); method public final void setProxSensor(com.android.server.display.config.SensorDetails); method public void setQuirks(com.android.server.display.config.DisplayQuirks); + method public void setRefreshRate(com.android.server.display.config.RefreshRateConfigs); method public final void setScreenBrightnessDefault(@NonNull java.math.BigDecimal); method public final void setScreenBrightnessMap(@NonNull com.android.server.display.config.NitsMap); method public final void setScreenBrightnessRampDecreaseMaxMillis(java.math.BigInteger); @@ -160,6 +175,14 @@ package com.android.server.display.config { method public final void setValue(@NonNull java.math.BigDecimal); } + public class RefreshRateConfigs { + ctor public RefreshRateConfigs(); + method public final com.android.server.display.config.BlockingZoneConfig getHigherBlockingZoneConfigs(); + method public final com.android.server.display.config.BlockingZoneConfig getLowerBlockingZoneConfigs(); + method public final void setHigherBlockingZoneConfigs(com.android.server.display.config.BlockingZoneConfig); + method public final void setLowerBlockingZoneConfigs(com.android.server.display.config.BlockingZoneConfig); + } + public class RefreshRateRange { ctor public RefreshRateRange(); method public final java.math.BigInteger getMaximum(); diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index ed369c016770..82236bfd98e0 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -155,6 +155,18 @@ public class LocalDisplayAdapterTest { when(mMockedResources.getIntArray( com.android.internal.R.array.config_autoBrightnessLevels)) .thenReturn(new int[]{}); + when(mMockedResources.getIntArray( + com.android.internal.R.array.config_brightnessThresholdsOfPeakRefreshRate)) + .thenReturn(new int[]{}); + when(mMockedResources.getIntArray( + com.android.internal.R.array.config_ambientThresholdsOfPeakRefreshRate)) + .thenReturn(new int[]{}); + when(mMockedResources.getIntArray( + com.android.internal.R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate)) + .thenReturn(new int[]{}); + when(mMockedResources.getIntArray( + com.android.internal.R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate)) + .thenReturn(new int[]{}); } @After diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java index 7f341fff514d..6b705aaf9721 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java @@ -150,6 +150,16 @@ public final class DisplayDeviceConfigTest { assertEquals("ProximitySensor123", mDisplayDeviceConfig.getProximitySensor().name); assertEquals("prox_type_1", mDisplayDeviceConfig.getProximitySensor().type); + assertEquals(75, mDisplayDeviceConfig.getDefaultLowRefreshRate()); + assertEquals(90, mDisplayDeviceConfig.getDefaultHighRefreshRate()); + assertArrayEquals(new int[]{45, 55}, + mDisplayDeviceConfig.getLowDisplayBrightnessThresholds()); + assertArrayEquals(new int[]{50, 60}, + mDisplayDeviceConfig.getLowAmbientBrightnessThresholds()); + assertArrayEquals(new int[]{65, 75}, + mDisplayDeviceConfig.getHighDisplayBrightnessThresholds()); + assertArrayEquals(new int[]{70, 80}, + mDisplayDeviceConfig.getHighAmbientBrightnessThresholds()); // Todo(brup): Add asserts for BrightnessThrottlingData, DensityMapping, // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor. @@ -212,9 +222,8 @@ public final class DisplayDeviceConfigTest { mDisplayDeviceConfig.getAmbientDarkeningLevelsIdle(), ZERO_DELTA); assertArrayEquals(new float[]{29, 30, 31}, mDisplayDeviceConfig.getAmbientDarkeningPercentagesIdle(), ZERO_DELTA); - - assertEquals(mDisplayDeviceConfig.getDefaultRefreshRate(), DEFAULT_REFRESH_RATE); - assertEquals(mDisplayDeviceConfig.getDefaultPeakRefreshRate(), DEFAULT_PEAK_REFRESH_RATE); + assertEquals(mDisplayDeviceConfig.getDefaultLowRefreshRate(), DEFAULT_REFRESH_RATE); + assertEquals(mDisplayDeviceConfig.getDefaultHighRefreshRate(), DEFAULT_PEAK_REFRESH_RATE); assertArrayEquals(mDisplayDeviceConfig.getLowDisplayBrightnessThresholds(), LOW_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE); assertArrayEquals(mDisplayDeviceConfig.getLowAmbientBrightnessThresholds(), @@ -426,6 +435,38 @@ public final class DisplayDeviceConfigTest { + "<name>ProximitySensor123</name>\n" + "<type>prox_type_1</type>\n" + "</proxSensor>\n" + + "<refreshRate>\n" + + "<lowerBlockingZoneConfigs>\n" + + "<defaultRefreshRate>75</defaultRefreshRate>\n" + + "<blockingZoneThreshold>\n" + + "<displayBrightnessPoint>\n" + + "<lux>50</lux>\n" + // This number will be rounded to integer when read by the system + + "<nits>45.3</nits>\n" + + "</displayBrightnessPoint>\n" + + "<displayBrightnessPoint>\n" + + "<lux>60</lux>\n" + // This number will be rounded to integer when read by the system + + "<nits>55.2</nits>\n" + + "</displayBrightnessPoint>\n" + + "</blockingZoneThreshold>\n" + + "</lowerBlockingZoneConfigs>\n" + + "<higherBlockingZoneConfigs>\n" + + "<defaultRefreshRate>90</defaultRefreshRate>\n" + + "<blockingZoneThreshold>\n" + + "<displayBrightnessPoint>\n" + + "<lux>70</lux>\n" + // This number will be rounded to integer when read by the system + + "<nits>65.6</nits>\n" + + "</displayBrightnessPoint>\n" + + "<displayBrightnessPoint>\n" + + "<lux>80</lux>\n" + // This number will be rounded to integer when read by the system + + "<nits>75</nits>\n" + + "</displayBrightnessPoint>\n" + + "</blockingZoneThreshold>\n" + + "</higherBlockingZoneConfigs>\n" + + "</refreshRate>\n" + "</displayConfiguration>\n"; } diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java index fb0cdfa9a680..cfea63babac3 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java @@ -1896,8 +1896,8 @@ public class DisplayModeDirectorTest { // Notify that the default display is updated, such that DisplayDeviceConfig has new values DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class); - when(displayDeviceConfig.getDefaultRefreshRate()).thenReturn(50); - when(displayDeviceConfig.getDefaultPeakRefreshRate()).thenReturn(55); + when(displayDeviceConfig.getDefaultLowRefreshRate()).thenReturn(50); + when(displayDeviceConfig.getDefaultHighRefreshRate()).thenReturn(55); when(displayDeviceConfig.getLowDisplayBrightnessThresholds()).thenReturn(new int[]{25}); when(displayDeviceConfig.getLowAmbientBrightnessThresholds()).thenReturn(new int[]{30}); when(displayDeviceConfig.getHighDisplayBrightnessThresholds()).thenReturn(new int[]{210}); diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java index d515fae4afe2..638637d544de 100644 --- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java +++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java @@ -18,10 +18,14 @@ package com.android.server.display; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.DEFAULT_DISPLAY_GROUP; +import static android.view.Display.TYPE_INTERNAL; +import static android.view.Display.TYPE_VIRTUAL; +import static com.android.server.display.DeviceStateToLayoutMap.STATE_DEFAULT; import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED; import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED; import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED; +import static com.android.server.display.DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY; import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED; import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED; @@ -69,7 +73,6 @@ import org.mockito.Spy; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; -import java.util.Set; @SmallTest @Presubmit @@ -151,8 +154,8 @@ public class LogicalDisplayMapperTest { @Test public void testDisplayDeviceAddAndRemove_Internal() { - DisplayDevice device = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + DisplayDevice device = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); // add LogicalDisplay displayAdded = add(device); @@ -173,7 +176,7 @@ public class LogicalDisplayMapperTest { testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_EXTERNAL); testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_WIFI); testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_OVERLAY); - testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_VIRTUAL); + testDisplayDeviceAddAndRemove_NonInternal(TYPE_VIRTUAL); testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_UNKNOWN); // Call the internal test again, just to verify that adding non-internal displays @@ -183,9 +186,9 @@ public class LogicalDisplayMapperTest { @Test public void testDisplayDeviceAdd_TwoInternalOneDefault() { - DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0); - DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800, 0); + DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); LogicalDisplay display1 = add(device1); assertEquals(info(display1).address, info(device1).address); @@ -198,10 +201,10 @@ public class LogicalDisplayMapperTest { @Test public void testDisplayDeviceAdd_TwoInternalBothDefault() { - DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); - DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); LogicalDisplay display1 = add(device1); assertEquals(info(display1).address, info(device1).address); @@ -216,7 +219,7 @@ public class LogicalDisplayMapperTest { @Test public void testDisplayDeviceAddAndRemove_OneExternalDefault() { DisplayDevice device = createDisplayDevice(Display.TYPE_EXTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); // add LogicalDisplay displayAdded = add(device); @@ -234,10 +237,10 @@ public class LogicalDisplayMapperTest { @Test public void testDisplayDeviceAddAndRemove_SwitchDefault() { - DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); - DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); LogicalDisplay display1 = add(device1); assertEquals(info(display1).address, info(device1).address); @@ -263,10 +266,10 @@ public class LogicalDisplayMapperTest { @Test public void testGetDisplayIdsLocked() { - add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); + add(createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); add(createDisplayDevice(Display.TYPE_EXTERNAL, 600, 800, 0)); - add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0)); + add(createDisplayDevice(TYPE_VIRTUAL, 600, 800, 0)); int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID, /* includeDisabled= */ true); @@ -276,71 +279,98 @@ public class LogicalDisplayMapperTest { } @Test - public void testGetDisplayInfoForStateLocked_oneDisplayGroup_internalType() { - add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_INTERNAL, 200, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_INTERNAL, 700, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - - Set<DisplayInfo> displayInfos = mLogicalDisplayMapper.getDisplayInfoForStateLocked( - DeviceStateToLayoutMap.STATE_DEFAULT, DEFAULT_DISPLAY, DEFAULT_DISPLAY_GROUP); - assertThat(displayInfos.size()).isEqualTo(1); - for (DisplayInfo displayInfo : displayInfos) { - assertThat(displayInfo.displayId).isEqualTo(DEFAULT_DISPLAY); - assertThat(displayInfo.displayGroupId).isEqualTo(DEFAULT_DISPLAY_GROUP); - assertThat(displayInfo.logicalWidth).isEqualTo(600); - assertThat(displayInfo.logicalHeight).isEqualTo(800); - } - } + public void testGetDisplayInfoForStateLocked_defaultLayout() { + final DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + final DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 200, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); - @Test - public void testGetDisplayInfoForStateLocked_oneDisplayGroup_differentTypes() { - add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_INTERNAL, 200, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_EXTERNAL, 700, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - - Set<DisplayInfo> displayInfos = mLogicalDisplayMapper.getDisplayInfoForStateLocked( - DeviceStateToLayoutMap.STATE_DEFAULT, DEFAULT_DISPLAY, DEFAULT_DISPLAY_GROUP); - assertThat(displayInfos.size()).isEqualTo(1); - for (DisplayInfo displayInfo : displayInfos) { - assertThat(displayInfo.displayId).isEqualTo(DEFAULT_DISPLAY); - assertThat(displayInfo.displayGroupId).isEqualTo(DEFAULT_DISPLAY_GROUP); - assertThat(displayInfo.logicalWidth).isEqualTo(600); - assertThat(displayInfo.logicalHeight).isEqualTo(800); - } + add(device1); + add(device2); + + Layout layout1 = new Layout(); + layout1.createDisplayLocked(info(device1).address, /* isDefault= */ true, + /* isEnabled= */ true); + layout1.createDisplayLocked(info(device2).address, /* isDefault= */ false, + /* isEnabled= */ true); + when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout1); + assertThat(layout1.size()).isEqualTo(2); + final int logicalId2 = layout1.getByAddress(info(device2).address).getLogicalDisplayId(); + + final DisplayInfo displayInfoDefault = mLogicalDisplayMapper.getDisplayInfoForStateLocked( + STATE_DEFAULT, DEFAULT_DISPLAY); + assertThat(displayInfoDefault.displayId).isEqualTo(DEFAULT_DISPLAY); + assertThat(displayInfoDefault.logicalWidth).isEqualTo(width(device1)); + assertThat(displayInfoDefault.logicalHeight).isEqualTo(height(device1)); + + final DisplayInfo displayInfoOther = mLogicalDisplayMapper.getDisplayInfoForStateLocked( + STATE_DEFAULT, logicalId2); + assertThat(displayInfoOther).isNotNull(); + assertThat(displayInfoOther.displayId).isEqualTo(logicalId2); + assertThat(displayInfoOther.logicalWidth).isEqualTo(width(device2)); + assertThat(displayInfoOther.logicalHeight).isEqualTo(height(device2)); } @Test - public void testGetDisplayInfoForStateLocked_multipleDisplayGroups_defaultGroup() { - add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_INTERNAL, 200, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_VIRTUAL, 700, 800, - DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP)); - - Set<DisplayInfo> displayInfos = mLogicalDisplayMapper.getDisplayInfoForStateLocked( - DeviceStateToLayoutMap.STATE_DEFAULT, DEFAULT_DISPLAY, DEFAULT_DISPLAY_GROUP); - assertThat(displayInfos.size()).isEqualTo(1); - for (DisplayInfo displayInfo : displayInfos) { - assertThat(displayInfo.displayId).isEqualTo(DEFAULT_DISPLAY); - assertThat(displayInfo.displayGroupId).isEqualTo(DEFAULT_DISPLAY_GROUP); - assertThat(displayInfo.logicalWidth).isEqualTo(600); - assertThat(displayInfo.logicalHeight).isEqualTo(800); - } + public void testGetDisplayInfoForStateLocked_multipleLayouts() { + final DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + final DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 200, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + final DisplayDevice device3 = createDisplayDevice(TYPE_VIRTUAL, 700, 800, + DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP); + + add(device1); + add(device2); + add(device3); + + Layout layout1 = new Layout(); + layout1.createDisplayLocked(info(device1).address, + /* isDefault= */ true, /* isEnabled= */ true); + when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout1); + + final int layoutState2 = 2; + Layout layout2 = new Layout(); + layout2.createDisplayLocked(info(device2).address, + /* isDefault= */ false, /* isEnabled= */ true); + // Device3 is the default display. + layout2.createDisplayLocked(info(device3).address, + /* isDefault= */ true, /* isEnabled= */ true); + when(mDeviceStateToLayoutMapSpy.get(layoutState2)).thenReturn(layout2); + assertThat(layout2.size()).isEqualTo(2); + final int logicalId2 = layout2.getByAddress(info(device2).address).getLogicalDisplayId(); + + // Default layout. + final DisplayInfo displayInfoLayout1Default = + mLogicalDisplayMapper.getDisplayInfoForStateLocked( + STATE_DEFAULT, DEFAULT_DISPLAY); + assertThat(displayInfoLayout1Default.displayId).isEqualTo(DEFAULT_DISPLAY); + assertThat(displayInfoLayout1Default.logicalWidth).isEqualTo(width(device1)); + assertThat(displayInfoLayout1Default.logicalHeight).isEqualTo(height(device1)); + + // Second layout, where device3 is the default display. + final DisplayInfo displayInfoLayout2Default = + mLogicalDisplayMapper.getDisplayInfoForStateLocked( + layoutState2, DEFAULT_DISPLAY); + assertThat(displayInfoLayout2Default.displayId).isEqualTo(DEFAULT_DISPLAY); + assertThat(displayInfoLayout2Default.logicalWidth).isEqualTo(width(device3)); + assertThat(displayInfoLayout2Default.logicalHeight).isEqualTo(height(device3)); + + final DisplayInfo displayInfoLayout2Other = + mLogicalDisplayMapper.getDisplayInfoForStateLocked( + layoutState2, logicalId2); + assertThat(displayInfoLayout2Other).isNotNull(); + assertThat(displayInfoLayout2Other.displayId).isEqualTo(logicalId2); + assertThat(displayInfoLayout2Other.logicalWidth).isEqualTo(width(device2)); + assertThat(displayInfoLayout2Other.logicalHeight).isEqualTo(height(device2)); } @Test public void testSingleDisplayGroup() { - LogicalDisplay display1 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0)); - LogicalDisplay display3 = add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0)); + LogicalDisplay display1 = add(createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); + LogicalDisplay display2 = add(createDisplayDevice(TYPE_INTERNAL, 600, 800, 0)); + LogicalDisplay display3 = add(createDisplayDevice(TYPE_VIRTUAL, 600, 800, 0)); assertEquals(DEFAULT_DISPLAY_GROUP, mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1))); @@ -352,12 +382,12 @@ public class LogicalDisplayMapperTest { @Test public void testMultipleDisplayGroups() { - LogicalDisplay display1 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); - LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0)); + LogicalDisplay display1 = add(createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY)); + LogicalDisplay display2 = add(createDisplayDevice(TYPE_INTERNAL, 600, 800, 0)); - TestDisplayDevice device3 = createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, + TestDisplayDevice device3 = createDisplayDevice(TYPE_VIRTUAL, 600, 800, DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP); LogicalDisplay display3 = add(device3); @@ -423,10 +453,10 @@ public class LogicalDisplayMapperTest { @Test public void testDeviceStateLocked() { - DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); - DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); Layout layout = new Layout(); layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address, true, true); @@ -479,13 +509,13 @@ public class LogicalDisplayMapperTest { DisplayAddress displayAddressTwo = new TestUtils.TestDisplayAddress(); DisplayAddress displayAddressThree = new TestUtils.TestDisplayAddress(); - TestDisplayDevice device1 = createDisplayDevice(displayAddressOne, Display.TYPE_INTERNAL, + TestDisplayDevice device1 = createDisplayDevice(displayAddressOne, TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); - TestDisplayDevice device2 = createDisplayDevice(displayAddressTwo, Display.TYPE_INTERNAL, + FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + TestDisplayDevice device2 = createDisplayDevice(displayAddressTwo, TYPE_INTERNAL, 200, 800, DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP); - TestDisplayDevice device3 = createDisplayDevice(displayAddressThree, Display.TYPE_INTERNAL, + TestDisplayDevice device3 = createDisplayDevice(displayAddressThree, TYPE_INTERNAL, 600, 900, DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP); Layout threeDevicesEnabledLayout = new Layout(); @@ -502,7 +532,7 @@ public class LogicalDisplayMapperTest { /* isDefault= */ false, /* isEnabled= */ true); - when(mDeviceStateToLayoutMapSpy.get(DeviceStateToLayoutMap.STATE_DEFAULT)) + when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)) .thenReturn(threeDevicesEnabledLayout); LogicalDisplay display1 = add(device1); @@ -620,6 +650,14 @@ public class LogicalDisplayMapperTest { return device.getDisplayDeviceInfoLocked(); } + private int width(DisplayDevice device) { + return info(device).width; + } + + private int height(DisplayDevice device) { + return info(device).height; + } + private DisplayInfo info(LogicalDisplay display) { return display.getDisplayInfoLocked(); } diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index 07009cb9a207..7c7e2ee53f3c 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -75,6 +75,7 @@ import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOO import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID; import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING; import static com.android.server.net.NetworkPolicyManagerService.UidBlockedState.getEffectiveBlockedReasons; +import static com.android.server.net.NetworkPolicyManagerService.normalizeTemplate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -2059,6 +2060,18 @@ public class NetworkPolicyManagerServiceTest { METERED_NO, actualPolicy.template.getMeteredness()); } + @Test + public void testNormalizeTemplate_duplicatedMergedImsiList() { + final NetworkTemplate template = new NetworkTemplate.Builder(MATCH_CARRIER) + .setSubscriberIds(Set.of(TEST_IMSI)).build(); + final String[] mergedImsiGroup = new String[] {TEST_IMSI, TEST_IMSI}; + final ArrayList<String[]> mergedList = new ArrayList<>(); + mergedList.add(mergedImsiGroup); + // Verify the duplicated items in the merged IMSI list won't crash the system. + final NetworkTemplate result = normalizeTemplate(template, mergedList); + assertEquals(template, result); + } + private String formatBlockedStateError(int uid, int rule, boolean metered, boolean backgroundRestricted) { return String.format( diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index babad4d4d744..94c33f27f651 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -164,6 +164,114 @@ public class SizeCompatTests extends WindowTestsBase { } @Test + public void testApplyStrategyToTranslucentActivities() { + mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); + setUpDisplaySizeWithApp(2000, 1000); + prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); + mActivity.info.setMinAspectRatio(1.2f); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + // Translucent Activity + final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setLaunchedFromUid(mActivity.getUid()) + .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE) + .setMinAspectRatio(1.1f) + .setMaxAspectRatio(3f) + .build(); + doReturn(false).when(translucentActivity).fillsParent(); + mTask.addChild(translucentActivity); + // We check bounds + final Rect opaqueBounds = mActivity.getConfiguration().windowConfiguration.getBounds(); + final Rect translucentRequestedBounds = translucentActivity.getRequestedOverrideBounds(); + assertEquals(opaqueBounds, translucentRequestedBounds); + // We check orientation + final int translucentOrientation = + translucentActivity.getRequestedConfigurationOrientation(); + assertEquals(ORIENTATION_PORTRAIT, translucentOrientation); + // We check aspect ratios + assertEquals(1.2f, translucentActivity.getMinAspectRatio(), 0.00001f); + assertEquals(1.5f, translucentActivity.getMaxAspectRatio(), 0.00001f); + } + + @Test + public void testNotApplyStrategyToTranslucentActivitiesWithDifferentUid() { + mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); + setUpDisplaySizeWithApp(2000, 1000); + prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); + mActivity.info.setMinAspectRatio(1.2f); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + // Translucent Activity + final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE) + .setMinAspectRatio(1.1f) + .setMaxAspectRatio(3f) + .build(); + doReturn(false).when(translucentActivity).fillsParent(); + mTask.addChild(translucentActivity); + // We check bounds + final Rect opaqueBounds = mActivity.getConfiguration().windowConfiguration.getBounds(); + final Rect translucentRequestedBounds = translucentActivity.getRequestedOverrideBounds(); + assertNotEquals(opaqueBounds, translucentRequestedBounds); + } + + @Test + public void testApplyStrategyToMultipleTranslucentActivities() { + mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); + setUpDisplaySizeWithApp(2000, 1000); + prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); + mActivity.info.setMinAspectRatio(1.2f); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + // Translucent Activity + final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setLaunchedFromUid(mActivity.getUid()) + .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE) + .setMinAspectRatio(1.1f) + .setMaxAspectRatio(3f) + .build(); + doReturn(false).when(translucentActivity).fillsParent(); + mTask.addChild(translucentActivity); + // We check bounds + final Rect opaqueBounds = mActivity.getConfiguration().windowConfiguration.getBounds(); + final Rect translucentRequestedBounds = translucentActivity.getRequestedOverrideBounds(); + assertEquals(opaqueBounds, translucentRequestedBounds); + // Launch another translucent activity + final ActivityRecord translucentActivity2 = new ActivityBuilder(mAtm) + .setLaunchedFromUid(mActivity.getUid()) + .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE) + .build(); + doReturn(false).when(translucentActivity2).fillsParent(); + mTask.addChild(translucentActivity2); + // We check bounds + final Rect translucent2RequestedBounds = translucentActivity2.getRequestedOverrideBounds(); + assertEquals(opaqueBounds, translucent2RequestedBounds); + } + + @Test + public void testTranslucentActivitiesDontGoInSizeCompactMode() { + mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); + setUpDisplaySizeWithApp(2800, 1400); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + prepareUnresizable(mActivity, -1f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); + // Rotate to put activity in size compat mode. + rotateDisplay(mActivity.mDisplayContent, ROTATION_90); + assertTrue(mActivity.inSizeCompatMode()); + // Rotate back + rotateDisplay(mActivity.mDisplayContent, ROTATION_0); + assertFalse(mActivity.inSizeCompatMode()); + // We launch a transparent activity + final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setLaunchedFromUid(mActivity.getUid()) + .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) + .build(); + doReturn(true).when(translucentActivity).fillsParent(); + mTask.addChild(translucentActivity); + // It should not be in SCM + assertFalse(translucentActivity.inSizeCompatMode()); + // We rotate again + rotateDisplay(translucentActivity.mDisplayContent, ROTATION_90); + assertFalse(translucentActivity.inSizeCompatMode()); + } + + @Test public void testRestartProcessIfVisible() { setUpDisplaySizeWithApp(1000, 2500); doNothing().when(mSupervisor).scheduleRestartTimeout(mActivity); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java index 11ac929327b9..c8932550d877 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -38,6 +38,7 @@ import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; @@ -98,12 +99,25 @@ public class TaskFragmentTest extends WindowTestsBase { } @Test - public void testOnConfigurationChanged_updateSurface() { - final Rect bounds = new Rect(100, 100, 1100, 1100); + public void testOnConfigurationChanged() { + final Configuration parentConfig = mTaskFragment.getParent().getConfiguration(); + final Rect parentBounds = parentConfig.windowConfiguration.getBounds(); + parentConfig.smallestScreenWidthDp += 10; + final int parentSw = parentConfig.smallestScreenWidthDp; + final Rect bounds = new Rect(parentBounds); + bounds.inset(100, 100); mTaskFragment.setBounds(bounds); + mTaskFragment.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); + // Calculate its own sw with smaller bounds in multi-window mode. + assertNotEquals(parentSw, mTaskFragment.getConfiguration().smallestScreenWidthDp); - verify(mTransaction).setPosition(mLeash, 100, 100); - verify(mTransaction).setWindowCrop(mLeash, 1000, 1000); + verify(mTransaction).setPosition(mLeash, bounds.left, bounds.top); + verify(mTransaction).setWindowCrop(mLeash, bounds.width(), bounds.height()); + + mTaskFragment.setBounds(parentBounds); + mTaskFragment.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + // Inherit parent's sw in fullscreen mode. + assertEquals(parentSw, mTaskFragment.getConfiguration().smallestScreenWidthDp); } @Test diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java index d5eea1f3ff35..b9d2ae6b0d39 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamManager.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java @@ -17,16 +17,23 @@ package com.android.server.voiceinteraction; import static android.app.AppOpsManager.MODE_ALLOWED; +import static android.service.voice.HotwordAudioStream.KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_EMPTY_AUDIO_STREAM_LIST; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_END; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_ILLEGAL_COPY_BUFFER_SIZE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_INTERRUPTED_EXCEPTION; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_NO_PERMISSION; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_START; import static com.android.server.voiceinteraction.HotwordDetectionConnection.DEBUG; import android.annotation.NonNull; import android.app.AppOpsManager; -import android.media.permission.Identity; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.service.voice.HotwordAudioStream; import android.service.voice.HotwordDetectedResult; -import android.util.Pair; import android.util.Slog; import java.io.IOException; @@ -39,21 +46,40 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -final class HotwordAudioStreamManager { +/** + * Copies the audio streams in {@link HotwordDetectedResult}s. This allows the system to manage the + * lifetime of the {@link ParcelFileDescriptor}s and ensures that the flow of data is in the right + * direction from the {@link android.service.voice.HotwordDetectionService} to the client (i.e., the + * voice interactor). + * + * @hide + */ +final class HotwordAudioStreamCopier { - private static final String TAG = "HotwordAudioStreamManager"; + private static final String TAG = "HotwordAudioStreamCopier"; private static final String OP_MESSAGE = "Streaming hotword audio to VoiceInteractionService"; private static final String TASK_ID_PREFIX = "HotwordDetectedResult@"; private static final String THREAD_NAME_PREFIX = "Copy-"; + private static final int DEFAULT_COPY_BUFFER_LENGTH_BYTES = 2_560; + + // Corresponds to the OS pipe capacity in bytes + private static final int MAX_COPY_BUFFER_LENGTH_BYTES = 65_536; private final AppOpsManager mAppOpsManager; - private final Identity mVoiceInteractorIdentity; + private final int mDetectorType; + private final int mVoiceInteractorUid; + private final String mVoiceInteractorPackageName; + private final String mVoiceInteractorAttributionTag; private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); - HotwordAudioStreamManager(@NonNull AppOpsManager appOpsManager, - @NonNull Identity voiceInteractorIdentity) { + HotwordAudioStreamCopier(@NonNull AppOpsManager appOpsManager, int detectorType, + int voiceInteractorUid, @NonNull String voiceInteractorPackageName, + @NonNull String voiceInteractorAttributionTag) { mAppOpsManager = appOpsManager; - mVoiceInteractorIdentity = voiceInteractorIdentity; + mDetectorType = detectorType; + mVoiceInteractorUid = voiceInteractorUid; + mVoiceInteractorPackageName = voiceInteractorPackageName; + mVoiceInteractorAttributionTag = voiceInteractorAttributionTag; } /** @@ -61,7 +87,7 @@ final class HotwordAudioStreamManager { * <p> * The returned {@link HotwordDetectedResult} is identical the one that was passed in, except * that the {@link ParcelFileDescriptor}s within {@link HotwordDetectedResult#getAudioStreams()} - * are replaced with descriptors from pipes managed by {@link HotwordAudioStreamManager}. The + * are replaced with descriptors from pipes managed by {@link HotwordAudioStreamCopier}. The * returned value should be passed on to the client (i.e., the voice interactor). * </p> * @@ -72,12 +98,14 @@ final class HotwordAudioStreamManager { throws IOException { List<HotwordAudioStream> audioStreams = result.getAudioStreams(); if (audioStreams.isEmpty()) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_EMPTY_AUDIO_STREAM_LIST, + mVoiceInteractorUid); return result; } List<HotwordAudioStream> newAudioStreams = new ArrayList<>(audioStreams.size()); - List<Pair<ParcelFileDescriptor, ParcelFileDescriptor>> sourcesAndSinks = new ArrayList<>( - audioStreams.size()); + List<CopyTaskInfo> copyTaskInfos = new ArrayList<>(audioStreams.size()); for (HotwordAudioStream audioStream : audioStreams) { ParcelFileDescriptor[] clientPipe = ParcelFileDescriptor.createReliablePipe(); ParcelFileDescriptor clientAudioSource = clientPipe[0]; @@ -87,74 +115,114 @@ final class HotwordAudioStreamManager { clientAudioSource).build(); newAudioStreams.add(newAudioStream); + int copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES; + PersistableBundle metadata = audioStream.getMetadata(); + if (metadata.containsKey(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES)) { + copyBufferLength = metadata.getInt(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES, -1); + if (copyBufferLength < 1 || copyBufferLength > MAX_COPY_BUFFER_LENGTH_BYTES) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_ILLEGAL_COPY_BUFFER_SIZE, + mVoiceInteractorUid); + Slog.w(TAG, "Attempted to set an invalid copy buffer length (" + + copyBufferLength + ") for: " + audioStream); + copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES; + } else if (DEBUG) { + Slog.i(TAG, "Copy buffer length set to " + copyBufferLength + " for: " + + audioStream); + } + } + ParcelFileDescriptor serviceAudioSource = audioStream.getAudioStreamParcelFileDescriptor(); - sourcesAndSinks.add(new Pair<>(serviceAudioSource, clientAudioSink)); + copyTaskInfos.add(new CopyTaskInfo(serviceAudioSource, clientAudioSink, + copyBufferLength)); } String resultTaskId = TASK_ID_PREFIX + System.identityHashCode(result); - mExecutorService.execute(new HotwordDetectedResultCopyTask(resultTaskId, sourcesAndSinks)); + mExecutorService.execute(new HotwordDetectedResultCopyTask(resultTaskId, copyTaskInfos)); return result.buildUpon().setAudioStreams(newAudioStreams).build(); } + private static class CopyTaskInfo { + private final ParcelFileDescriptor mSource; + private final ParcelFileDescriptor mSink; + private final int mCopyBufferLength; + + CopyTaskInfo(ParcelFileDescriptor source, ParcelFileDescriptor sink, int copyBufferLength) { + mSource = source; + mSink = sink; + mCopyBufferLength = copyBufferLength; + } + } + private class HotwordDetectedResultCopyTask implements Runnable { private final String mResultTaskId; - private final List<Pair<ParcelFileDescriptor, ParcelFileDescriptor>> mSourcesAndSinks; + private final List<CopyTaskInfo> mCopyTaskInfos; private final ExecutorService mExecutorService = Executors.newCachedThreadPool(); - HotwordDetectedResultCopyTask(String resultTaskId, - List<Pair<ParcelFileDescriptor, ParcelFileDescriptor>> sourcesAndSinks) { + HotwordDetectedResultCopyTask(String resultTaskId, List<CopyTaskInfo> copyTaskInfos) { mResultTaskId = resultTaskId; - mSourcesAndSinks = sourcesAndSinks; + mCopyTaskInfos = copyTaskInfos; } @Override public void run() { Thread.currentThread().setName(THREAD_NAME_PREFIX + mResultTaskId); - int size = mSourcesAndSinks.size(); + int size = mCopyTaskInfos.size(); List<SingleAudioStreamCopyTask> tasks = new ArrayList<>(size); for (int i = 0; i < size; i++) { - Pair<ParcelFileDescriptor, ParcelFileDescriptor> sourceAndSink = - mSourcesAndSinks.get(i); - ParcelFileDescriptor serviceAudioSource = sourceAndSink.first; - ParcelFileDescriptor clientAudioSink = sourceAndSink.second; + CopyTaskInfo copyTaskInfo = mCopyTaskInfos.get(i); String streamTaskId = mResultTaskId + "@" + i; - tasks.add(new SingleAudioStreamCopyTask(streamTaskId, serviceAudioSource, - clientAudioSink)); + tasks.add(new SingleAudioStreamCopyTask(streamTaskId, copyTaskInfo.mSource, + copyTaskInfo.mSink, copyTaskInfo.mCopyBufferLength, mDetectorType, + mVoiceInteractorUid)); } if (mAppOpsManager.startOpNoThrow(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, - mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, - mVoiceInteractorIdentity.attributionTag, OP_MESSAGE) == MODE_ALLOWED) { + mVoiceInteractorUid, mVoiceInteractorPackageName, + mVoiceInteractorAttributionTag, OP_MESSAGE) == MODE_ALLOWED) { try { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_START, + mVoiceInteractorUid); // TODO(b/244599891): Set timeout, close after inactivity mExecutorService.invokeAll(tasks); + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_END, + mVoiceInteractorUid); } catch (InterruptedException e) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_INTERRUPTED_EXCEPTION, + mVoiceInteractorUid); Slog.e(TAG, mResultTaskId + ": Task was interrupted", e); bestEffortPropagateError(e.getMessage()); } finally { mAppOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, - mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, - mVoiceInteractorIdentity.attributionTag); + mVoiceInteractorUid, mVoiceInteractorPackageName, + mVoiceInteractorAttributionTag); } } else { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_NO_PERMISSION, + mVoiceInteractorUid); bestEffortPropagateError( - "Failed to obtain RECORD_AUDIO_HOTWORD permission for " - + SoundTriggerSessionPermissionsDecorator.toString( - mVoiceInteractorIdentity)); + "Failed to obtain RECORD_AUDIO_HOTWORD permission for voice interactor with" + + " uid=" + mVoiceInteractorUid + + " packageName=" + mVoiceInteractorPackageName + + " attributionTag=" + mVoiceInteractorAttributionTag); } } private void bestEffortPropagateError(@NonNull String errorMessage) { try { - for (Pair<ParcelFileDescriptor, ParcelFileDescriptor> sourceAndSink : - mSourcesAndSinks) { - ParcelFileDescriptor serviceAudioSource = sourceAndSink.first; - ParcelFileDescriptor clientAudioSink = sourceAndSink.second; - serviceAudioSource.closeWithError(errorMessage); - clientAudioSink.closeWithError(errorMessage); + for (CopyTaskInfo copyTaskInfo : mCopyTaskInfos) { + copyTaskInfo.mSource.closeWithError(errorMessage); + copyTaskInfo.mSink.closeWithError(errorMessage); } + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM, + mVoiceInteractorUid); } catch (IOException e) { Slog.e(TAG, mResultTaskId + ": Failed to propagate error", e); } @@ -162,18 +230,21 @@ final class HotwordAudioStreamManager { } private static class SingleAudioStreamCopyTask implements Callable<Void> { - // TODO: Make this buffer size customizable from updateState() - private static final int COPY_BUFFER_LENGTH = 2_560; - private final String mStreamTaskId; private final ParcelFileDescriptor mAudioSource; private final ParcelFileDescriptor mAudioSink; + private final int mCopyBufferLength; + private final int mDetectorType; + private final int mUid; SingleAudioStreamCopyTask(String streamTaskId, ParcelFileDescriptor audioSource, - ParcelFileDescriptor audioSink) { + ParcelFileDescriptor audioSink, int copyBufferLength, int detectorType, int uid) { mStreamTaskId = streamTaskId; mAudioSource = audioSource; mAudioSink = audioSink; + mCopyBufferLength = copyBufferLength; + mDetectorType = detectorType; + mUid = uid; } @Override @@ -189,7 +260,7 @@ final class HotwordAudioStreamManager { try { fis = new ParcelFileDescriptor.AutoCloseInputStream(mAudioSource); fos = new ParcelFileDescriptor.AutoCloseOutputStream(mAudioSink); - byte[] buffer = new byte[COPY_BUFFER_LENGTH]; + byte[] buffer = new byte[mCopyBufferLength]; while (true) { if (Thread.interrupted()) { Slog.e(TAG, @@ -217,6 +288,8 @@ final class HotwordAudioStreamManager { mAudioSource.closeWithError(e.getMessage()); mAudioSink.closeWithError(e.getMessage()); Slog.e(TAG, mStreamTaskId + ": Failed to copy audio stream", e); + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM, mUid); } finally { if (fis != null) { fis.close(); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 6f7d80caa147..55bf2ab3a0e9 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -170,7 +170,7 @@ final class HotwordDetectionConnection { private final ScheduledExecutorService mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private final AppOpsManager mAppOpsManager; - private final HotwordAudioStreamManager mHotwordAudioStreamManager; + private final HotwordAudioStreamCopier mHotwordAudioStreamCopier; @Nullable private final ScheduledFuture<?> mCancellationTaskFuture; private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false); private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied; @@ -232,8 +232,9 @@ final class HotwordDetectionConnection { mVoiceInteractionServiceUid = voiceInteractionServiceUid; mVoiceInteractorIdentity = voiceInteractorIdentity; mAppOpsManager = mContext.getSystemService(AppOpsManager.class); - mHotwordAudioStreamManager = new HotwordAudioStreamManager(mAppOpsManager, - mVoiceInteractorIdentity); + mHotwordAudioStreamCopier = new HotwordAudioStreamCopier(mAppOpsManager, detectorType, + mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName, + mVoiceInteractorIdentity.attributionTag); mDetectionComponentName = serviceName; mUser = userId; mCallback = callback; @@ -267,7 +268,8 @@ final class HotwordDetectionConnection { synchronized (mLock) { restartProcessLocked(); HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType, - HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE); + HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE, + mVoiceInteractionServiceUid); } }, mReStartPeriodSeconds, mReStartPeriodSeconds, TimeUnit.SECONDS); } @@ -302,7 +304,8 @@ final class HotwordDetectionConnection { // conditions with audio reading in the service. restartProcessLocked(); HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType, - HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__AUDIO_SERVICE_DIED); + HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__AUDIO_SERVICE_DIED, + mVoiceInteractionServiceUid); } } @@ -333,13 +336,14 @@ final class HotwordDetectionConnection { try { mCallback.onStatusReported(status); HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, - initResultMetricsResult); + initResultMetricsResult, mVoiceInteractionServiceUid); } catch (RemoteException e) { // TODO: Add a new atom for RemoteException case, the error doesn't very // correct here Slog.w(TAG, "Failed to report initialization status: " + e); HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, - METRICS_INIT_CALLBACK_STATE_ERROR); + METRICS_INIT_CALLBACK_STATE_ERROR, + mVoiceInteractionServiceUid); } } }; @@ -362,11 +366,12 @@ final class HotwordDetectionConnection { try { mCallback.onStatusReported(INITIALIZATION_STATUS_UNKNOWN); HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, - METRICS_INIT_UNKNOWN_TIMEOUT); + METRICS_INIT_UNKNOWN_TIMEOUT, mVoiceInteractionServiceUid); } catch (RemoteException e) { Slog.w(TAG, "Failed to report initialization status UNKNOWN", e); HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, - METRICS_INIT_CALLBACK_STATE_ERROR); + METRICS_INIT_CALLBACK_STATE_ERROR, + mVoiceInteractionServiceUid); } } else if (err != null) { Slog.w(TAG, "Failed to update state: " + err); @@ -469,12 +474,14 @@ final class HotwordDetectionConnection { synchronized (mLock) { HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED); + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED, + mVoiceInteractionServiceUid); if (!mPerformingSoftwareHotwordDetection) { Slog.i(TAG, "Hotword detection has already completed"); HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - METRICS_KEYPHRASE_TRIGGERED_DETECT_UNEXPECTED_CALLBACK); + METRICS_KEYPHRASE_TRIGGERED_DETECT_UNEXPECTED_CALLBACK, + mVoiceInteractionServiceUid); return; } mPerformingSoftwareHotwordDetection = false; @@ -483,14 +490,15 @@ final class HotwordDetectionConnection { } catch (SecurityException e) { HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION); + METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION, + mVoiceInteractionServiceUid); mSoftwareCallback.onError(); return; } saveProximityValueToBundle(result); HotwordDetectedResult newResult; try { - newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result); + newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result); } catch (IOException e) { // TODO: Write event mSoftwareCallback.onError(); @@ -512,7 +520,8 @@ final class HotwordDetectionConnection { } HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED); + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED, + mVoiceInteractionServiceUid); // onRejected isn't allowed here, and we are not expecting it. } }; @@ -660,12 +669,14 @@ final class HotwordDetectionConnection { } HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED); + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED, + mVoiceInteractionServiceUid); if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignoring #onDetected due to a process restart"); HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - METRICS_KEYPHRASE_TRIGGERED_DETECT_UNEXPECTED_CALLBACK); + METRICS_KEYPHRASE_TRIGGERED_DETECT_UNEXPECTED_CALLBACK, + mVoiceInteractionServiceUid); return; } mValidatingDspTrigger = false; @@ -675,14 +686,15 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Ignoring #onDetected due to a SecurityException", e); HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION); + METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION, + mVoiceInteractionServiceUid); externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION); return; } saveProximityValueToBundle(result); HotwordDetectedResult newResult; try { - newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result); + newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result); } catch (IOException e) { // TODO: Write event externalCallback.onError(CALLBACK_ONDETECTED_STREAM_COPY_ERROR); @@ -708,12 +720,14 @@ final class HotwordDetectionConnection { } HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED); + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED, + mVoiceInteractionServiceUid); if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignoring #onRejected due to a process restart"); HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - METRICS_KEYPHRASE_TRIGGERED_REJECT_UNEXPECTED_CALLBACK); + METRICS_KEYPHRASE_TRIGGERED_REJECT_UNEXPECTED_CALLBACK, + mVoiceInteractionServiceUid); return; } mValidatingDspTrigger = false; @@ -727,21 +741,20 @@ final class HotwordDetectionConnection { synchronized (mLock) { mValidatingDspTrigger = true; - mRemoteHotwordDetectionService.run( - service -> { - // TODO: avoid allocate every time - mCancellationKeyPhraseDetectionFuture = mScheduledExecutorService.schedule( - () -> HotwordMetricsLogger - .writeKeyphraseTriggerEvent(mDetectorType, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_TIMEOUT), - VALIDATION_TIMEOUT_MILLIS, - TimeUnit.MILLISECONDS); - service.detectFromDspSource( - recognitionEvent, - recognitionEvent.getCaptureFormat(), - VALIDATION_TIMEOUT_MILLIS, - internalCallback); - }); + mRemoteHotwordDetectionService.run(service -> { + // TODO: avoid allocate every time + mCancellationKeyPhraseDetectionFuture = mScheduledExecutorService.schedule( + () -> HotwordMetricsLogger.writeKeyphraseTriggerEvent(mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_TIMEOUT, + mVoiceInteractionServiceUid), + VALIDATION_TIMEOUT_MILLIS, + TimeUnit.MILLISECONDS); + service.detectFromDspSource( + recognitionEvent, + recognitionEvent.getCaptureFormat(), + VALIDATION_TIMEOUT_MILLIS, + internalCallback); + }); } } @@ -789,7 +802,8 @@ final class HotwordDetectionConnection { mCallback.onRejected(new HotwordRejectedResult.Builder().build()); HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED_FROM_RESTART); + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED_FROM_RESTART, + mVoiceInteractionServiceUid); } catch (RemoteException e) { Slog.w(TAG, "Failed to call #rejected"); } @@ -835,11 +849,13 @@ final class HotwordDetectionConnection { private SoundTrigger.KeyphraseRecognitionEvent mRecognitionEvent; private final HotwordDetectionConnection mHotwordDetectionConnection; private final IHotwordRecognitionStatusCallback mExternalCallback; + private final int mVoiceInteractionServiceUid; SoundTriggerCallback(IHotwordRecognitionStatusCallback callback, - HotwordDetectionConnection connection) { + HotwordDetectionConnection connection, int uid) { mHotwordDetectionConnection = connection; mExternalCallback = callback; + mVoiceInteractionServiceUid = uid; } @Override @@ -852,14 +868,16 @@ final class HotwordDetectionConnection { if (useHotwordDetectionService) { HotwordMetricsLogger.writeKeyphraseTriggerEvent( HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER); + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER, + mVoiceInteractionServiceUid); mRecognitionEvent = recognitionEvent; mHotwordDetectionConnection.detectFromDspSource( recognitionEvent, mExternalCallback); } else { HotwordMetricsLogger.writeKeyphraseTriggerEvent( HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER); + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER, + mVoiceInteractionServiceUid); mExternalCallback.onKeyphraseDetected(recognitionEvent, null); } } @@ -1014,7 +1032,7 @@ final class HotwordDetectionConnection { HotwordDetectedResult newResult; try { newResult = - mHotwordAudioStreamManager.startCopyingAudioStreams( + mHotwordAudioStreamCopier.startCopyingAudioStreams( triggerResult); } catch (IOException e) { // TODO: Write event diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java index 940aed34b7fb..61c18be6f133 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java @@ -64,28 +64,28 @@ public final class HotwordMetricsLogger { /** * Logs information related to hotword detection service init result. */ - public static void writeServiceInitResultEvent(int detectorType, int result) { + public static void writeServiceInitResultEvent(int detectorType, int result, int uid) { int metricsDetectorType = getInitMetricsDetectorType(detectorType); FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED, - metricsDetectorType, result); + metricsDetectorType, result, uid); } /** * Logs information related to hotword detection service restarting. */ - public static void writeServiceRestartEvent(int detectorType, int reason) { + public static void writeServiceRestartEvent(int detectorType, int reason, int uid) { int metricsDetectorType = getRestartMetricsDetectorType(detectorType); FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED, - metricsDetectorType, reason); + metricsDetectorType, reason, uid); } /** * Logs information related to keyphrase trigger. */ - public static void writeKeyphraseTriggerEvent(int detectorType, int result) { + public static void writeKeyphraseTriggerEvent(int detectorType, int result, int uid) { int metricsDetectorType = getKeyphraseMetricsDetectorType(detectorType); FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED, - metricsDetectorType, result); + metricsDetectorType, result, uid); } /** diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index f90fbb249f5d..c4f341e951da 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -711,7 +711,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne Slog.d(TAG, "createSoundTriggerCallbackLocked"); } return new HotwordDetectionConnection.SoundTriggerCallback(callback, - mHotwordDetectionConnection); + mHotwordDetectionConnection, mInfo.getServiceInfo().applicationInfo.uid); } private static ServiceInfo getServiceInfoLocked(@NonNull ComponentName componentName, @@ -880,5 +880,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne @Override public void onSessionHidden(VoiceInteractionSessionConnection connection) { mServiceStub.onSessionHidden(); + // Notifies visibility change here can cause duplicate events, it is added to make sure + // client always get the callback even if session is unexpectedly closed. + mServiceStub.setSessionWindowVisible(connection.mToken, false); } } |