diff options
493 files changed, 7374 insertions, 4925 deletions
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 22a1a47d3d0a..d6f44e60eb0c 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -325,6 +325,13 @@ public class ActivityOptions extends ComponentOptions { "android:activity.applyMultipleTaskFlagForShortcut"; /** + * Indicates to apply {@link Intent#FLAG_ACTIVITY_NO_USER_ACTION} to the launching shortcut. + * @hide + */ + private static final String KEY_APPLY_NO_USER_ACTION_FLAG_FOR_SHORTCUT = + "android:activity.applyNoUserActionFlagForShortcut"; + + /** * For Activity transitions, the calling Activity's TransitionListener used to * notify the called Activity when the shared element and the exit transitions * complete. @@ -457,6 +464,7 @@ public class ActivityOptions extends ComponentOptions { private boolean mDisallowEnterPictureInPictureWhileLaunching; private boolean mApplyActivityFlagsForBubbles; private boolean mApplyMultipleTaskFlagForShortcut; + private boolean mApplyNoUserActionFlagForShortcut; private boolean mTaskAlwaysOnTop; private boolean mTaskOverlay; private boolean mTaskOverlayCanResume; @@ -1256,6 +1264,8 @@ public class ActivityOptions extends ComponentOptions { KEY_APPLY_ACTIVITY_FLAGS_FOR_BUBBLES, false); mApplyMultipleTaskFlagForShortcut = opts.getBoolean( KEY_APPLY_MULTIPLE_TASK_FLAG_FOR_SHORTCUT, false); + mApplyNoUserActionFlagForShortcut = opts.getBoolean( + KEY_APPLY_NO_USER_ACTION_FLAG_FOR_SHORTCUT, false); if (opts.containsKey(KEY_ANIM_SPECS)) { Parcelable[] specs = opts.getParcelableArray(KEY_ANIM_SPECS); mAnimSpecs = new AppTransitionAnimationSpec[specs.length]; @@ -1835,6 +1845,16 @@ public class ActivityOptions extends ComponentOptions { return mApplyMultipleTaskFlagForShortcut; } + /** @hide */ + public void setApplyNoUserActionFlagForShortcut(boolean apply) { + mApplyNoUserActionFlagForShortcut = apply; + } + + /** @hide */ + public boolean isApplyNoUserActionFlagForShortcut() { + return mApplyNoUserActionFlagForShortcut; + } + /** * Sets a launch cookie that can be used to track the activity and task that are launch as a * result of this option. If the launched activity is a trampoline that starts another activity @@ -2167,6 +2187,9 @@ public class ActivityOptions extends ComponentOptions { b.putBoolean(KEY_APPLY_MULTIPLE_TASK_FLAG_FOR_SHORTCUT, mApplyMultipleTaskFlagForShortcut); } + if (mApplyNoUserActionFlagForShortcut) { + b.putBoolean(KEY_APPLY_NO_USER_ACTION_FLAG_FOR_SHORTCUT, true); + } if (mAnimSpecs != null) { b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs); } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index bab20615cf77..097f6222f7a8 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -6638,6 +6638,13 @@ public class DevicePolicyManager { public static final int KEYGUARD_DISABLE_IRIS = 1 << 8; /** + * Disable all keyguard shortcuts. + * + * @hide + */ + public static final int KEYGUARD_DISABLE_SHORTCUTS_ALL = 1 << 9; + + /** * NOTE: Please remember to update the DevicePolicyManagerTest's testKeyguardDisabledFeatures * CTS test when adding to the list above. */ @@ -6680,7 +6687,8 @@ public class DevicePolicyManager { */ public static final int ORG_OWNED_PROFILE_KEYGUARD_FEATURES_PARENT_ONLY = DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA - | DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS; + | DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS + | DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL; /** * Keyguard features that when set on a normal or organization-owned managed profile, have diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ce29c731221f..10e1633b22d7 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9922,7 +9922,7 @@ public final class Settings { /** * If active unlock triggers on unlock intents, then also request active unlock on - * these wake-up reasons. See PowerManager.WakeReason for value mappings. + * these wake-up reasons. See {@link PowerManager.WakeReason} for value mappings. * WakeReasons should be separated by a pipe. For example: "0|3" or "0". If this * setting should be disabled, then this should be set to an empty string. A null value * will use the system default value (WAKE_REASON_UNFOLD_DEVICE). @@ -9932,6 +9932,17 @@ public final class Settings { "active_unlock_wakeups_considered_unlock_intents"; /** + * If active unlock triggers and succeeds on these wakeups, force dismiss keyguard on + * these wake reasons. See {@link PowerManager#WakeReason} for value mappings. + * WakeReasons should be separated by a pipe. For example: "0|3" or "0". If this + * setting should be disabled, then this should be set to an empty string. A null value + * will use the system default value (WAKE_REASON_UNFOLD_DEVICE). + * @hide + */ + public static final String ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD = + "active_unlock_wakeups_to_force_dismiss_keyguard"; + + /** * Whether the assist gesture should be enabled. * * @hide diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 2d1a41e92a99..e27af17ebc3d 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -170,6 +170,7 @@ public abstract class WallpaperService extends Service { Float.NEGATIVE_INFINITY); private static final int NOTIFY_COLORS_RATE_LIMIT_MS = 1000; + private static final int PROCESS_LOCAL_COLORS_INTERVAL_MS = 1000; private static final boolean ENABLE_WALLPAPER_DIMMING = SystemProperties.getBoolean("persist.debug.enable_wallpaper_dimming", true); @@ -275,9 +276,13 @@ public abstract class WallpaperService extends Service { MotionEvent mPendingMove; boolean mIsInAmbientMode; - // Needed for throttling onComputeColors. + // used to throttle onComputeColors private long mLastColorInvalidation; private final Runnable mNotifyColorsChanged = this::notifyColorsChanged; + + // used to throttle processLocalColors + private long mLastProcessLocalColorsTimestamp; + private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false); private final Supplier<Long> mClockFunction; private final Handler mHandler; @@ -1591,7 +1596,26 @@ public abstract class WallpaperService extends Service { processLocalColors(xOffset, xOffsetStep); } + /** + * Thread-safe util to call {@link #processLocalColorsInternal} with a minimum interval of + * {@link #PROCESS_LOCAL_COLORS_INTERVAL_MS} between two calls. + */ private void processLocalColors(float xOffset, float xOffsetStep) { + if (mProcessLocalColorsPending.compareAndSet(false, true)) { + final long now = mClockFunction.get(); + final long timeSinceLastColorProcess = now - mLastProcessLocalColorsTimestamp; + final long timeToWait = Math.max(0, + PROCESS_LOCAL_COLORS_INTERVAL_MS - timeSinceLastColorProcess); + + mHandler.postDelayed(() -> { + mLastProcessLocalColorsTimestamp = now + timeToWait; + mProcessLocalColorsPending.set(false); + processLocalColorsInternal(xOffset, xOffsetStep); + }, timeToWait); + } + } + + private void processLocalColorsInternal(float xOffset, float xOffsetStep) { // implemented by the wallpaper if (supportsLocalColorExtraction()) return; if (DEBUG) { @@ -1625,40 +1649,39 @@ public abstract class WallpaperService extends Service { float finalXOffsetStep = xOffsetStep; float finalXOffset = xOffset; - mHandler.post(() -> { - Trace.beginSection("WallpaperService#processLocalColors"); - resetWindowPages(); - int xPage = xCurrentPage; - EngineWindowPage current; - if (mWindowPages.length == 0 || (mWindowPages.length != xPages)) { - mWindowPages = new EngineWindowPage[xPages]; - initWindowPages(mWindowPages, finalXOffsetStep); - } - if (mLocalColorsToAdd.size() != 0) { - for (RectF colorArea : mLocalColorsToAdd) { - if (!isValid(colorArea)) continue; - mLocalColorAreas.add(colorArea); - int colorPage = getRectFPage(colorArea, finalXOffsetStep); - EngineWindowPage currentPage = mWindowPages[colorPage]; - currentPage.setLastUpdateTime(0); - currentPage.removeColor(colorArea); - } - mLocalColorsToAdd.clear(); + + Trace.beginSection("WallpaperService#processLocalColors"); + resetWindowPages(); + int xPage = xCurrentPage; + EngineWindowPage current; + if (mWindowPages.length == 0 || (mWindowPages.length != xPages)) { + mWindowPages = new EngineWindowPage[xPages]; + initWindowPages(mWindowPages, finalXOffsetStep); + } + if (mLocalColorsToAdd.size() != 0) { + for (RectF colorArea : mLocalColorsToAdd) { + if (!isValid(colorArea)) continue; + mLocalColorAreas.add(colorArea); + int colorPage = getRectFPage(colorArea, finalXOffsetStep); + EngineWindowPage currentPage = mWindowPages[colorPage]; + currentPage.setLastUpdateTime(0); + currentPage.removeColor(colorArea); } - if (xPage >= mWindowPages.length) { - if (DEBUG) { - Log.e(TAG, "error xPage >= mWindowPages.length page: " + xPage); - Log.e(TAG, "error on page " + xPage + " out of " + xPages); - Log.e(TAG, - "error on xOffsetStep " + finalXOffsetStep - + " xOffset " + finalXOffset); - } - xPage = mWindowPages.length - 1; + mLocalColorsToAdd.clear(); + } + if (xPage >= mWindowPages.length) { + if (DEBUG) { + Log.e(TAG, "error xPage >= mWindowPages.length page: " + xPage); + Log.e(TAG, "error on page " + xPage + " out of " + xPages); + Log.e(TAG, + "error on xOffsetStep " + finalXOffsetStep + + " xOffset " + finalXOffset); } - current = mWindowPages[xPage]; - updatePage(current, xPage, xPages, finalXOffsetStep); - Trace.endSection(); - }); + xPage = mWindowPages.length - 1; + } + current = mWindowPages[xPage]; + updatePage(current, xPage, xPages, finalXOffsetStep); + Trace.endSection(); } private void initWindowPages(EngineWindowPage[] windowPages, float step) { diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index b9373be76b9a..3303c0e73e07 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -573,13 +573,6 @@ public final class SystemUiDeviceConfigFlags { public static final String PERSISTS_WIDGET_PROVIDER_INFO = "persists_widget_provider_info"; /** - * (boolean) Whether the clipboard overlay shows an edit button (as opposed to requiring tapping - * the preview to send an edit intent). - */ - public static final String CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON = - "clipboard_overlay_show_edit_button"; - - /** * (boolean) Whether to show smart chips (based on TextClassifier) in the clipboard overlay. */ public static final String CLIPBOARD_OVERLAY_SHOW_ACTIONS = "clipboard_overlay_show_actions"; diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index fcfdd956ddb0..7372a7ecfef7 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebare vasvang wat op die toestel se vingerafdruksensor uitgevoer word."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Neem skermkiekie"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan \'n skermkiekie neem."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"deaktiveer of verander statusbalk"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Laat die program toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"wees die statusbalk"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index a5619fd1e011..3310cec48579 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"በመሣሪያው የጣት አሻራ ዳሳሽ ላይ የተከናወኑ የጣት ምልክቶችን መያዝ ይችላል።"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ቅጽበታዊ ገጽ እይታን ያነሳል"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"የማሳያው ቅጽበታዊ ገጽ እይታን ማንሳት ይችላል።"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"የሁኔቴ አሞሌ አቦዝን ወይም ቀይር"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"የሁኔታ አሞሌ መሆን"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 1aba35a30e55..980986e976ba 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -346,6 +346,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"يمكن أن تلتقط الإيماءات من أداة استشعار بصمة الإصبع في الجهاز."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"أخذ لقطة شاشة"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"يمكن أخذ لقطة شاشة."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"إيقاف شريط الحالة أو تعديله"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"للسماح للتطبيق بإيقاف شريط الحالة أو إضافة رموز نظام وإزالتها."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"العمل كشريط للحالة"</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 38ec792a6b8b..77f230505552 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইচটোৰ ফিংগাৰপ্ৰিণ্ট ছেন্সৰত দিয়া নিৰ্দেশ বুজিব পাৰে।"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্ৰীনশ্বট লওক"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিছপ্লে’খনৰ এটা স্ক্ৰীনশ্বট ল\'ব পাৰে।"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"স্থিতি দণ্ড অক্ষম কৰক বা সলনি কৰক"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"স্থিতি দণ্ড অক্ষম কৰিবলৈ বা ছিষ্টেম আইকন আঁতৰাবলৈ এপ্টোক অনুমতি দিয়ে।"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দণ্ড হ\'ব পাৰে"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index d2359c742760..534f1a0e9feb 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazların barmaq izi sensorunda olan işarələri əldə edə bilər."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran şəkli çəkin"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran şəkli çəkilə bilər."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"status panelini deaktivləşdir və ya dəyişdir"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"status paneli edin"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 4a7a235c2fc6..ae8c663fecd6 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Može da registruje pokrete na senzoru za otisak prsta na uređaju."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Napravi snimak ekrana"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može da napravi snimak ekrana."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmena statusne trake"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji da onemogući statusnu traku ili da dodaje i uklanja sistemske ikone."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"funkcionisanje kao statusna traka"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 24d799082777..85bd8f9c871f 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -344,6 +344,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зрабіць здымак экрана"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Можна зрабіць здымак экрана."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"адключаць ці змяняць радок стану"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"быць панэллю стану"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 164040f6ca38..424f2cfafe2b 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да улавя жестовете, извършени върху сензора за отпечатъци на устройството."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Създаване на екранна снимка"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да създава екранни снимки."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"деактивиране или промяна на лентата на състоянието"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"изпълняване на ролята на лента на състоянието"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index b0a9467813d2..cc1e61618458 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইসের আঙ্গুলের ছাপের সেন্সরের উপরে ইঙ্গিত করলে বুঝতে পারে।"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্রিনশট নিন"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিসপ্লের একটি স্ক্রিনশট নিতে পারেন।"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"স্ট্যাটাস বার নিষ্ক্রিয় অথবা সংশোধন করে"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"অ্যাপ্লিকেশনকে স্ট্যাটাস বার অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দন্ডে থাকুন"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index ec381a559dcb..34b20468383a 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -343,6 +343,7 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Može zabilježiti pokrete na senzoru za otisak prsta uređaja."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"praviti snimke ekrana"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može napraviti snimak ekrana."</string> + <string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili mijenjanje statusne trake"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji onemogućavanje statusne trake ili dodavanje i uklanjanje sistemskih ikona."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"funkcioniranje u vidu statusne trake"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 4cf938470ea0..4744f440ebb4 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pot capturar els gestos fets en el sensor d\'empremtes digitals del dispositiu."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fer una captura de pantalla"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pot fer una captura de la pantalla."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra d\'estat"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"aparèixer a la barra d\'estat"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index a04b34aa206b..99686911539b 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -344,6 +344,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dokáže rozpoznat gesta zadaná na snímači otisků prstů."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pořídit snímek obrazovky"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Může pořídit snímek obrazovky."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"zakázání či změny stavového řádku"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vydávání se za stavový řádek"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 0e17b9ab4831..7b04bc98120a 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan registrere bevægelser, der foretages på enhedens fingeraftrykssensor."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tag screenshot"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan tage et screenshot af skærmen."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller redigere statuslinje"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vær statusbjælken"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 9b416bc2b886..7b78645fd4c1 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Erfasst Touch-Gesten auf dem Fingerabdrucksensor des Geräts."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot erstellen"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Es kann ein Screenshot des Displays erstellt werden."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"Statusleiste deaktivieren oder ändern"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"Statusleiste darstellen"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 8ab0345233c1..93128aa9ad7c 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικού αποτυπώματος της συσκευής."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Λήψη στιγμιότυπου οθόνης"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Μπορεί να τραβήξει στιγμιότυπο της οθόνης."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ορίζεται ως γραμμή κατάστασης"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index e96b543d248e..d1da0fb1cf78 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -342,6 +342,7 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> + <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 7d455c7a31e4..8c6285c5ca53 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -342,6 +342,7 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> + <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 0ee88ad9439a..861393f0d105 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -342,6 +342,7 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> + <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 68cbfa8499d4..a0a9436c86db 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -342,6 +342,7 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> + <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index b8767b7bcca3..b3551cfa8cc9 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -342,6 +342,7 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string> + <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 2f510555e883..817f00ea41ec 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Capturará los gestos que se hacen en el sensor de huellas dactilares del dispositivo."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tomar captura de pantalla"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede tomar capturas de pantalla."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra de estado"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 29e8abf44a6b..ba30d42619e8 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Puede capturar los gestos realizados en el sensor de huellas digitales del dispositivo."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Hacer captura"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede hacer capturas de la pantalla."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"inhabilitar o modificar la barra de estado"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 9178aff1d6b6..18539dfd2eb1 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Teil on võimalik jäädvustada seadme sõrmejäljeanduril tehtud liigutused."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Jäädvusta ekraanipilt"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Saab jäädvustada ekraanipildi."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"keela või muuda olekuriba"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"olekuribana kuvamine"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index fc7a86e21f20..858b656d930c 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Gailuaren hatz-marken sentsorean egindako keinuak atzeman ditzake."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pantaila-argazkiak atera."</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pantaila-argazkiak atera ditzake."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"desgaitu edo aldatu egoera-barra"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"bihurtu egoera-barra"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 26d1d4bbb366..5b5d5e4b57b1 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"میتواند اشارههای اجراشده روی حسگر اثرانگشت دستگاه را ثبت کند."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"گرفتن نماگرفت"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"میتواند از نمایشگر نماگرفت بگیرد."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"غیرفعال کردن یا تغییر نوار وضعیت"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"به برنامه اجازه میدهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"نوار وضعیت باشد"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 5f27e36d7e18..e2b8fcc8dde7 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Voi tallentaa laitteen sormenjälkitunnistimelle tehtyjä eleitä."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ota kuvakaappaus"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Voi ottaa kuvakaappauksen näytöstä."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"sijaita tilapalkissa"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 6ca95b3281e5..3e29326d91eb 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut capturer des gestes effectués sur le capteur d\'empreintes digitales de l\'appareil."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre une capture de l\'écran."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"désactiver ou modifier la barre d\'état"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"servir de barre d\'état"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 815ae1be8dc1..c5bf6a945775 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut enregistrer des gestes effectués sur le lecteur d\'empreinte digitale de l\'appareil."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Prendre une capture d\'écran"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Peut prendre des captures d\'écran."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"Désactivation ou modification de la barre d\'état"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"remplacer la barre d\'état"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 5576f42cda4c..b89bd3f0c40e 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode rexistrar os xestos realizados no sensor de impresión dixital do dispositivo."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Facer captura de pantalla"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode facer capturas de pantalla."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"desactivar ou modificar a barra de estado"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite á aplicación desactivar a barra de estado ou engadir e quitar as iconas do sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"actuar como a barra de estado"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 2665731059e6..c77502178ac7 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ડિવાઇસના ફિંગરપ્રિન્ટ સેન્સર પર કરવામાં આવેલા સંકેતો કૅપ્ચર કરી શકે છે."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"સ્ક્રીનશૉટ લો"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ડિસ્પ્લેનો સ્ક્રીનશૉટ લઈ શકે છે."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"સ્ટેટસ બારને અક્ષમ કરો અથવા તેમાં ફેરફાર કરો"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ઍપ્લિકેશનને સ્ટેટસ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"સ્ટેટસ બારમાં બતાવો"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index b17eb42371ae..1951a38804e9 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिवाइस के फ़िंगरप्रिंट सेंसर पर किए गए हाथ के जेस्चर कैप्चर किए जा सकते हैं."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट लें"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिसप्ले का स्क्रीनशॉट लिया जा सकता है."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार को अक्षम करें या बदलें"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ऐप को, स्टेटस बार को बंद करने या सिस्टम आइकॉन को जोड़ने और निकालने की अनुमति देता है."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार को रहने दें"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 0b0b8fe43917..f380cb49dcbb 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -343,6 +343,7 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Može snimati pokrete izvršene na senzoru otiska prsta na uređaju."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Snimi zaslon"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Možete napraviti snimku zaslona."</string> + <string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmjena trake statusa"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikaciji omogućuje onemogućavanje trake statusa ili dodavanje i uklanjanje sistemskih ikona."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"biti traka statusa"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index d797230895d8..3d98bb4d79f0 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Érzékeli az eszköz ujjlenyomat-érzékelőjén végzett kézmozdulatokat."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Képernyőkép készítése"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Készíthet képernyőképet a kijelzőről."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"állapotsor kikapcsolása vagy módosítása"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"az állapotsor szerepének átvétele"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 5937faf3d6f8..5d60c5dd1d35 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Կարող է արձանագրել մատնահետքերի սկաների վրա կատարվող ժեստերը"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Սքրինշոթի ստեղծում"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Կարող է ստեղծել էկրանի սքրինշոթ։"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"լինել կարգավիճակի գոտի"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 93b8a15b6d7a..2173eb9364e0 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dapat merekam gestur yang dilakukan di sensor sidik jari perangkat."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil screenshot"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Dapat mengambil screenshot tampilan."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"nonaktifkan atau ubah bilah status"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"jadikan bilah status"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 29c1a2ae3cc9..d9df6203143c 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Getur fangað bendingar sem eru gerðar á fingrafaralesara tækisins."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Taka skjámynd"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Getur tekið skjámynd af skjánum."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"slökkva á eða breyta stöðustiku"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vera stöðustikan"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 304d21226de6..dd1b8defba37 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"È in grado di rilevare i gesti compiuti con il sensore di impronte dei dispositivi."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Acquisire screenshot"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Può acquisire uno screenshot del display."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"disattivazione o modifica della barra di stato"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ruolo di barra di stato"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 963d473e3bd9..a6c46a21f585 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"צילום המסך"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ניתן לצלם צילום מסך של התצוגה."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"השבתה או שינוי של שורת הסטטוס"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"מאפשרת לאפליקציה להשבית את שורת הסטטוס או להוסיף ולהסיר סמלי מערכת."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"להיות שורת הסטטוס"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index f2bc9a975afc..1879cc62088b 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"デバイスの指紋認証センサーで行われた操作をキャプチャできます。"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"スクリーンショットの撮影"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ディスプレイのスクリーンショットを撮影できます。"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ステータスバーの無効化や変更"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ステータスバーへの表示"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 3803a26f2b9d..8343198bc157 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"შეუძლია აღბეჭდოს მოწყობილობის თითის ანაბეჭდის სენსორზე განხორციელებული ჟესტები."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ეკრანის ანაბეჭდის გადაღება"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"შეუძლია ეკრანის ანაბეჭდის გადაღება."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"სტატუსის ზოლის ჩანაცვლება"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 2b113467a4f5..c863cd8d2cae 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Құрылғының саусақ ізі сенсорында орындалған қимылдарды сақтайды."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот жасау"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдің скриншотын жасай аласыз."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"күйін көрсету тақтасын өшіру немесе өзгерту"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"күй жолағы болу"</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 9cf498dcae4e..35b59bef94a3 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"អាចចាប់យកចលនាដែលធ្វើនៅលើនៅលើឧបករណ៍ចាប់ស្នាមម្រាមដៃរបស់ឧបករណ៍បាន។"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ថតអេក្រង់"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"អាចថតអេក្រង់នៃផ្ទាំងអេក្រង់បាន។"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"បិទ ឬកែរបារស្ថានភាព"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ឲ្យកម្មវិធីបិទរបារស្ថានភាព ឬបន្ថែម និងលុបរូបតំណាងប្រព័ន្ធ។"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ធ្វើជារបារស្ថានភាព"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 879f9e85fe63..d0decdf7d983 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ಸಾಧನದ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ನಲ್ಲಿ ನಡೆಸಿದ ಗೆಶ್ಚರ್ಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಿ"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ಪ್ರದರ್ಶನದ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಲ್ಲದು."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 7504943ddf48..04dc86a6c9a7 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"기기 지문 센서에서 동작을 캡처합니다."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"스크린샷 촬영"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"디스플레이 스크린샷을 촬영할 수 있습니다."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"상태 표시줄 사용 중지 또는 수정"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"상태 표시줄에 위치"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index de2cdb7007c0..bdb8fe1576a1 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Түзмөктөгү манжа изинин сенсорунда жасалган жаңсоолорду жаздырып алат."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот тартып алуу"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдин скриншотун тартып алсаңыз болот."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"абал тилкесин өчүрүү же өзгөртүү"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"абал тилкесинин милдетин аткаруу"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 366881b4d56e..b7a4c05a2f61 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ສາມາດບັນທຶກທ່າທາງທີ່ເກີດຂຶ້ນໃນອຸປະກອນເຊັນເຊີລາຍນິ້ວມືໄດ້."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ຖ່າຍຮູບໜ້າຈໍ"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ເປັນແຖບສະຖານະ"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 8f5e7fba720a..cdfa1ac3cc5e 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -344,6 +344,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Gali užfiksuoti gestus, atliktus naudojant įrenginio piršto antspaudo jutiklį."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrano kopijos kūrimas"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Galima sukurti vaizdo ekrano kopiją."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"išjungti ar keisti būsenos juostą"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"būti būsenos juosta"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index cf858b778b64..66826c9fa605 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Var uztvert žestus ierīces pirksta nospieduma sensorā."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrānuzņēmuma izveide"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Var izveidot displeja ekrānuzņēmumu."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"atspējot vai pārveidot statusa joslu"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"Būt par statusa joslu"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index beed8e6ddd7f..dd5e44ed3709 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да сними движења што се направени на сензорот за отпечатоци на уредот."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зачувување слика од екранот"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да зачува слика од екранот."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"оневозможи или измени статусна лента"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"да стане статусна лента"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 4ab4c073d83b..4ed058dfb073 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്ത ജെസ്റ്ററുകൾ ക്യാപ്ചർ ചെയ്യാനാകും."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"സ്ക്രീന്ഷോട്ട് എടുക്കുക"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ഡിസ്പ്ലേയുടെ സ്ക്രീൻഷോട്ട് എടുക്കാൻ കഴിയും."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്ക്കരിക്കുക"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 5e98d53e9c69..5b8209ba92f2 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Төхөөрөмжийн хурууны хээ мэдрэгчид зангасан зангааг танина."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Дэлгэцийн зургийг дарах"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дэлгэцийн зургийг дарах боломжтой."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"статусын хэсэг болох"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 9b2f1be42a95..ee6e2eedffd5 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिव्हाइसच्या फिंगरप्रिंट सेंन्सरवरील जेश्चर कॅप्चर करू शकते."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट घ्या"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेचा स्क्रीनशॉट घेऊ शकतो."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार होऊ द्या"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index fefa9f5ea030..8f5476281f09 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Boleh menangkap gerak isyarat yang dilakukan pada penderia cap jari peranti."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil tangkapan skrin"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Boleh mengambil tangkapan skrin paparan."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"lumpuhkan atau ubah suai bar status"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"jadi bar status"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index fa13d38dead7..939df8038677 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"စက်ပစ္စည်း၏ လက်ဗွေအာရုံခံကိရိယာတွင် လုပ်ဆောင်ထားသည့် လက်ဟန်များကို မှတ်သားထားနိုင်သည်။"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ဖန်သားပြင်ဓာတ်ပုံ ရိုက်ရန်"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ဖန်သားပြင်ပြသမှုကို ဓာတ်ပုံရိုက်နိုင်ပါသည်။"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index aec00894a1e6..f0f4439c57aa 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan fange inn bevegelser som utføres på enhetens fingeravtrykkssensor."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skjermdump"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ikke ta en skjermdump av skjermen."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller endre statusfeltet"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vise appen i statusfeltet"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 5fa9b6c36831..94551e5daad4 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"यसले यन्त्रको फिंगरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्न सक्छ।"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रिनसट लिनुहोस्"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेको स्क्रिनसट लिन सकिन्छ।"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन एपलाई अनुमति दिन्छ।"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"स्टाटस बार हुन दिनुहोस्"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index c2639db2b42c..0f7d35f3fb48 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebaren registreren die op de vingerafdruksensor van het apparaat worden getekend."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot maken"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan een screenshot van het scherm maken."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"statusbalk uitzetten of wijzigen"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Hiermee kan de app de statusbalk uitzetten of systeemiconen toevoegen en verwijderen."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"de statusbalk zijn"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 8619511085d7..26821da497b7 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ଡିଭାଇସ୍ର ଟିପଚିହ୍ନ ସେନସର୍ ଉପରେ ଜେଶ୍ଚର୍ କ୍ୟାପଚର୍ କାର୍ଯ୍ୟ କରାଯାଇପାରିବ।"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ସ୍କ୍ରିନସଟ୍ ନିଅନ୍ତୁ"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ଡିସପ୍ଲେର ଏକ ସ୍କ୍ରିନସଟ୍ ନିଆଯାଇପାରେ।"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ଷ୍ଟାଟସ୍ ବାର୍କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ଆପ୍କୁ, ସ୍ଥିତି ବାର୍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍ ଆଇକନ୍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ଷ୍ଟାଟସ୍ ବାର୍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 57e187b0926d..c8c382b1a289 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ਡੀਵਾਈਸਾਂ ਦੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ \'ਤੇ ਕੀਤੇ ਗਏ ਸੰਕੇਤਾਂ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੇ ਹਨ।"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਓ"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ਡਿਸਪਲੇ ਦਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈ ਸਕਦੀ ਹੈ।"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ਸਥਿਤੀ ਪੱਟੀ ਬੰਦ ਕਰੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਨੂੰ ਚਾਲੂ ਕਰਨ ਜਾਂ ਸਿਸਟਮ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index ae83e688ab3c..8425a7a8a816 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -344,6 +344,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Może przechwytywać gesty wykonywane na czytniku linii papilarnych w urządzeniu."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Robienie zrzutu ekranu"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Może robić zrzuty ekranu wyświetlacza."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"wyłączanie lub zmienianie paska stanu"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"działanie jako pasek stanu"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 7886d2b471b2..4fe36de666b9 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 561e47eb5cfa..b6fbbea10084 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -343,6 +343,7 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode capturar gestos realizados no sensor de impressões digitais do dispositivo."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer captura de ecrã"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"É possível tirar uma captura de ecrã."</string> + <string name="dream_preview_title" msgid="5570751491996100804">"Pré-visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar barra de estado"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite à app desativar a barra de estado ou adicionar e remover ícones do sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ser apresentada na barra de estado"</string> @@ -1235,7 +1236,7 @@ <string name="unsupported_display_size_show" msgid="980129850974919375">"Mostrar sempre"</string> <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> foi concebida para uma versão incompatível do SO Android e pode ter um comportamento inesperado. Pode estar disponível uma versão atualizada da app."</string> <string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"Mostrar sempre"</string> - <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"Verificar atualizações"</string> + <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"Rever atualizações"</string> <string name="smv_application" msgid="3775183542777792638">"A app <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>) violou a política StrictMode auto-imposta."</string> <string name="smv_process" msgid="1398801497130695446">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> violou a política StrictMode auto-imposta."</string> <string name="android_upgrading_title" product="default" msgid="7279077384220829683">"O telemóvel está a atualizar…"</string> @@ -1963,7 +1964,7 @@ <string name="app_streaming_blocked_message_for_settings_dialog" product="tablet" msgid="3286849551133045896">"Não é possível aceder a esta app no seu dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no tablet."</string> <string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Não é possível aceder a esta app no seu dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no telemóvel."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta app foi concebida para uma versão mais antiga do Android e pode não funcionar corretamente. Experimente verificar se existem atualizações ou contacte o programador."</string> - <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Verificar atualizações"</string> + <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Rever atualizações"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tem mensagens novas"</string> <string name="new_sms_notification_content" msgid="3197949934153460639">"Abra a app de SMS para ver"</string> <string name="profile_encrypted_title" msgid="9001208667521266472">"Algumas funcionalidades limitadas"</string> @@ -2293,7 +2294,7 @@ <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Uma app ainda está ativa"</string> <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"A app <xliff:g id="APP">%1$s</xliff:g> está a ser executada em segundo plano Toque para gerir a utilização da bateria."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"A app <xliff:g id="APP">%1$s</xliff:g> pode afetar a autonomia da bateria. Toque para rever as apps ativas."</string> - <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificar apps ativas"</string> + <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Rever apps ativas"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Não é possível aceder à câmara do telemóvel a partir do dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>"</string> <string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Não é possível aceder à câmara do tablet a partir do dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>"</string> <string name="vdm_secure_window" msgid="161700398158812314">"Não é possível aceder a isto durante o streaming. Em alternativa, experimente no telemóvel."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 7886d2b471b2..4fe36de666b9 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 301d14cdea0c..a3be67382471 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Poate reda gesturile făcute pe senzorul de amprentă al dispozitivului."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fă o captură de ecran"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Poate face o captură de ecran."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"dezactivare sau modificare bare de stare"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"să fie bara de stare"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index c7658177e2ca..d5067ae4e035 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -344,6 +344,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Использовать сканер отпечатков пальцев для дополнительных жестов."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Создавать скриншоты"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Создавать снимки экрана."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"Отключение/изменение строки состояния"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"Замена строки состояния"</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 69d806a58b27..66b0cd6fff3b 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"උපාංගයෙහි ඇඟිලි සලකුණු සංවේදකය මත සිදු කරන ඉංගිත ග්රහණය කළ හැකිය."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"තිර රුව ගන්න"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"සංදර්ශකයේ තිර රුවක් ගැනීමට හැකිය."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"තත්ව තීරුව අක්රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"තත්ත්ව තීරුව බවට පත්වීම"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 6bbfe0ab7fd3..816feefb8b7a 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -344,6 +344,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dokáže zaznamenať gestá na senzore odtlačkov prstov zariadenia."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Vytvoriť snímku obrazovky"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Je možné vytvoriť snímku obrazovky."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"zakázanie alebo zmeny stavového riadka"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"vydávanie sa za stavový riadok"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 1accd18949d7..61f2b51f3d85 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -344,6 +344,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Prepoznava poteze, narejene po tipalu prstnih odtisov naprave."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ustvarjanje posnetka zaslona"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Lahko naredi posnetek zaslona."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"onemogočanje ali spreminjanje vrstice stanja"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"postane vrstica stanja"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index a8fc00eb4c3c..1708904e40e5 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Mund të regjistrojë gjestet e kryera në sensorin e gjurmës së gishtit të pajisjes."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Nxirr një pamje të ekranit"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Mund të nxjerrë një pamje e ekranit."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"çaktivizo ose modifiko shiritin e statusit"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"të bëhet shiriti i statusit"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index bf8c0f76d5ee..fb36169d3e33 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -343,6 +343,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да региструје покрете на сензору за отисак прста на уређају."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Направи снимак екрана"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да направи снимак екрана."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"онемогућавање или измена статусне траке"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"функционисање као статусна трака"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 177615d89574..6c593df1ff34 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan registrera rörelser som utförs med hjälp av enhetens fingeravtryckssensor."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skärmbild"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ta en skärmbild av skärmen."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"inaktivera eller ändra statusfält"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"visas i statusfältet"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 1319d1b0b6da..715c1c4f1b34 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Inaweza kurekodi ishara zinazotekelezwa kwenye kitambua alama ya kidole."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Piga picha ya skrini"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Inaweza kupiga picha ya skrini ya onyesho."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"zima au rekebisha mwambaa hali"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa aikoni za mfumo."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"kuwa sehemu ya arifa"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 6b53c8e2cdf4..2c8c532fefeb 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"சாதனத்தின் கைரேகை சென்சார்மேல் செய்யப்படும் சைகைகளைக் கேப்ட்சர் செய்ய முடியும்."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ஸ்கிரீன்ஷாட்டை எடுக்கும்"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"டிஸ்ப்ளேவை ஸ்கிரீன்ஷாட் எடுக்க முடியும்."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற ஆப்ஸை அனுமதிக்கிறது."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"நிலைப் பட்டியில் இருக்கும்"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index cff6773b7c57..bc5380279ca3 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"పరికర వేలిముద్ర సెన్సార్లో ఉపయోగించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"స్క్రీన్షాట్ను తీయండి"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"డిస్ప్లే యొక్క స్క్రీన్షాట్ తీసుకోవచ్చు."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"స్టేటస్ బార్ను డిజేబుల్ చేయడం లేదా మార్చడం"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"స్టేటస్ బార్ను డిజేబుల్ చేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"స్టేటస్ పట్టీగా ఉండటం"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 10ee52014745..d12b209e3d5e 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"สามารถจับท่าทางสัมผัสที่เกิดขึ้นบนเซ็นเซอร์ลายนิ้วมือของอุปกรณ์"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ถ่ายภาพหน้าจอ"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ถ่ายภาพหน้าจอได้"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"เป็นแถบสถานะ"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index f4658cf8b339..4c9e38847f1f 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Makukunan ang mga galaw na ginawa sa sensor para sa fingerprint ng device."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Kumuha ng screenshot"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puwedeng kumuha ng screenshot ng display."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"i-disable o baguhin ang status bar"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Pinapayagan ang app na i-disable ang status bar o magdagdag at mag-alis ng mga icon ng system."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"maging status bar"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 0573fcd89f0b..4e6c6c78234f 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazın parmak izi sensörlerinde gerçekleştirilen hareketleri yakalayabilir."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran görüntüsü al"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran görüntüsü alınabilir."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"durum çubuğunu devre dışı bırak veya değiştir"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"durum çubuğunda olma"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index ad03757a970e..28828e713be4 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -344,6 +344,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може фіксувати жести на сканері відбитків пальців."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Робити знімки екрана"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може робити знімки екрана."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"вимикати чи змін. рядок стану"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"відображатися як рядок стану"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 4e03774d644f..d94ccc133442 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"آلہ کے فنگر پرنٹ سینسر پر کیے گئے اشاروں کو کیپچر کر سکتا ہے۔"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"اسکرین شاٹ لیں"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ڈسپلے کا اسکرین شاٹ لیا جا سکتا ہے۔"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"بطور اسٹیٹس بار کام لیں"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 8d3bedf9e860..8db468bb8181 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Barmoq izi skanerida kiritilgan ishoralarni taniy oladi."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Skrinshot olish"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekrandan skrinshot olishi mumkin."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"holat panelini o‘zgartirish yoki o‘chirish"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"holat qatorida ko‘rinishi"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index f30df3b67da8..30cab1ae2c11 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Có thể ghi lại các cử chỉ được thực hiện trên cảm biến vân tay của thiết bị."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Chụp ảnh màn hình"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Có thể chụp ảnh màn hình."</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"trở thành thanh trạng thái"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 2f3951f2f3f5..3a8ab3cab7fa 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以捕捉在设备指纹传感器上执行的手势。"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"截取屏幕截图"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可截取显示画面的屏幕截图。"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改状态栏"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"允许应用停用状态栏或者增删系统图标。"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"用作状态栏"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index ed5e9899922c..0e65d66f7dd7 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取在裝置指紋感應器上執行的手勢。"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕擷圖"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕截圖。"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改狀態列"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"成為狀態列"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 08b597a6c675..bd37579fb6f1 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取使用者對裝置的指紋感應器執行的手勢。"</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕畫面"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕畫面。"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"停用或變更狀態列"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"以狀態列顯示"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index a8cdb4e6f287..abc673bfb3b9 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -342,6 +342,8 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Ingathatha ukuthinta okwenziwe kunzwa yezigxivizo zeminwe zedivayisi."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Thatha isithombe-skrini"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ingathatha isithombe-skrini sesiboniso"</string> + <!-- no translation found for dream_preview_title (5570751491996100804) --> + <skip /> <string name="permlab_statusBar" msgid="8798267849526214017">"khubaza noma guqula ibha yomumo"</string> <string name="permdesc_statusBar" msgid="5809162768651019642">"Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"yiba yibha yesimo"</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index dffd1cc9e217..dafa0ad7989f 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -6084,6 +6084,12 @@ different from the home screen wallpaper. --> <bool name="config_independentLockscreenLiveWallpaper">false</bool> + <!-- Whether the vendor power press code need to be mapped. --> + <bool name="config_powerPressMapping">false</bool> + + <!-- Power press vendor code. --> + <integer name="config_powerPressCode">-1</integer> + <!-- Whether to show weather on the lock screen by default. --> <bool name="config_lockscreenWeatherEnabledByDefault">false</bool> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 9cc8aa81419d..591ba5feeee9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2655,6 +2655,8 @@ <java-symbol type="integer" name="config_sideFpsToastTimeout"/> <java-symbol type="integer" name="config_sidefpsSkipWaitForPowerAcquireMessage"/> <java-symbol type="integer" name="config_sidefpsSkipWaitForPowerVendorAcquireMessage"/> + <java-symbol type="integer" name="config_powerPressCode"/> + <java-symbol type="bool" name="config_powerPressMapping"/> <!-- Clickable toast used during sidefps enrollment --> <java-symbol type="layout" name="side_fps_toast" /> diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml index 26246fcee52b..22d921960174 100644 --- a/libs/WindowManager/Shell/res/values-af/strings.xml +++ b/libs/WindowManager/Shell/res/values-af/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Bo 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Bo 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Volskerm onder"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Verdeel links"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Verdeel regs"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Verdeel bo"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Verdeel onder"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Gebruik eenhandmodus"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Swiep van die onderkant van die skerm af op of tik enige plek bo die program om uit te gaan"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Begin eenhandmodus"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Maak toe"</string> <string name="back_button_text" msgid="1469718707134137085">"Terug"</string> <string name="handle_text" msgid="1766582106752184456">"Handvatsel"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Volskerm"</string> <string name="desktop_text" msgid="1077633567027630454">"Rekenaarmodus"</string> <string name="split_screen_text" msgid="1396336058129570886">"Verdeelde skerm"</string> <string name="more_button_text" msgid="3655388105592893530">"Meer"</string> <string name="float_button_text" msgid="9221657008391364581">"Sweef"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml index 7f0a3ab2c070..17ea0530de52 100644 --- a/libs/WindowManager/Shell/res/values-am/strings.xml +++ b/libs/WindowManager/Shell/res/values-am/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ከላይ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ከላይ 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"የታች ሙሉ ማያ ገጽ"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"ወደ ግራ ከፋፍል"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"ወደ ቀኝ ከፋፍል"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"ወደ ላይ ከፋፍል"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"ወደ ታች ከፋፍል"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ባለአንድ እጅ ሁነታን በመጠቀም ላይ"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"ለመውጣት ከማያው ግርጌ ወደ ላይ ይጥረጉ ወይም ከመተግበሪያው በላይ ማንኛውም ቦታ ላይ መታ ያድርጉ"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ባለአንድ እጅ ሁነታ ጀምር"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"ዝጋ"</string> <string name="back_button_text" msgid="1469718707134137085">"ተመለስ"</string> <string name="handle_text" msgid="1766582106752184456">"መያዣ"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"ሙሉ ማያ"</string> <string name="desktop_text" msgid="1077633567027630454">"የዴስክቶፕ ሁነታ"</string> <string name="split_screen_text" msgid="1396336058129570886">"የተከፈለ ማያ ገጽ"</string> <string name="more_button_text" msgid="3655388105592893530">"ተጨማሪ"</string> <string name="float_button_text" msgid="9221657008391364581">"ተንሳፋፊ"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml index 7f81e50e72fa..2e4c8ef29862 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings.xml @@ -100,9 +100,19 @@ <string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string> <string name="back_button_text" msgid="1469718707134137085">"رجوع"</string> <string name="handle_text" msgid="1766582106752184456">"مقبض"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"ملء الشاشة"</string> <string name="desktop_text" msgid="1077633567027630454">"وضع سطح المكتب"</string> <string name="split_screen_text" msgid="1396336058129570886">"تقسيم الشاشة"</string> <string name="more_button_text" msgid="3655388105592893530">"المزيد"</string> <string name="float_button_text" msgid="9221657008391364581">"نافذة عائمة"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index 505ca96a3c73..c88519736ad6 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"শীর্ষ স্ক্ৰীনখন ৫০% কৰক"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"শীর্ষ স্ক্ৰীনখন ৩০% কৰক"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"তলৰ স্ক্ৰীনখন সম্পূৰ্ণ স্ক্ৰীন কৰক"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"বাওঁফালে বিভাজন কৰক"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"সোঁফালে বিভাজন কৰক"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"একেবাৰে ওপৰৰফালে বিভাজন কৰক"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"একেবাৰে তলৰফালে বিভাজন কৰক"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"এখন হাতেৰে ব্যৱহাৰ কৰা ম’ড ব্যৱহাৰ কৰা"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"বাহিৰ হ’বলৈ স্ক্ৰীনখনৰ একেবাৰে তলৰ পৰা ওপৰলৈ ছোৱাইপ কৰক অথবা এপ্টোৰ ওপৰত যিকোনো ঠাইত টিপক"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"এখন হাতেৰে ব্যৱহাৰ কৰা ম\'ডটো আৰম্ভ কৰক"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string> <string name="back_button_text" msgid="1469718707134137085">"উভতি যাওক"</string> <string name="handle_text" msgid="1766582106752184456">"হেণ্ডেল"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"সম্পূৰ্ণ স্ক্ৰীন"</string> <string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ ম’ড"</string> <string name="split_screen_text" msgid="1396336058129570886">"বিভাজিত স্ক্ৰীন"</string> <string name="more_button_text" msgid="3655388105592893530">"অধিক"</string> <string name="float_button_text" msgid="9221657008391364581">"ওপঙা"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index 0d754bae12fc..4427fa94c8fc 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Yuxarı 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Yuxarı 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Aşağı tam ekran"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Sola ayırın"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Sağa ayırın"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Yuxarı ayırın"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Aşağı ayırın"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Birəlli rejim istifadəsi"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Çıxmaq üçün ekranın aşağısından yuxarıya doğru sürüşdürün və ya tətbiqin yuxarısında istənilən yerə toxunun"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Birəlli rejim başlasın"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Bağlayın"</string> <string name="back_button_text" msgid="1469718707134137085">"Geriyə"</string> <string name="handle_text" msgid="1766582106752184456">"Hər kəsə açıq istifadəçi adı"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string> <string name="desktop_text" msgid="1077633567027630454">"Masaüstü Rejimi"</string> <string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string> <string name="more_button_text" msgid="3655388105592893530">"Ardı"</string> <string name="float_button_text" msgid="9221657008391364581">"Üzən pəncərə"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml index 46d9f2b028d7..a67ba393180e 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Gornji ekran 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Gornji ekran 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Režim celog ekrana za donji ekran"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Podelite levo"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Podelite desno"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Podelite u vrhu"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Podelite u dnu"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Korišćenje režima jednom rukom"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Da biste izašli, prevucite nagore od dna ekrana ili dodirnite bilo gde iznad aplikacije"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Pokrenite režim jednom rukom"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Zatvorite"</string> <string name="back_button_text" msgid="1469718707134137085">"Nazad"</string> <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Preko celog ekrana"</string> <string name="desktop_text" msgid="1077633567027630454">"Režim za računare"</string> <string name="split_screen_text" msgid="1396336058129570886">"Podeljeni ekran"</string> <string name="more_button_text" msgid="3655388105592893530">"Još"</string> <string name="float_button_text" msgid="9221657008391364581">"Plutajuće"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml index 31d0484476cd..5adb2ecec112 100644 --- a/libs/WindowManager/Shell/res/values-be/strings.xml +++ b/libs/WindowManager/Shell/res/values-be/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Верхні экран – 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Верхні экран – 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ніжні экран – поўнаэкранны рэжым"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Падзяліць злева"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Падзяліць справа"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Падзяліць уверсе"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Падзяліць унізе"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Выкарыстоўваецца рэжым кіравання адной рукой"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Каб выйсці, правядзіце па экране пальцам знізу ўверх або націсніце ў любым месцы над праграмай"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Запусціць рэжым кіравання адной рукой"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Закрыць"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"На ўвесь экран"</string> <string name="desktop_text" msgid="1077633567027630454">"Рэжым працоўнага стала"</string> <string name="split_screen_text" msgid="1396336058129570886">"Падзяліць экран"</string> <string name="more_button_text" msgid="3655388105592893530">"Яшчэ"</string> <string name="float_button_text" msgid="9221657008391364581">"Зрабіць рухомым акном"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index 08fe3656891c..8c82d1a7c94f 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Горен екран: 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Горен екран: 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Долен екран: Показване на цял екран"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Разделяне в лявата част"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Разделяне в дясната част"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Разделяне в горната част"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Разделяне в долната част"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Използване на режима за работа с една ръка"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"За изход прекарайте пръст нагоре от долната част на екрана или докоснете произволно място над приложението"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Стартиране на режима за работа с една ръка"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> <string name="handle_text" msgid="1766582106752184456">"Манипулатор"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Цял екран"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим за настолни компютри"</string> <string name="split_screen_text" msgid="1396336058129570886">"Разделяне на екрана"</string> <string name="more_button_text" msgid="3655388105592893530">"Още"</string> <string name="float_button_text" msgid="9221657008391364581">"Плаващо"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml index ac0daa0f97cb..11a4175c0bb0 100644 --- a/libs/WindowManager/Shell/res/values-bn/strings.xml +++ b/libs/WindowManager/Shell/res/values-bn/strings.xml @@ -100,9 +100,19 @@ <string name="close_button_text" msgid="2913281996024033299">"বন্ধ করুন"</string> <string name="back_button_text" msgid="1469718707134137085">"ফিরে যান"</string> <string name="handle_text" msgid="1766582106752184456">"হাতল"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"ফুলস্ক্রিন"</string> <string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ মোড"</string> <string name="split_screen_text" msgid="1396336058129570886">"স্প্লিট স্ক্রিন"</string> <string name="more_button_text" msgid="3655388105592893530">"আরও"</string> <string name="float_button_text" msgid="9221657008391364581">"ফ্লোট"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index 745e6fc06b9b..c65ce0842db7 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Gore 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Gore 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Donji ekran kao cijeli ekran"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Podjela ulijevo"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Podjela udesno"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Podjela nagore"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Podjela nadolje"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Korištenje načina rada jednom rukom"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Da izađete, prevucite s dna ekrana prema gore ili dodirnite bilo gdje iznad aplikacije"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Započinjanje načina rada jednom rukom"</string> @@ -100,9 +96,14 @@ <string name="close_button_text" msgid="2913281996024033299">"Zatvaranje"</string> <string name="back_button_text" msgid="1469718707134137085">"Nazad"</string> <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string> + <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Cijeli ekran"</string> <string name="desktop_text" msgid="1077633567027630454">"Način rada radne površine"</string> <string name="split_screen_text" msgid="1396336058129570886">"Podijeljeni ekran"</string> <string name="more_button_text" msgid="3655388105592893530">"Više"</string> <string name="float_button_text" msgid="9221657008391364581">"Lebdeći"</string> + <string name="select_text" msgid="5139083974039906583">"Odaberite"</string> + <string name="screenshot_text" msgid="1477704010087786671">"Snimka zaslona"</string> + <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string> + <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite izbornik"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index 727c31913516..f50b8f295a32 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Pantalla superior al 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Pantalla superior al 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pantalla inferior completa"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Divideix a l\'esquerra"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Divideix a la dreta"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Divideix a la part superior"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Divideix a la part inferior"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"S\'està utilitzant el mode d\'una mà"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Per sortir, llisca cap amunt des de la part inferior de la pantalla o toca qualsevol lloc a sobre de l\'aplicació"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Inicia el mode d\'una mà"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Tanca"</string> <string name="back_button_text" msgid="1469718707134137085">"Enrere"</string> <string name="handle_text" msgid="1766582106752184456">"Ansa"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string> <string name="desktop_text" msgid="1077633567027630454">"Mode d\'escriptori"</string> <string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string> <string name="more_button_text" msgid="3655388105592893530">"Més"</string> <string name="float_button_text" msgid="9221657008391364581">"Flotant"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index 395e12caf6e1..ac36edbb2f6e 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % nahoře"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30 % nahoře"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Dolní část na celou obrazovku"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Rozdělit vlevo"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Rozdělit vpravo"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Rozdělit nahoře"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Rozdělit dole"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Používání režimu jedné ruky"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Režim ukončíte, když přejedete prstem z dolní části obrazovky nahoru nebo klepnete kamkoli nad aplikaci"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Spustit režim jedné ruky"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Zavřít"</string> <string name="back_button_text" msgid="1469718707134137085">"Zpět"</string> <string name="handle_text" msgid="1766582106752184456">"Úchyt"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string> <string name="desktop_text" msgid="1077633567027630454">"Režim počítače"</string> <string name="split_screen_text" msgid="1396336058129570886">"Rozdělená obrazovka"</string> <string name="more_button_text" msgid="3655388105592893530">"Více"</string> <string name="float_button_text" msgid="9221657008391364581">"Plovoucí"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index 5087c13be462..8635cc5d4632 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Øverste 50 %"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Øverste 30 %"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Vis nederste del i fuld skærm"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Vis i venstre side"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Vis i højre side"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Vis øverst"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Vis nederst"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Brug af enhåndstilstand"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Du kan afslutte ved at stryge opad fra bunden af skærmen eller trykke et vilkårligt sted over appen"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Start enhåndstilstand"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Luk"</string> <string name="back_button_text" msgid="1469718707134137085">"Tilbage"</string> <string name="handle_text" msgid="1766582106752184456">"Håndtag"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Fuld skærm"</string> <string name="desktop_text" msgid="1077633567027630454">"Computertilstand"</string> <string name="split_screen_text" msgid="1396336058129570886">"Opdelt skærm"</string> <string name="more_button_text" msgid="3655388105592893530">"Mere"</string> <string name="float_button_text" msgid="9221657008391364581">"Svævende"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index e97f0687ca3d..059a4da313fe 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % oben"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30 % oben"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Vollbild unten"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Links teilen"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Rechts teilen"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Oben teilen"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Unten teilen"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Einhandmodus wird verwendet"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Wenn du die App schließen möchtest, wische vom unteren Rand des Displays nach oben oder tippe auf eine beliebige Stelle oberhalb der App"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Einhandmodus starten"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Schließen"</string> <string name="back_button_text" msgid="1469718707134137085">"Zurück"</string> <string name="handle_text" msgid="1766582106752184456">"Ziehpunkt"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Vollbild"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string> <string name="split_screen_text" msgid="1396336058129570886">"Geteilter Bildschirm"</string> <string name="more_button_text" msgid="3655388105592893530">"Mehr"</string> <string name="float_button_text" msgid="9221657008391364581">"Frei schwebend"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml index df82625674f1..5800cc826ef2 100644 --- a/libs/WindowManager/Shell/res/values-el/strings.xml +++ b/libs/WindowManager/Shell/res/values-el/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Πάνω 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Πάνω 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Κάτω πλήρης οθόνη"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Διαχωρισμός αριστερά"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Διαχωρισμός δεξιά"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Διαχωρισμός επάνω"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Διαχωρισμός κάτω"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Χρήση λειτουργίας ενός χεριού"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Για έξοδο, σύρετε προς τα πάνω από το κάτω μέρος της οθόνης ή πατήστε οπουδήποτε πάνω από την εφαρμογή."</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Έναρξη λειτουργίας ενός χεριού"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Κλείσιμο"</string> <string name="back_button_text" msgid="1469718707134137085">"Πίσω"</string> <string name="handle_text" msgid="1766582106752184456">"Λαβή"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Πλήρης οθόνη"</string> <string name="desktop_text" msgid="1077633567027630454">"Λειτουργία επιφάνειας εργασίας"</string> <string name="split_screen_text" msgid="1396336058129570886">"Διαχωρισμός οθόνης"</string> <string name="more_button_text" msgid="3655388105592893530">"Περισσότερα"</string> <string name="float_button_text" msgid="9221657008391364581">"Κινούμενο"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml index b1c9ba8203ee..4d18f5ebb5ac 100644 --- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml @@ -96,9 +96,14 @@ <string name="close_button_text" msgid="2913281996024033299">"Close"</string> <string name="back_button_text" msgid="1469718707134137085">"Back"</string> <string name="handle_text" msgid="1766582106752184456">"Handle"</string> + <string name="app_icon_text" msgid="2823268023931811747">"App icon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string> <string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string> <string name="more_button_text" msgid="3655388105592893530">"More"</string> <string name="float_button_text" msgid="9221657008391364581">"Float"</string> + <string name="select_text" msgid="5139083974039906583">"Select"</string> + <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string> + <string name="close_text" msgid="4986518933445178928">"Close"</string> + <string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml index 4aa22116b256..40b9d959e734 100644 --- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml @@ -96,9 +96,14 @@ <string name="close_button_text" msgid="2913281996024033299">"Close"</string> <string name="back_button_text" msgid="1469718707134137085">"Back"</string> <string name="handle_text" msgid="1766582106752184456">"Handle"</string> + <string name="app_icon_text" msgid="2823268023931811747">"App Icon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string> <string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string> <string name="more_button_text" msgid="3655388105592893530">"More"</string> <string name="float_button_text" msgid="9221657008391364581">"Float"</string> + <string name="select_text" msgid="5139083974039906583">"Select"</string> + <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string> + <string name="close_text" msgid="4986518933445178928">"Close"</string> + <string name="collapse_menu_text" msgid="7515008122450342029">"Close Menu"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml index b1c9ba8203ee..4d18f5ebb5ac 100644 --- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml @@ -96,9 +96,14 @@ <string name="close_button_text" msgid="2913281996024033299">"Close"</string> <string name="back_button_text" msgid="1469718707134137085">"Back"</string> <string name="handle_text" msgid="1766582106752184456">"Handle"</string> + <string name="app_icon_text" msgid="2823268023931811747">"App icon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string> <string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string> <string name="more_button_text" msgid="3655388105592893530">"More"</string> <string name="float_button_text" msgid="9221657008391364581">"Float"</string> + <string name="select_text" msgid="5139083974039906583">"Select"</string> + <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string> + <string name="close_text" msgid="4986518933445178928">"Close"</string> + <string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml index b1c9ba8203ee..4d18f5ebb5ac 100644 --- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml @@ -96,9 +96,14 @@ <string name="close_button_text" msgid="2913281996024033299">"Close"</string> <string name="back_button_text" msgid="1469718707134137085">"Back"</string> <string name="handle_text" msgid="1766582106752184456">"Handle"</string> + <string name="app_icon_text" msgid="2823268023931811747">"App icon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string> <string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string> <string name="more_button_text" msgid="3655388105592893530">"More"</string> <string name="float_button_text" msgid="9221657008391364581">"Float"</string> + <string name="select_text" msgid="5139083974039906583">"Select"</string> + <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string> + <string name="close_text" msgid="4986518933445178928">"Close"</string> + <string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml index 265849cd4978..e0fbfbb6ef09 100644 --- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml @@ -96,9 +96,14 @@ <string name="close_button_text" msgid="2913281996024033299">"Close"</string> <string name="back_button_text" msgid="1469718707134137085">"Back"</string> <string name="handle_text" msgid="1766582106752184456">"Handle"</string> + <string name="app_icon_text" msgid="2823268023931811747">"App Icon"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string> <string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string> <string name="more_button_text" msgid="3655388105592893530">"More"</string> <string name="float_button_text" msgid="9221657008391364581">"Float"</string> + <string name="select_text" msgid="5139083974039906583">"Select"</string> + <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string> + <string name="close_text" msgid="4986518933445178928">"Close"</string> + <string name="collapse_menu_text" msgid="7515008122450342029">"Close Menu"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index 1196aaf8ffb9..d30653759f2f 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Superior: 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Superior: 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pantalla inferior completa"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir a la izquierda"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir a la derecha"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir en la parte superior"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir en la parte inferior"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Cómo usar el modo de una mano"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para salir, desliza el dedo hacia arriba desde la parte inferior de la pantalla o presiona cualquier parte arriba de la app"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar el modo de una mano"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string> <string name="back_button_text" msgid="1469718707134137085">"Atrás"</string> <string name="handle_text" msgid="1766582106752184456">"Controlador"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string> <string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string> <string name="more_button_text" msgid="3655388105592893530">"Más"</string> <string name="float_button_text" msgid="9221657008391364581">"Flotante"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index c3c832b4943f..ab1ced4f6d1e 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Superior 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Superior 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pantalla inferior completa"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir en la parte izquierda"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir en la parte derecha"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir en la parte superior"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir en la parte inferior"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Usar modo Una mano"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para salir, desliza el dedo hacia arriba desde la parte inferior de la pantalla o toca cualquier zona que haya encima de la aplicación"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar modo Una mano"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string> <string name="back_button_text" msgid="1469718707134137085">"Atrás"</string> <string name="handle_text" msgid="1766582106752184456">"Controlador"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo Escritorio"</string> <string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string> <string name="more_button_text" msgid="3655388105592893530">"Más"</string> <string name="float_button_text" msgid="9221657008391364581">"Flotante"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index 4722c074deb9..4c4d87ebf574 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Ülemine: 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Ülemine: 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Alumine täisekraan"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Jaga vasakule"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Jaga paremale"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Jaga üles"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Jaga alla"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Ühekäerežiimi kasutamine"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Väljumiseks pühkige ekraani alaosast üles või puudutage rakenduse kohal olevat ala"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Ühekäerežiimi käivitamine"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Sule"</string> <string name="back_button_text" msgid="1469718707134137085">"Tagasi"</string> <string name="handle_text" msgid="1766582106752184456">"Käepide"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Täisekraan"</string> <string name="desktop_text" msgid="1077633567027630454">"Lauaarvuti režiim"</string> <string name="split_screen_text" msgid="1396336058129570886">"Jagatud ekraanikuva"</string> <string name="more_button_text" msgid="3655388105592893530">"Rohkem"</string> <string name="float_button_text" msgid="9221657008391364581">"Hõljuv"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml index e1c2a0d25ee6..5642a5f33115 100644 --- a/libs/WindowManager/Shell/res/values-eu/strings.xml +++ b/libs/WindowManager/Shell/res/values-eu/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Ezarri goialdea % 50en"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Ezarri goialdea % 30en"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ezarri behealdea pantaila osoan"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Zatitu ezkerraldean"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Zatitu eskuinaldean"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Zatitu goialdean"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Zatitu behealdean"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Esku bakarreko modua erabiltzea"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Irteteko, pasatu hatza pantailaren behealdetik gora edo sakatu aplikazioaren gainaldea"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Abiarazi esku bakarreko modua"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Itxi"</string> <string name="back_button_text" msgid="1469718707134137085">"Atzera"</string> <string name="handle_text" msgid="1766582106752184456">"Kontu-izena"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Pantaila osoa"</string> <string name="desktop_text" msgid="1077633567027630454">"Ordenagailuetarako modua"</string> <string name="split_screen_text" msgid="1396336058129570886">"Pantaila zatitua"</string> <string name="more_button_text" msgid="3655388105592893530">"Gehiago"</string> <string name="float_button_text" msgid="9221657008391364581">"Leiho gainerakorra"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index 5a4871d7c6cc..a15d7a4e1c1f 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"٪۵۰ بالا"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"٪۳۰ بالا"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"تمامصفحه پایین"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"تقسیم از چپ"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"تقسیم از راست"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"تقسیم از بالا"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"تقسیم از پایین"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"استفاده از حالت یکدستی"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"برای خارج شدن، از پایین صفحهنمایش تند بهطرف بالا بکشید یا در هر جایی از بالای برنامه که میخواهید ضربه بزنید"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"آغاز «حالت یکدستی»"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"بستن"</string> <string name="back_button_text" msgid="1469718707134137085">"برگشتن"</string> <string name="handle_text" msgid="1766582106752184456">"دستگیره"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"تمامصفحه"</string> <string name="desktop_text" msgid="1077633567027630454">"حالت رایانه"</string> <string name="split_screen_text" msgid="1396336058129570886">"صفحهٔ دونیمه"</string> <string name="more_button_text" msgid="3655388105592893530">"بیشتر"</string> <string name="float_button_text" msgid="9221657008391364581">"شناور"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index 56f444e4e9a2..8c679b6b6ff7 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Yläosa 50 %"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Yläosa 30 %"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Alaosa koko näytölle"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Vasemmalla"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Oikealla"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Ylhäällä"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Alhaalla"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Yhden käden moodin käyttö"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Poistu pyyhkäisemällä ylös näytön alareunasta tai napauttamalla sovelluksen yllä"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Käynnistä yhden käden moodi"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Sulje"</string> <string name="back_button_text" msgid="1469718707134137085">"Takaisin"</string> <string name="handle_text" msgid="1766582106752184456">"Kahva"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Koko näyttö"</string> <string name="desktop_text" msgid="1077633567027630454">"Työpöytätila"</string> <string name="split_screen_text" msgid="1396336058129570886">"Jaettu näyttö"</string> <string name="more_button_text" msgid="3655388105592893530">"Lisää"</string> <string name="float_button_text" msgid="9221657008391364581">"Kelluva ikkuna"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index e48d794b3ac3..d43aea5849d1 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % dans le haut"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30 % dans le haut"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Plein écran dans le bas"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Diviser à gauche"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Diviser à droite"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Diviser dans la partie supérieure"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Diviser dans la partie inférieure"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Utiliser le mode Une main"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Pour quitter, balayez l\'écran du bas vers le haut, ou touchez n\'importe où sur l\'écran en haut de l\'application"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Démarrer le mode Une main"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Fermer"</string> <string name="back_button_text" msgid="1469718707134137085">"Retour"</string> <string name="handle_text" msgid="1766582106752184456">"Identifiant"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string> <string name="desktop_text" msgid="1077633567027630454">"Mode Bureau"</string> <string name="split_screen_text" msgid="1396336058129570886">"Écran partagé"</string> <string name="more_button_text" msgid="3655388105592893530">"Plus"</string> <string name="float_button_text" msgid="9221657008391364581">"Flottant"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index 301bca6434c3..15e89f81682e 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Écran du haut à 50 %"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Écran du haut à 30 %"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Écran du bas en plein écran"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Affichée à gauche"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Affichée à droite"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Affichée en haut"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Affichée en haut"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Utiliser le mode une main"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Pour quitter, balayez l\'écran de bas en haut ou appuyez n\'importe où au-dessus de l\'application"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Démarrer le mode une main"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Fermer"</string> <string name="back_button_text" msgid="1469718707134137085">"Retour"</string> <string name="handle_text" msgid="1766582106752184456">"Poignée"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string> <string name="desktop_text" msgid="1077633567027630454">"Mode ordinateur"</string> <string name="split_screen_text" msgid="1396336058129570886">"Écran partagé"</string> <string name="more_button_text" msgid="3655388105592893530">"Plus"</string> <string name="float_button_text" msgid="9221657008391364581">"Flottante"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index 967945ce64b8..f83564d05f44 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % arriba"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30 % arriba"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pantalla completa abaixo"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir (esquerda)"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir (dereita)"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir (arriba)"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir (abaixo)"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Como se usa o modo dunha soa man?"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para saír, pasa o dedo cara arriba desde a parte inferior da pantalla ou toca calquera lugar da zona situada encima da aplicación"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar modo dunha soa man"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Pechar"</string> <string name="back_button_text" msgid="1469718707134137085">"Atrás"</string> <string name="handle_text" msgid="1766582106752184456">"Controlador"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string> <string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string> <string name="more_button_text" msgid="3655388105592893530">"Máis"</string> <string name="float_button_text" msgid="9221657008391364581">"Flotante"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml index 653e1a69e698..bd3620591cf7 100644 --- a/libs/WindowManager/Shell/res/values-gu/strings.xml +++ b/libs/WindowManager/Shell/res/values-gu/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"શીર્ષ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"શીર્ષ 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"તળિયાની પૂર્ણ સ્ક્રીન"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"ડાબે વિભાજિત કરો"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"જમણે વિભાજિત કરો"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"ઉપર વિભાજિત કરો"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"નીચે વિભાજિત કરો"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"એક-હાથે વાપરો મોડનો ઉપયોગ કરી રહ્યાં છીએ"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"બહાર નીકળવા માટે, સ્ક્રીનની નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરો અથવા ઍપના આઇકન પર ગમે ત્યાં ટૅપ કરો"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"એક-હાથે વાપરો મોડ શરૂ કરો"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"બંધ કરો"</string> <string name="back_button_text" msgid="1469718707134137085">"પાછળ"</string> <string name="handle_text" msgid="1766582106752184456">"હૅન્ડલ"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"પૂર્ણસ્ક્રીન"</string> <string name="desktop_text" msgid="1077633567027630454">"ડેસ્કટૉપ મોડ"</string> <string name="split_screen_text" msgid="1396336058129570886">"સ્ક્રીનને વિભાજિત કરો"</string> <string name="more_button_text" msgid="3655388105592893530">"વધુ"</string> <string name="float_button_text" msgid="9221657008391364581">"ફ્લોટિંગ વિન્ડો"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index 25b658adf05f..e56ad17d2680 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ऊपर की स्क्रीन को 50% बनाएं"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ऊपर की स्क्रीन को 30% बनाएं"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"नीचे की स्क्रीन को फ़ुल स्क्रीन बनाएं"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"स्क्रीन को बाएं हिस्से में स्प्लिट करें"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"स्क्रीन को दाएं हिस्से में स्प्लिट करें"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"स्क्रीन को ऊपर के हिस्से में स्प्लिट करें"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"स्क्रीन को सबसे नीचे वाले हिस्से में स्प्लिट करें"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"वन-हैंडेड मोड का इस्तेमाल करना"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"इस मोड से बाहर निकलने के लिए, स्क्रीन के सबसे निचले हिस्से से ऊपर की ओर स्वाइप करें या ऐप्लिकेशन के बाहर कहीं भी टैप करें"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"वन-हैंडेड मोड चालू करें"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string> <string name="back_button_text" msgid="1469718707134137085">"वापस जाएं"</string> <string name="handle_text" msgid="1766582106752184456">"हैंडल"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"फ़ुलस्क्रीन"</string> <string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string> <string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन मोड"</string> <string name="more_button_text" msgid="3655388105592893530">"ज़्यादा देखें"</string> <string name="float_button_text" msgid="9221657008391364581">"फ़्लोट"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml index 57fd2fa3c937..cde33c7e3725 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Gornji zaslon na 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Gornji zaslon na 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Donji zaslon u cijeli zaslon"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Podijeli lijevo"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Podijeli desno"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Podijeli gore"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Podijeli dolje"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Korištenje načina rada jednom rukom"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Za izlaz prijeđite prstom od dna zaslona prema gore ili dodirnite bio gdje iznad aplikacije"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Pokretanje načina rada jednom rukom"</string> @@ -100,9 +96,14 @@ <string name="close_button_text" msgid="2913281996024033299">"Zatvori"</string> <string name="back_button_text" msgid="1469718707134137085">"Natrag"</string> <string name="handle_text" msgid="1766582106752184456">"Pokazivač"</string> + <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Puni zaslon"</string> <string name="desktop_text" msgid="1077633567027630454">"Stolni način rada"</string> <string name="split_screen_text" msgid="1396336058129570886">"Razdvojeni zaslon"</string> <string name="more_button_text" msgid="3655388105592893530">"Više"</string> <string name="float_button_text" msgid="9221657008391364581">"Plutajući"</string> + <string name="select_text" msgid="5139083974039906583">"Odaberite"</string> + <string name="screenshot_text" msgid="1477704010087786671">"Snimka zaslona"</string> + <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string> + <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite izbornik"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml index ee7ff866e79d..28536e67952f 100644 --- a/libs/WindowManager/Shell/res/values-hu/strings.xml +++ b/libs/WindowManager/Shell/res/values-hu/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Felső 50%-ra"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Felső 30%-ra"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Alsó teljes képernyőre"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Osztás a képernyő bal oldalán"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Osztás a képernyő jobb oldalán"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Osztás a képernyő tetején"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Osztás alul"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Egykezes mód használata"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"A kilépéshez csúsztasson felfelé a képernyő aljáról, vagy koppintson az alkalmazás felett a képernyő bármelyik részére"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Egykezes mód indítása"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Bezárás"</string> <string name="back_button_text" msgid="1469718707134137085">"Vissza"</string> <string name="handle_text" msgid="1766582106752184456">"Fogópont"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Teljes képernyő"</string> <string name="desktop_text" msgid="1077633567027630454">"Asztali üzemmód"</string> <string name="split_screen_text" msgid="1396336058129570886">"Osztott képernyő"</string> <string name="more_button_text" msgid="3655388105592893530">"Továbbiak"</string> <string name="float_button_text" msgid="9221657008391364581">"Lebegő"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index 4538cec37ec1..bd3508482f7c 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Վերևի էկրանը՝ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Վերևի էկրանը՝ 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ներքևի էկրանը՝ լիաէկրան"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Հավելվածը ձախ կողմում"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Հավելվածը աջ կողմում"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Հավելվածը վերևում"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Հավելվածը ներքևում"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Ինչպես օգտվել մեկ ձեռքի ռեժիմից"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Դուրս գալու համար մատը սահեցրեք էկրանի ներքևից վերև կամ հպեք հավելվածի վերևում որևէ տեղ։"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Գործարկել մեկ ձեռքի ռեժիմը"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Փակել"</string> <string name="back_button_text" msgid="1469718707134137085">"Հետ"</string> <string name="handle_text" msgid="1766582106752184456">"Նշիչ"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Լիաէկրան"</string> <string name="desktop_text" msgid="1077633567027630454">"Համակարգչի ռեժիմ"</string> <string name="split_screen_text" msgid="1396336058129570886">"Տրոհված էկրան"</string> <string name="more_button_text" msgid="3655388105592893530">"Ավելին"</string> <string name="float_button_text" msgid="9221657008391364581">"Լողացող պատուհան"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index 6880d53a0bd7..6f859ed8ef29 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Atas 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Atas 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Layar penuh di bawah"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Pisahkan ke kiri"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Pisahkan ke kanan"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Pisahkan ke atas"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Pisahkan ke bawah"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Menggunakan mode satu tangan"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Untuk keluar, geser layar dari bawah ke atas atau ketuk di mana saja di atas aplikasi"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Mulai mode satu tangan"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Tutup"</string> <string name="back_button_text" msgid="1469718707134137085">"Kembali"</string> <string name="handle_text" msgid="1766582106752184456">"Tuas"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Layar Penuh"</string> <string name="desktop_text" msgid="1077633567027630454">"Mode Desktop"</string> <string name="split_screen_text" msgid="1396336058129570886">"Layar Terpisah"</string> <string name="more_button_text" msgid="3655388105592893530">"Lainnya"</string> <string name="float_button_text" msgid="9221657008391364581">"Mengambang"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index 23c93a3faa43..b17abf593cd7 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Efri 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Efri 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Neðri á öllum skjánum"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Skipta vinstra megin"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Skipta hægra megin"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Skipta efst"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Skipta neðst"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Notkun einhentrar stillingar"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Til að loka skaltu strjúka upp frá neðri hluta skjásins eða ýta hvar sem er fyrir ofan forritið"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Ræsa einhenta stillingu"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Loka"</string> <string name="back_button_text" msgid="1469718707134137085">"Til baka"</string> <string name="handle_text" msgid="1766582106752184456">"Handfang"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Allur skjárinn"</string> <string name="desktop_text" msgid="1077633567027630454">"Skjáborðsstilling"</string> <string name="split_screen_text" msgid="1396336058129570886">"Skjáskipting"</string> <string name="more_button_text" msgid="3655388105592893530">"Meira"</string> <string name="float_button_text" msgid="9221657008391364581">"Reikult"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index ece92cf9c922..28e274bce7d6 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Schermata superiore al 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Schermata superiore al 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Schermata inferiore a schermo intero"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Dividi a sinistra"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Dividi a destra"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Dividi in alto"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividi in basso"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Usare la modalità a una mano"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Per uscire, scorri verso l\'alto dalla parte inferiore dello schermo oppure tocca un punto qualsiasi sopra l\'app"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Avvia la modalità a una mano"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Chiudi"</string> <string name="back_button_text" msgid="1469718707134137085">"Indietro"</string> <string name="handle_text" msgid="1766582106752184456">"Handle"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Schermo intero"</string> <string name="desktop_text" msgid="1077633567027630454">"Modalità desktop"</string> <string name="split_screen_text" msgid="1396336058129570886">"Schermo diviso"</string> <string name="more_button_text" msgid="3655388105592893530">"Altro"</string> <string name="float_button_text" msgid="9221657008391364581">"Mobile"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index 948137f770f6..497e0b0c7884 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"עליון 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"למעלה 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"מסך תחתון מלא"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"פיצול שמאלה"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"פיצול ימינה"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"פיצול למעלה"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"פיצול למטה"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"איך להשתמש בתכונה \'מצב שימוש ביד אחת\'"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"כדי לצאת, יש להחליק למעלה מתחתית המסך או להקיש במקום כלשהו במסך מעל האפליקציה"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"הפעלה של מצב שימוש ביד אחת"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"סגירה"</string> <string name="back_button_text" msgid="1469718707134137085">"חזרה"</string> <string name="handle_text" msgid="1766582106752184456">"נקודת אחיזה"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"מסך מלא"</string> <string name="desktop_text" msgid="1077633567027630454">"ממשק המחשב"</string> <string name="split_screen_text" msgid="1396336058129570886">"מסך מפוצל"</string> <string name="more_button_text" msgid="3655388105592893530">"עוד"</string> <string name="float_button_text" msgid="9221657008391364581">"בלונים"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index 9fdb86100b2e..7f7cd940619d 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"上 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"上 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"下部全画面"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"左に分割"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"右に分割"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"上に分割"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"下に分割"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"片手モードの使用"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"終了するには、画面を下から上にスワイプするか、アプリの任意の場所をタップします"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"片手モードを開始します"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"閉じる"</string> <string name="back_button_text" msgid="1469718707134137085">"戻る"</string> <string name="handle_text" msgid="1766582106752184456">"ハンドル"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"全画面表示"</string> <string name="desktop_text" msgid="1077633567027630454">"デスクトップ モード"</string> <string name="split_screen_text" msgid="1396336058129570886">"分割画面"</string> <string name="more_button_text" msgid="3655388105592893530">"その他"</string> <string name="float_button_text" msgid="9221657008391364581">"フローティング"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml index d827f1967458..deec26db2a8d 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ზედა ეკრანი — 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ზედა ეკრანი — 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ქვედა ნაწილის სრულ ეკრანზე გაშლა"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"გაყოფა მარცხნივ"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"გაყოფა მარჯვნივ"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"გაყოფა ზემოთ"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"გაყოფა ქვემოთ"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ცალი ხელის რეჟიმის გამოყენება"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"გასასვლელად გადაფურცლეთ ეკრანის ქვედა კიდიდან ზემოთ ან შეეხეთ ნებისმიერ ადგილას აპის ზემოთ"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ცალი ხელის რეჟიმის დაწყება"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"დახურვა"</string> <string name="back_button_text" msgid="1469718707134137085">"უკან"</string> <string name="handle_text" msgid="1766582106752184456">"იდენტიფიკატორი"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"სრულ ეკრანზე"</string> <string name="desktop_text" msgid="1077633567027630454">"დესკტოპის რეჟიმი"</string> <string name="split_screen_text" msgid="1396336058129570886">"ეკრანის გაყოფა"</string> <string name="more_button_text" msgid="3655388105592893530">"სხვა"</string> <string name="float_button_text" msgid="9221657008391364581">"ფარფატი"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index b0b03755c7ca..d429ba95df18 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% жоғарғы жақта"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30% жоғарғы жақта"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Төменгісін толық экранға шығару"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Сол жақтан шығару"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Оң жақтан шығару"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Жоғарыдан шығару"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Астынан шығару"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Бір қолмен енгізу режимін пайдалану"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Шығу үшін экранның төменгі жағынан жоғары қарай сырғытыңыз немесе қолданбаның үстінен кез келген жерден түртіңіз."</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Бір қолмен енгізу режимін іске қосу"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Жабу"</string> <string name="back_button_text" msgid="1469718707134137085">"Артқа"</string> <string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Толық экран"</string> <string name="desktop_text" msgid="1077633567027630454">"Компьютер режимі"</string> <string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлу"</string> <string name="more_button_text" msgid="3655388105592893530">"Қосымша"</string> <string name="float_button_text" msgid="9221657008391364581">"Қалқыма"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml index 3783067d1dd5..bfcf40bad5ef 100644 --- a/libs/WindowManager/Shell/res/values-km/strings.xml +++ b/libs/WindowManager/Shell/res/values-km/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ខាងលើ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ខាងលើ 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"អេក្រង់ពេញខាងក្រោម"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"បំបែកខាងឆ្វេង"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"បំបែកខាងស្ដាំ"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"បំបែកខាងលើ"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"បំបែកខាងក្រោម"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"កំពុងប្រើមុខងារប្រើដៃម្ខាង"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"ដើម្បីចាកចេញ សូមអូសឡើងលើពីផ្នែកខាងក្រោមអេក្រង់ ឬចុចផ្នែកណាមួយនៅខាងលើកម្មវិធី"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ចាប់ផ្ដើមមុខងារប្រើដៃម្ខាង"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"បិទ"</string> <string name="back_button_text" msgid="1469718707134137085">"ថយក្រោយ"</string> <string name="handle_text" msgid="1766582106752184456">"ឈ្មោះអ្នកប្រើប្រាស់"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"អេក្រង់ពេញ"</string> <string name="desktop_text" msgid="1077633567027630454">"មុខងារកុំព្យូទ័រ"</string> <string name="split_screen_text" msgid="1396336058129570886">"មុខងារបំបែកអេក្រង់"</string> <string name="more_button_text" msgid="3655388105592893530">"ច្រើនទៀត"</string> <string name="float_button_text" msgid="9221657008391364581">"អណ្ដែត"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml index 45fd76fdaa44..9d2515c396eb 100644 --- a/libs/WindowManager/Shell/res/values-kn/strings.xml +++ b/libs/WindowManager/Shell/res/values-kn/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% ಮೇಲಕ್ಕೆ"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30% ಮೇಲಕ್ಕೆ"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ಕೆಳಗಿನ ಪೂರ್ಣ ಪರದೆ"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"ಎಡಕ್ಕೆ ವಿಭಜಿಸಿ"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"ಬಲಕ್ಕೆ ವಿಭಜಿಸಿ"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"ಮೇಲಕ್ಕೆ ವಿಭಜಿಸಿ"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"ಕೆಳಕ್ಕೆ ವಿಭಜಿಸಿ"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ಒಂದು ಕೈ ಮೋಡ್ ಬಳಸುವುದರ ಬಗ್ಗೆ"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"ನಿರ್ಗಮಿಸಲು, ಸ್ಕ್ರೀನ್ನ ಕೆಳಗಿನಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಅಥವಾ ಆ್ಯಪ್ನ ಮೇಲೆ ಎಲ್ಲಿಯಾದರೂ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ಒಂದು ಕೈ ಮೋಡ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"ಮುಚ್ಚಿರಿ"</string> <string name="back_button_text" msgid="1469718707134137085">"ಹಿಂದಕ್ಕೆ"</string> <string name="handle_text" msgid="1766582106752184456">"ಹ್ಯಾಂಡಲ್"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"ಫುಲ್ಸ್ಕ್ರೀನ್"</string> <string name="desktop_text" msgid="1077633567027630454">"ಡೆಸ್ಕ್ಟಾಪ್ ಮೋಡ್"</string> <string name="split_screen_text" msgid="1396336058129570886">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್"</string> <string name="more_button_text" msgid="3655388105592893530">"ಇನ್ನಷ್ಟು"</string> <string name="float_button_text" msgid="9221657008391364581">"ಫ್ಲೋಟ್"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index 0ee1feb979e5..55007fc3de0a 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"위쪽 화면 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"위쪽 화면 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"아래쪽 화면 전체화면"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"왼쪽으로 분할"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"오른쪽으로 분할"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"위쪽으로 분할"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"아래쪽으로 분할"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"한 손 사용 모드 사용하기"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"화면 하단에서 위로 스와이프하거나 앱 상단을 탭하여 종료합니다."</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"한 손 사용 모드 시작"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"닫기"</string> <string name="back_button_text" msgid="1469718707134137085">"뒤로"</string> <string name="handle_text" msgid="1766582106752184456">"핸들"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"전체 화면"</string> <string name="desktop_text" msgid="1077633567027630454">"데스크톱 모드"</string> <string name="split_screen_text" msgid="1396336058129570886">"화면 분할"</string> <string name="more_button_text" msgid="3655388105592893530">"더보기"</string> <string name="float_button_text" msgid="9221657008391364581">"플로팅"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml index 6798f498c579..9691dbae4bbc 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Үстүнкү экранды 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Үстүнкү экранды 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ылдыйкы экранды толук экран режимине өткөрүү"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Солго бөлүү"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Оңго бөлүү"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Өйдө бөлүү"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Ылдый бөлүү"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Бир кол режимин колдонуу"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Чыгуу үчүн экранды ылдый жагынан өйдө сүрүңүз же колдонмонун өйдө жагын басыңыз"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Бир кол режимин баштоо"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Жабуу"</string> <string name="back_button_text" msgid="1469718707134137085">"Артка"</string> <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Толук экран"</string> <string name="desktop_text" msgid="1077633567027630454">"Компьютер режими"</string> <string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлүү"</string> <string name="more_button_text" msgid="3655388105592893530">"Дагы"</string> <string name="float_button_text" msgid="9221657008391364581">"Калкыма"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index b758c0cb7c8a..678e0859272a 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ເທິງສຸດ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ເທິງສຸດ 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ເຕັມໜ້າຈໍລຸ່ມສຸດ"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"ແຍກຊ້າຍ"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"ແຍກຂວາ"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"ແຍກເທິງ"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"ແຍກລຸ່ມ"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ກຳລັງໃຊ້ໂໝດມືດຽວ"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"ເພື່ອອອກ, ໃຫ້ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍ ຫຼື ແຕະບ່ອນໃດກໍໄດ້ຢູ່ເໜືອແອັບ"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ເລີ່ມໂໝດມືດຽວ"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"ປິດ"</string> <string name="back_button_text" msgid="1469718707134137085">"ກັບຄືນ"</string> <string name="handle_text" msgid="1766582106752184456">"ມືບັງຄັບ"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"ເຕັມຈໍ"</string> <string name="desktop_text" msgid="1077633567027630454">"ໂໝດເດັສທັອບ"</string> <string name="split_screen_text" msgid="1396336058129570886">"ແບ່ງໜ້າຈໍ"</string> <string name="more_button_text" msgid="3655388105592893530">"ເພີ່ມເຕີມ"</string> <string name="float_button_text" msgid="9221657008391364581">"ລອຍ"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index 84f42640b185..f8a2a0fc0671 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Viršutinis ekranas 50 %"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Viršutinis ekranas 30 %"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Apatinis ekranas viso ekrano režimu"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Išskaidyti kairėn"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Išskaidyti dešinėn"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Išskaidyti viršuje"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Išskaidyti apačioje"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Vienos rankos režimo naudojimas"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Jei norite išeiti, perbraukite aukštyn nuo ekrano apačios arba palieskite bet kur virš programos"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Pradėti vienos rankos režimą"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Uždaryti"</string> <string name="back_button_text" msgid="1469718707134137085">"Atgal"</string> <string name="handle_text" msgid="1766582106752184456">"Rankenėlė"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Visas ekranas"</string> <string name="desktop_text" msgid="1077633567027630454">"Stalinio kompiuterio režimas"</string> <string name="split_screen_text" msgid="1396336058129570886">"Išskaidyto ekrano režimas"</string> <string name="more_button_text" msgid="3655388105592893530">"Daugiau"</string> <string name="float_button_text" msgid="9221657008391364581">"Slankusis langas"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index bac75e3a5141..d14bb67936d3 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Augšdaļa 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Augšdaļa 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Apakšdaļu pa visu ekrānu"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Sadalījums pa kreisi"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Sadalījums pa labi"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Sadalījums augšdaļā"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Sadalījums apakšdaļā"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Vienas rokas režīma izmantošana"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Lai izietu, velciet augšup no ekrāna apakšdaļas vai pieskarieties jebkurā vietā virs lietotnes"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Pāriet vienas rokas režīmā"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Aizvērt"</string> <string name="back_button_text" msgid="1469718707134137085">"Atpakaļ"</string> <string name="handle_text" msgid="1766582106752184456">"Turis"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Pilnekrāna režīms"</string> <string name="desktop_text" msgid="1077633567027630454">"Darbvirsmas režīms"</string> <string name="split_screen_text" msgid="1396336058129570886">"Sadalīt ekrānu"</string> <string name="more_button_text" msgid="3655388105592893530">"Vairāk"</string> <string name="float_button_text" msgid="9221657008391364581">"Peldošs"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml index b96f8a1a5e5c..45aeb7f332b0 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings.xml @@ -100,9 +100,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Затвори"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> <string name="handle_text" msgid="1766582106752184456">"Прекар"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Цел екран"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим за компјутер"</string> <string name="split_screen_text" msgid="1396336058129570886">"Поделен екран"</string> <string name="more_button_text" msgid="3655388105592893530">"Повеќе"</string> <string name="float_button_text" msgid="9221657008391364581">"Лебдечко"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml index f67e7abe5b63..ca5f0f7c4941 100644 --- a/libs/WindowManager/Shell/res/values-ml/strings.xml +++ b/libs/WindowManager/Shell/res/values-ml/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"മുകളിൽ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"മുകളിൽ 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"താഴെ പൂർണ്ണ സ്ക്രീൻ"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"ഇടത് ഭാഗത്തേക്ക് വിഭജിക്കുക"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"വലത് ഭാഗത്തേക്ക് വിഭജിക്കുക"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"മുകളിലേക്ക് വിഭജിക്കുക"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"താഴേക്ക് വിഭജിക്കുക"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ഒറ്റക്കൈ മോഡ് എങ്ങനെ ഉപയോഗിക്കാം"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"പുറത്ത് കടക്കാൻ, സ്ക്രീനിന്റെ ചുവടെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക അല്ലെങ്കിൽ ആപ്പിന് മുകളിലായി എവിടെയെങ്കിലും ടാപ്പ് ചെയ്യുക"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ഒറ്റക്കൈ മോഡ് ആരംഭിച്ചു"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"അടയ്ക്കുക"</string> <string name="back_button_text" msgid="1469718707134137085">"മടങ്ങുക"</string> <string name="handle_text" msgid="1766582106752184456">"ഹാൻഡിൽ"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"പൂർണ്ണസ്ക്രീൻ"</string> <string name="desktop_text" msgid="1077633567027630454">"ഡെസ്ക്ടോപ്പ് മോഡ്"</string> <string name="split_screen_text" msgid="1396336058129570886">"സ്ക്രീൻ വിഭജനം"</string> <string name="more_button_text" msgid="3655388105592893530">"കൂടുതൽ"</string> <string name="float_button_text" msgid="9221657008391364581">"ഫ്ലോട്ട്"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml index 00846ef749cd..9678c5c7190e 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Дээд 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Дээд 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Доод бүтэн дэлгэц"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Зүүн талд хуваах"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Баруун талд хуваах"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Дээд талд хуваах"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Доод талд хуваах"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Нэг гарын горимыг ашиглаж байна"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Гарахын тулд дэлгэцийн доод хэсгээс дээш шударч эсвэл апп дээр хүссэн газраа товшино уу"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Нэг гарын горимыг эхлүүлэх"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Хаах"</string> <string name="back_button_text" msgid="1469718707134137085">"Буцах"</string> <string name="handle_text" msgid="1766582106752184456">"Бариул"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Бүтэн дэлгэц"</string> <string name="desktop_text" msgid="1077633567027630454">"Дэлгэцийн горим"</string> <string name="split_screen_text" msgid="1396336058129570886">"Дэлгэцийг хуваах"</string> <string name="more_button_text" msgid="3655388105592893530">"Бусад"</string> <string name="float_button_text" msgid="9221657008391364581">"Хөвөгч"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml index 888e8ddcd0c9..ea728e844cb7 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"शीर्ष 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"शीर्ष 10"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"तळाशी फुल स्क्रीन"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"डावीकडे स्प्लिट करा"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"उजवीकडे स्प्लिट करा"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"सर्वात वरती स्प्लिट करा"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"खालती स्प्लिट करा"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"एकहाती मोड वापरणे"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"बाहेर पडण्यासाठी स्क्रीनच्या खालून वरच्या दिशेने स्वाइप करा किंवा ॲपवर कोठेही टॅप करा"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"एकहाती मोड सुरू करा"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"बंद करा"</string> <string name="back_button_text" msgid="1469718707134137085">"मागे जा"</string> <string name="handle_text" msgid="1766582106752184456">"हँडल"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"फुलस्क्रीन"</string> <string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string> <string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन"</string> <string name="more_button_text" msgid="3655388105592893530">"आणखी"</string> <string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml index d4a659ba9ae9..8a9b81c9e333 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Atas 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Atas 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Skrin penuh bawah"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Pisah kiri"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Pisah kanan"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Pisah atas"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Pisah bawah"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Menggunakan mod sebelah tangan"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Untuk keluar, leret ke atas daripada bahagian bawah skrin atau ketik pada mana-mana di bahagian atas apl"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Mulakan mod sebelah tangan"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Tutup"</string> <string name="back_button_text" msgid="1469718707134137085">"Kembali"</string> <string name="handle_text" msgid="1766582106752184456">"Pemegang"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Skrin penuh"</string> <string name="desktop_text" msgid="1077633567027630454">"Mod Desktop"</string> <string name="split_screen_text" msgid="1396336058129570886">"Skrin Pisah"</string> <string name="more_button_text" msgid="3655388105592893530">"Lagi"</string> <string name="float_button_text" msgid="9221657008391364581">"Terapung"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml index 6f8b3c7c54a8..b37bfa7fcaf6 100644 --- a/libs/WindowManager/Shell/res/values-my/strings.xml +++ b/libs/WindowManager/Shell/res/values-my/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"အပေါ်ဘက် မျက်နှာပြင် ၅၀%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"အပေါ်ဘက် မျက်နှာပြင် ၃၀%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"အောက်ခြေ မျက်နှာပြင်အပြည့်"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"ဘယ်ဘက်ကို ခွဲရန်"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"ညာဘက်ကို ခွဲရန်"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"ထိပ်ပိုင်းကို ခွဲရန်"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"အောက်ခြေကို ခွဲရန်"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"လက်တစ်ဖက်သုံးမုဒ် အသုံးပြုခြင်း"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"ထွက်ရန် ဖန်သားပြင်၏အောက်ခြေမှ အပေါ်သို့ပွတ်ဆွဲပါ သို့မဟုတ် အက်ပ်အပေါ်ဘက် မည်သည့်နေရာတွင်မဆို တို့ပါ"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"လက်တစ်ဖက်သုံးမုဒ်ကို စတင်လိုက်သည်"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"ပိတ်ရန်"</string> <string name="back_button_text" msgid="1469718707134137085">"နောက်သို့"</string> <string name="handle_text" msgid="1766582106752184456">"သုံးသူအမည်"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"ဖန်သားပြင်အပြည့်"</string> <string name="desktop_text" msgid="1077633567027630454">"ဒက်စ်တော့မုဒ်"</string> <string name="split_screen_text" msgid="1396336058129570886">"မျက်နှာပြင် ခွဲ၍ပြသရန်"</string> <string name="more_button_text" msgid="3655388105592893530">"ပိုပြပါ"</string> <string name="float_button_text" msgid="9221657008391364581">"မျှောရန်"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index 1ea390757b6c..7c96f0d681a8 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Sett størrelsen på den øverste delen av skjermen til 50 %"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Sett størrelsen på den øverste delen av skjermen til 30 %"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Utvid den nederste delen av skjermen til hele skjermen"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Del opp til venstre"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Del opp til høyre"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Del opp øverst"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Del opp nederst"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Bruk av enhåndsmodus"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"For å avslutte, sveip opp fra bunnen av skjermen eller trykk hvor som helst over appen"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Start enhåndsmodus"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Lukk"</string> <string name="back_button_text" msgid="1469718707134137085">"Tilbake"</string> <string name="handle_text" msgid="1766582106752184456">"Håndtak"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Fullskjerm"</string> <string name="desktop_text" msgid="1077633567027630454">"Skrivebordmodus"</string> <string name="split_screen_text" msgid="1396336058129570886">"Delt skjerm"</string> <string name="more_button_text" msgid="3655388105592893530">"Mer"</string> <string name="float_button_text" msgid="9221657008391364581">"Svevende"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml index fd3485c8396a..8a89d4c2c05f 100644 --- a/libs/WindowManager/Shell/res/values-ne/strings.xml +++ b/libs/WindowManager/Shell/res/values-ne/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"माथिल्लो भाग ५०%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"माथिल्लो भाग ३०%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"तल्लो भाग फुल स्क्रिन"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"बायाँतिर स्प्लिट गर्नुहोस्"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"दायाँतिर स्प्लिट गर्नुहोस्"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"सिरानतिर स्प्लिट गर्नुहोस्"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"पुछारतिर स्प्लिट गर्नुहोस्"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"एक हाते मोड प्रयोग गरिँदै छ"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"बाहिर निस्कन, स्क्रिनको पुछारबाट माथितिर स्वाइप गर्नुहोस् वा एपभन्दा माथि जुनसुकै ठाउँमा ट्याप गर्नुहोस्"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"एक हाते मोड सुरु गर्नुहोस्"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"बन्द गर्नुहोस्"</string> <string name="back_button_text" msgid="1469718707134137085">"पछाडि"</string> <string name="handle_text" msgid="1766582106752184456">"ह्यान्डल"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"फुल स्क्रिन"</string> <string name="desktop_text" msgid="1077633567027630454">"डेस्कटप मोड"</string> <string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रिन"</string> <string name="more_button_text" msgid="3655388105592893530">"थप"</string> <string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml index c3ab297c899d..1f0b6d233dcd 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Bovenste scherm 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Bovenste scherm 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Onderste scherm op volledig scherm"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Gesplitst scherm links"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Gesplitst scherm rechts"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Gesplitst scherm boven"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Gesplitst scherm onder"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Bediening met 1 hand gebruiken"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Als je wilt afsluiten, swipe je omhoog vanaf de onderkant van het scherm of tik je ergens boven de app"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Bediening met 1 hand starten"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Sluiten"</string> <string name="back_button_text" msgid="1469718707134137085">"Terug"</string> <string name="handle_text" msgid="1766582106752184456">"Gebruikersnaam"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Volledig scherm"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string> <string name="split_screen_text" msgid="1396336058129570886">"Gesplitst scherm"</string> <string name="more_button_text" msgid="3655388105592893530">"Meer"</string> <string name="float_button_text" msgid="9221657008391364581">"Zwevend"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml index 90c90d316c78..edfe3f01e6bc 100644 --- a/libs/WindowManager/Shell/res/values-or/strings.xml +++ b/libs/WindowManager/Shell/res/values-or/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ଉପର ଆଡ଼କୁ 50% କରନ୍ତୁ"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ଉପର ଆଡ଼କୁ 30% କରନ୍ତୁ"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ତଳ ଅଂଶର ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"ବାମପଟକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"ଡାହାଣପଟକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"ଶୀର୍ଷକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"ନିମ୍ନକୁ ସ୍ଲିଟ କରନ୍ତୁ"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ଏକ-ହାତ ମୋଡ୍ ବ୍ୟବହାର କରି"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"ବାହାରି ଯିବା ପାଇଁ, ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ କିମ୍ବା ଆପରେ ଯେ କୌଣସି ସ୍ଥାନରେ ଟାପ୍ କରନ୍ତୁ"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ଏକ-ହାତ ମୋଡ୍ ଆରମ୍ଭ କରନ୍ତୁ"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"ବନ୍ଦ କରନ୍ତୁ"</string> <string name="back_button_text" msgid="1469718707134137085">"ପଛକୁ ଫେରନ୍ତୁ"</string> <string name="handle_text" msgid="1766582106752184456">"ହେଣ୍ଡେଲ"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"ପୂର୍ଣ୍ଣସ୍କ୍ରିନ"</string> <string name="desktop_text" msgid="1077633567027630454">"ଡେସ୍କଟପ ମୋଡ"</string> <string name="split_screen_text" msgid="1396336058129570886">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ"</string> <string name="more_button_text" msgid="3655388105592893530">"ଅଧିକ"</string> <string name="float_button_text" msgid="9221657008391364581">"ଫ୍ଲୋଟ"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index b27e034fd655..8c2ad2231d19 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ਉੱਪਰ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ਉੱਪਰ 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ਹੇਠਾਂ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"ਖੱਬੇ ਪਾਸੇ ਵੰਡੋ"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"ਸੱਜੇ ਪਾਸੇ ਵੰਡੋ"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"ਸਿਖਰ \'ਤੇ ਵੰਡੋ"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"ਹੇਠਾਂ ਵੰਡੋ"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ਇੱਕ ਹੱਥ ਮੋਡ ਵਰਤਣਾ"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"ਬਾਹਰ ਜਾਣ ਲਈ, ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ ਜਾਂ ਐਪ \'ਤੇ ਕਿਤੇ ਵੀ ਟੈਪ ਕਰੋ"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ਇੱਕ ਹੱਥ ਮੋਡ ਸ਼ੁਰੂ ਕਰੋ"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string> <string name="back_button_text" msgid="1469718707134137085">"ਪਿੱਛੇ"</string> <string name="handle_text" msgid="1766582106752184456">"ਹੈਂਡਲ"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"ਪੂਰੀ-ਸਕ੍ਰੀਨ"</string> <string name="desktop_text" msgid="1077633567027630454">"ਡੈਸਕਟਾਪ ਮੋਡ"</string> <string name="split_screen_text" msgid="1396336058129570886">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ"</string> <string name="more_button_text" msgid="3655388105592893530">"ਹੋਰ"</string> <string name="float_button_text" msgid="9221657008391364581">"ਫ਼ਲੋਟ"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index 6d00aaa1f17e..191f6decebad 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% górnej części ekranu"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30% górnej części ekranu"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Dolna część ekranu na pełnym ekranie"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Podziel po lewej"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Podziel po prawej"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Podziel u góry"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Podziel u dołu"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Korzystanie z trybu jednej ręki"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Aby zamknąć, przesuń palcem z dołu ekranu w górę lub kliknij dowolne miejsce nad aplikacją"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Uruchom tryb jednej ręki"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Zamknij"</string> <string name="back_button_text" msgid="1469718707134137085">"Wstecz"</string> <string name="handle_text" msgid="1766582106752184456">"Uchwyt"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Pełny ekran"</string> <string name="desktop_text" msgid="1077633567027630454">"Tryb pulpitu"</string> <string name="split_screen_text" msgid="1396336058129570886">"Podzielony ekran"</string> <string name="more_button_text" msgid="3655388105592893530">"Więcej"</string> <string name="float_button_text" msgid="9221657008391364581">"Pływające"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml index b2f3121fd98b..82409f40f8cf 100644 --- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Parte superior a 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Parte superior a 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Parte inferior em tela cheia"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir para a esquerda"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir para a direita"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir para cima"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir para baixo"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Como usar o modo para uma mão"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para sair, deslize de baixo para cima na tela ou toque em qualquer lugar acima do app"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar o modo para uma mão"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Fechar"</string> <string name="back_button_text" msgid="1469718707134137085">"Voltar"</string> <string name="handle_text" msgid="1766582106752184456">"Alça"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string> <string name="split_screen_text" msgid="1396336058129570886">"Tela dividida"</string> <string name="more_button_text" msgid="3655388105592893530">"Mais"</string> <string name="float_button_text" msgid="9221657008391364581">"Ponto flutuante"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index 3f3be4bc8943..f33a0ecedcaa 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% no ecrã superior"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30% no ecrã superior"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ecrã inferior inteiro"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Divisão à esquerda"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Divisão à direita"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Divisão na parte superior"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Divisão na parte inferior"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Utilize o modo para uma mão"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para sair, deslize rapidamente para cima a partir da parte inferior do ecrã ou toque em qualquer ponto acima da app."</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar o modo para uma mão"</string> @@ -100,9 +96,14 @@ <string name="close_button_text" msgid="2913281996024033299">"Fechar"</string> <string name="back_button_text" msgid="1469718707134137085">"Anterior"</string> <string name="handle_text" msgid="1766582106752184456">"Indicador"</string> + <string name="app_icon_text" msgid="2823268023931811747">"Ícone da app"</string> <string name="fullscreen_text" msgid="1162316685217676079">"Ecrã inteiro"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo de ambiente de trabalho"</string> <string name="split_screen_text" msgid="1396336058129570886">"Ecrã dividido"</string> <string name="more_button_text" msgid="3655388105592893530">"Mais"</string> <string name="float_button_text" msgid="9221657008391364581">"Flutuar"</string> + <string name="select_text" msgid="5139083974039906583">"Selecionar"</string> + <string name="screenshot_text" msgid="1477704010087786671">"Captura de ecrã"</string> + <string name="close_text" msgid="4986518933445178928">"Fechar"</string> + <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml index b2f3121fd98b..82409f40f8cf 100644 --- a/libs/WindowManager/Shell/res/values-pt/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Parte superior a 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Parte superior a 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Parte inferior em tela cheia"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir para a esquerda"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir para a direita"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir para cima"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir para baixo"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Como usar o modo para uma mão"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para sair, deslize de baixo para cima na tela ou toque em qualquer lugar acima do app"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar o modo para uma mão"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Fechar"</string> <string name="back_button_text" msgid="1469718707134137085">"Voltar"</string> <string name="handle_text" msgid="1766582106752184456">"Alça"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string> <string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string> <string name="split_screen_text" msgid="1396336058129570886">"Tela dividida"</string> <string name="more_button_text" msgid="3655388105592893530">"Mais"</string> <string name="float_button_text" msgid="9221657008391364581">"Ponto flutuante"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml index 402ef6b1834c..29297f4b55bd 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Partea de sus: 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Partea de sus: 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Partea de jos pe ecran complet"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Împarte în stânga"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Împarte în dreapta"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Împarte în sus"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Împarte în jos"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Folosirea modului cu o mână"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Pentru a ieși, glisează în sus din partea de jos a ecranului sau atinge oriunde deasupra ferestrei aplicației"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Activează modul cu o mână"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Închide"</string> <string name="back_button_text" msgid="1469718707134137085">"Înapoi"</string> <string name="handle_text" msgid="1766582106752184456">"Ghidaj"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Ecran complet"</string> <string name="desktop_text" msgid="1077633567027630454">"Modul desktop"</string> <string name="split_screen_text" msgid="1396336058129570886">"Ecran împărțit"</string> <string name="more_button_text" msgid="3655388105592893530">"Mai multe"</string> <string name="float_button_text" msgid="9221657008391364581">"Flotantă"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml index dd595455963b..de0bcf4da82a 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Верхний на 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Верхний на 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Нижний во весь экран"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Приложение слева"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Приложение справа"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Приложение сверху"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Приложение снизу"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Использование режима управления одной рукой"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Чтобы выйти, проведите по экрану снизу вверх или коснитесь области за пределами приложения."</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Запустить режим управления одной рукой"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Закрыть"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Полноэкранный режим"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим компьютера"</string> <string name="split_screen_text" msgid="1396336058129570886">"Разделить экран"</string> <string name="more_button_text" msgid="3655388105592893530">"Ещё"</string> <string name="float_button_text" msgid="9221657008391364581">"Плавающее окно"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index 91342c483a5d..849dbac4c485 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ඉහළම 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ඉහළම 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"පහළ පූර්ණ තිරය"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"වම බෙදන්න"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"දකුණ බෙදන්න"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"ඉහළ බෙදන්න"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"පහළ බෙදන්න"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"තනි-අත් ප්රකාරය භාවිත කරමින්"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"පිටවීමට, තිරයේ පහළ සිට ඉහළට ස්වයිප් කරන්න හෝ යෙදුමට ඉහළින් ඕනෑම තැනක තට්ටු කරන්න"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"තනි අත් ප්රකාරය ආරම්භ කරන්න"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string> <string name="back_button_text" msgid="1469718707134137085">"ආපසු"</string> <string name="handle_text" msgid="1766582106752184456">"හැඬලය"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"පූර්ණ තිරය"</string> <string name="desktop_text" msgid="1077633567027630454">"ඩෙස්ක්ටොප් ප්රකාරය"</string> <string name="split_screen_text" msgid="1396336058129570886">"බෙදුම් තිරය"</string> <string name="more_button_text" msgid="3655388105592893530">"තව"</string> <string name="float_button_text" msgid="9221657008391364581">"පාවෙන"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml index b9199c2631fd..e86ecded8502 100644 --- a/libs/WindowManager/Shell/res/values-sk/strings.xml +++ b/libs/WindowManager/Shell/res/values-sk/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Horná – 50 %"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Horná – 30 %"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Dolná – na celú obrazovku"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Rozdeliť vľavo"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Rozdeliť vpravo"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Rozdeliť hore"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Rozdeliť dole"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Používanie režimu jednej ruky"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Ukončíte potiahnutím z dolnej časti obrazovky nahor alebo klepnutím kdekoľvek nad aplikáciu"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Spustiť režim jednej ruky"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Zavrieť"</string> <string name="back_button_text" msgid="1469718707134137085">"Späť"</string> <string name="handle_text" msgid="1766582106752184456">"Rukoväť"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string> <string name="desktop_text" msgid="1077633567027630454">"Režim počítača"</string> <string name="split_screen_text" msgid="1396336058129570886">"Rozdelená obrazovka"</string> <string name="more_button_text" msgid="3655388105592893530">"Viac"</string> <string name="float_button_text" msgid="9221657008391364581">"Plávajúce"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml index 0fd44f086029..954e7290163b 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Zgornji 50 %"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Zgornji 30 %"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Spodnji v celozaslonski način"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Delitev levo"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Delitev desno"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Delitev zgoraj"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Delitev spodaj"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Uporaba enoročnega načina"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Za izhod povlecite z dna zaslona navzgor ali se dotaknite na poljubnem mestu nad aplikacijo"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Zagon enoročnega načina"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Zapri"</string> <string name="back_button_text" msgid="1469718707134137085">"Nazaj"</string> <string name="handle_text" msgid="1766582106752184456">"Ročica"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Celozaslonsko"</string> <string name="desktop_text" msgid="1077633567027630454">"Namizni način"</string> <string name="split_screen_text" msgid="1396336058129570886">"Razdeljen zaslon"</string> <string name="more_button_text" msgid="3655388105592893530">"Več"</string> <string name="float_button_text" msgid="9221657008391364581">"Lebdeče"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index 00e63d2e5027..6209ff912cde 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Lart 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Lart 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ekrani i plotë poshtë"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Ndaj majtas"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Ndaj djathtas"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Ndaj lart"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Ndaj në fund"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Po përdor modalitetin e përdorimit me një dorë"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Për të dalë, rrëshqit lart nga fundi i ekranit ose trokit diku mbi aplikacion"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Modaliteti i përdorimit me një dorë"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Mbyll"</string> <string name="back_button_text" msgid="1469718707134137085">"Pas"</string> <string name="handle_text" msgid="1766582106752184456">"Emërtimi"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Ekrani i plotë"</string> <string name="desktop_text" msgid="1077633567027630454">"Modaliteti i desktopit"</string> <string name="split_screen_text" msgid="1396336058129570886">"Ekrani i ndarë"</string> <string name="more_button_text" msgid="3655388105592893530">"Më shumë"</string> <string name="float_button_text" msgid="9221657008391364581">"Pluskuese"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml index d0f689c3236d..f810d3d9890e 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Горњи екран 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Горњи екран 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Режим целог екрана за доњи екран"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Поделите лево"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Поделите десно"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Поделите у врху"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Поделите у дну"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Коришћење режима једном руком"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Да бисте изашли, превуците нагоре од дна екрана или додирните било где изнад апликације"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Покрените режим једном руком"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Затворите"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> <string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Преко целог екрана"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим за рачунаре"</string> <string name="split_screen_text" msgid="1396336058129570886">"Подељени екран"</string> <string name="more_button_text" msgid="3655388105592893530">"Још"</string> <string name="float_button_text" msgid="9221657008391364581">"Плутајуће"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index e3827d6b8278..0e4487102f68 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Övre 50 %"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Övre 30 %"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Helskärm på nedre skärm"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Till vänster på delad skärm"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Till höger på delad skärm"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Upptill på delad skärm"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Nedtill på delad skärm"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Använda enhandsläge"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Avsluta genom att svepa uppåt från skärmens nederkant eller trycka ovanför appen"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Starta enhandsläge"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Stäng"</string> <string name="back_button_text" msgid="1469718707134137085">"Tillbaka"</string> <string name="handle_text" msgid="1766582106752184456">"Handtag"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Helskärm"</string> <string name="desktop_text" msgid="1077633567027630454">"Datorläge"</string> <string name="split_screen_text" msgid="1396336058129570886">"Delad skärm"</string> <string name="more_button_text" msgid="3655388105592893530">"Mer"</string> <string name="float_button_text" msgid="9221657008391364581">"Svävande"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml index 8c2f2ad9e6fe..e167bcab1cdb 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Juu 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Juu 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Skrini nzima ya chini"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Gawanya sehemu ya kushoto"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Gawanya sehemu ya kulia"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Gawanya sehemu ya juu"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Gawanya sehemu ya chini"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Kutumia hali ya kutumia kwa mkono mmoja"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Ili ufunge, telezesha kidole juu kutoka sehemu ya chini ya skrini au uguse mahali popote juu ya programu"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Anzisha hali ya kutumia kwa mkono mmoja"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Funga"</string> <string name="back_button_text" msgid="1469718707134137085">"Rudi nyuma"</string> <string name="handle_text" msgid="1766582106752184456">"Ncha"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Skrini nzima"</string> <string name="desktop_text" msgid="1077633567027630454">"Hali ya Kompyuta ya mezani"</string> <string name="split_screen_text" msgid="1396336058129570886">"Gawa Skrini"</string> <string name="more_button_text" msgid="3655388105592893530">"Zaidi"</string> <string name="float_button_text" msgid="9221657008391364581">"Inayoelea"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml index 4732e391cd56..286d60832db1 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"மேலே 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"மேலே 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"கீழ்ப்புறம் முழுத் திரை"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"இடதுபுறமாகப் பிரிக்கும்"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"வலதுபுறமாகப் பிரிக்கும்"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"மேற்புறமாகப் பிரிக்கும்"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"கீழ்புறமாகப் பிரிக்கும்"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ஒற்றைக் கைப் பயன்முறையைப் பயன்படுத்துதல்"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"வெளியேற, திரையின் கீழிருந்து மேல்நோக்கி ஸ்வைப் செய்யவும் அல்லது ஆப்ஸுக்கு மேலே ஏதேனும் ஓர் இடத்தில் தட்டவும்"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ஒற்றைக் கைப் பயன்முறையைத் தொடங்கும்"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"மூடும்"</string> <string name="back_button_text" msgid="1469718707134137085">"பின்செல்லும்"</string> <string name="handle_text" msgid="1766582106752184456">"ஹேண்டில்"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"முழுத்திரை"</string> <string name="desktop_text" msgid="1077633567027630454">"டெஸ்க்டாப் பயன்முறை"</string> <string name="split_screen_text" msgid="1396336058129570886">"திரையைப் பிரிக்கும்"</string> <string name="more_button_text" msgid="3655388105592893530">"கூடுதல் விருப்பத்தேர்வுகள்"</string> <string name="float_button_text" msgid="9221657008391364581">"மிதக்கும் சாளரம்"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index 093a8487b3e4..ec3ca78cf747 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ఎగువ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ఎగువ 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"దిగువ ఫుల్-స్క్రీన్"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"ఎడమ వైపున్న భాగంలో విభజించండి"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"కుడి వైపున్న భాగంలో విభజించండి"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"ఎగువ భాగంలో విభజించండి"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"దిగువ భాగంలో విభజించండి"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"వన్-హ్యాండెడ్ మోడ్ను ఉపయోగించడం"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"నిష్క్రమించడానికి, స్క్రీన్ కింది భాగం నుండి పైకి స్వైప్ చేయండి లేదా యాప్ పైన ఎక్కడైనా ట్యాప్ చేయండి"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"వన్-హ్యాండెడ్ మోడ్ను ప్రారంభిస్తుంది"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"మూసివేయండి"</string> <string name="back_button_text" msgid="1469718707134137085">"వెనుకకు"</string> <string name="handle_text" msgid="1766582106752184456">"హ్యాండిల్"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"ఫుల్-స్క్రీన్"</string> <string name="desktop_text" msgid="1077633567027630454">"డెస్క్టాప్ మోడ్"</string> <string name="split_screen_text" msgid="1396336058129570886">"స్ప్లిట్ స్క్రీన్"</string> <string name="more_button_text" msgid="3655388105592893530">"మరిన్ని"</string> <string name="float_button_text" msgid="9221657008391364581">"ఫ్లోట్"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml index f7c810b02561..1a9fa1828cf5 100644 --- a/libs/WindowManager/Shell/res/values-th/strings.xml +++ b/libs/WindowManager/Shell/res/values-th/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ด้านบน 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ด้านบน 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"เต็มหน้าจอด้านล่าง"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"แยกไปทางซ้าย"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"แยกไปทางขวา"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"แยกไปด้านบน"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"แยกไปด้านล่าง"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"การใช้โหมดมือเดียว"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"หากต้องการออก ให้เลื่อนขึ้นจากด้านล่างของหน้าจอหรือแตะที่ใดก็ได้เหนือแอป"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"เริ่มโหมดมือเดียว"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"ปิด"</string> <string name="back_button_text" msgid="1469718707134137085">"กลับ"</string> <string name="handle_text" msgid="1766582106752184456">"แฮนเดิล"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"เต็มหน้าจอ"</string> <string name="desktop_text" msgid="1077633567027630454">"โหมดเดสก์ท็อป"</string> <string name="split_screen_text" msgid="1396336058129570886">"แยกหน้าจอ"</string> <string name="more_button_text" msgid="3655388105592893530">"เพิ่มเติม"</string> <string name="float_button_text" msgid="9221657008391364581">"ล่องลอย"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index 4660d6d0c9ee..27c4363eb630 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Gawing 50% ang nasa itaas"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Gawing 30% ang nasa itaas"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"I-full screen ang nasa ibaba"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Hatiin sa kaliwa"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Hatiin sa kanan"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Hatiin sa itaas"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Hatiin sa ilalim"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Paggamit ng one-hand mode"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para lumabas, mag-swipe pataas mula sa ibaba ng screen o mag-tap kahit saan sa itaas ng app"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Simulan ang one-hand mode"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Isara"</string> <string name="back_button_text" msgid="1469718707134137085">"Bumalik"</string> <string name="handle_text" msgid="1766582106752184456">"Handle"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string> <string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string> <string name="more_button_text" msgid="3655388105592893530">"Higit pa"</string> <string name="float_button_text" msgid="9221657008391364581">"Float"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index 6fdfe56c2b36..a9ad92d39ec9 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Üstte %50"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Üstte %30"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Altta tam ekran"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Sol tarafta böl"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Sağ tarafta böl"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Üst tarafta böl"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Alt tarafta böl"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Tek el modunu kullanma"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Çıkmak için ekranın alt kısmından yukarı kaydırın veya uygulamanın üzerinde herhangi bir yere dokunun"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Tek el modunu başlat"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Kapat"</string> <string name="back_button_text" msgid="1469718707134137085">"Geri"</string> <string name="handle_text" msgid="1766582106752184456">"Herkese açık kullanıcı adı"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string> <string name="desktop_text" msgid="1077633567027630454">"Masaüstü Modu"</string> <string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string> <string name="more_button_text" msgid="3655388105592893530">"Daha Fazla"</string> <string name="float_button_text" msgid="9221657008391364581">"Havada Süzülen"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml index c5cfd02eec6c..a9b05d513ec8 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Верхнє вікно на 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Верхнє вікно на 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Нижнє вікно на весь екран"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Розділити зліва"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Розділити справа"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Розділити вгорі"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Розділити внизу"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Як користуватися режимом керування однією рукою"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Щоб вийти, проведіть пальцем по екрану знизу вгору або торкніться екрана над додатком"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Увімкнути режим керування однією рукою"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Закрити"</string> <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"На весь екран"</string> <string name="desktop_text" msgid="1077633567027630454">"Режим комп’ютера"</string> <string name="split_screen_text" msgid="1396336058129570886">"Розділити екран"</string> <string name="more_button_text" msgid="3655388105592893530">"Більше"</string> <string name="float_button_text" msgid="9221657008391364581">"Плаваюче вікно"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml index 9c138d9164b9..1c31a3dbbbe3 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"اوپر %50"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"اوپر %30"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"نچلی فل اسکرین"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"دائیں طرف تقسیم کریں"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"بائیں طرف تقسیم کریں"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"اوپر کی طرف تقسیم کریں"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"نیچے کی طرف تقسیم کریں"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"ایک ہاتھ کی وضع کا استعمال کرنا"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"باہر نکلنے کیلئے، اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں یا ایپ کے اوپر کہیں بھی تھپتھپائیں"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ایک ہاتھ کی وضع شروع کریں"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"بند کریں"</string> <string name="back_button_text" msgid="1469718707134137085">"پیچھے"</string> <string name="handle_text" msgid="1766582106752184456">"ہینڈل"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"مکمل اسکرین"</string> <string name="desktop_text" msgid="1077633567027630454">"ڈیسک ٹاپ موڈ"</string> <string name="split_screen_text" msgid="1396336058129570886">"اسپلٹ اسکرین"</string> <string name="more_button_text" msgid="3655388105592893530">"مزید"</string> <string name="float_button_text" msgid="9221657008391364581">"فلوٹ"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml index 907c5bdc2753..3ce167293d39 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Tepada 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Tepada 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pastda to‘liq ekran"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Chapga ajratish"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Oʻngga ajratish"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Yuqoriga ajratish"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Pastga ajratish"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Ixcham rejimdan foydalanish"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Chiqish uchun ekran pastidan tepaga suring yoki ilovaning tepasidagi istalgan joyga bosing."</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Ixcham rejimni ishga tushirish"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Yopish"</string> <string name="back_button_text" msgid="1469718707134137085">"Orqaga"</string> <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Butun ekran"</string> <string name="desktop_text" msgid="1077633567027630454">"Desktop rejimi"</string> <string name="split_screen_text" msgid="1396336058129570886">"Ekranni ikkiga ajratish"</string> <string name="more_button_text" msgid="3655388105592893530">"Yana"</string> <string name="float_button_text" msgid="9221657008391364581">"Pufakli"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index 211e231943b4..1bf967a69eae 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Trên 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Trên 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Toàn màn hình phía dưới"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Chia đôi màn hình về bên trái"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Chia đôi màn hình về bên phải"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Chia đôi màn hình lên trên cùng"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Chia đôi màn hình xuống dưới cùng"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Cách dùng chế độ một tay"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Để thoát, hãy vuốt lên từ cuối màn hình hoặc nhấn vào vị trí bất kỳ phía trên ứng dụng"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Bắt đầu chế độ một tay"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Đóng"</string> <string name="back_button_text" msgid="1469718707134137085">"Quay lại"</string> <string name="handle_text" msgid="1766582106752184456">"Xử lý"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Toàn màn hình"</string> <string name="desktop_text" msgid="1077633567027630454">"Chế độ máy tính"</string> <string name="split_screen_text" msgid="1396336058129570886">"Chia đôi màn hình"</string> <string name="more_button_text" msgid="3655388105592893530">"Tuỳ chọn khác"</string> <string name="float_button_text" msgid="9221657008391364581">"Nổi"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index 3d0637a37173..3a8dd242246b 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"顶部 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"顶部 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"底部全屏"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"左分屏"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"右分屏"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"上分屏"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"下分屏"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"使用单手模式"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"如需退出,请从屏幕底部向上滑动,或点按应用上方的任意位置"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"启动单手模式"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"关闭"</string> <string name="back_button_text" msgid="1469718707134137085">"返回"</string> <string name="handle_text" msgid="1766582106752184456">"处理"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"全屏"</string> <string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string> <string name="split_screen_text" msgid="1396336058129570886">"分屏"</string> <string name="more_button_text" msgid="3655388105592893530">"更多"</string> <string name="float_button_text" msgid="9221657008391364581">"悬浮"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml index c4df0864004d..112bd41c4f15 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"頂部 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"頂部 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"底部全螢幕"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"分割左側區域"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"分割右側區域"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"分割上方區域"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"分割下方區域"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"使用單手模式"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"如要退出,請從螢幕底部向上滑動,或輕按應用程式上方的任何位置"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"開始單手模式"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"關閉"</string> <string name="back_button_text" msgid="1469718707134137085">"返去"</string> <string name="handle_text" msgid="1766582106752184456">"控點"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string> <string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string> <string name="split_screen_text" msgid="1396336058129570886">"分割螢幕"</string> <string name="more_button_text" msgid="3655388105592893530">"更多"</string> <string name="float_button_text" msgid="9221657008391364581">"浮動"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml index 2d9e7f3a4f43..edb0c7e8aa88 100644 --- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"以 50% 的螢幕空間顯示頂端畫面"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"以 30% 的螢幕空間顯示頂端畫面"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"以全螢幕顯示底部畫面"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"分割左側區域"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"分割右側區域"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"分割上方區域"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"分割下方區域"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"使用單手模式"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"如要退出,請從螢幕底部向上滑動,或輕觸應用程式上方的任何位置"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"啟動單手模式"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"關閉"</string> <string name="back_button_text" msgid="1469718707134137085">"返回"</string> <string name="handle_text" msgid="1766582106752184456">"控點"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string> <string name="desktop_text" msgid="1077633567027630454">"電腦模式"</string> <string name="split_screen_text" msgid="1396336058129570886">"分割畫面"</string> <string name="more_button_text" msgid="3655388105592893530">"更多"</string> <string name="float_button_text" msgid="9221657008391364581">"浮動"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml index 5c600560dca4..749b223993db 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings.xml @@ -47,14 +47,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Okuphezulu okungu-50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Okuphezulu okungu-30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ngaphansi kwesikrini esigcwele"</string> - <!-- no translation found for accessibility_split_left (1713683765575562458) --> - <skip /> - <!-- no translation found for accessibility_split_right (8441001008181296837) --> - <skip /> - <!-- no translation found for accessibility_split_top (2789329702027147146) --> - <skip /> - <!-- no translation found for accessibility_split_bottom (8694551025220868191) --> - <skip /> + <string name="accessibility_split_left" msgid="1713683765575562458">"Hlukanisa ngakwesobunxele"</string> + <string name="accessibility_split_right" msgid="8441001008181296837">"Hlukanisa ngakwesokudla"</string> + <string name="accessibility_split_top" msgid="2789329702027147146">"Hlukanisa phezulu"</string> + <string name="accessibility_split_bottom" msgid="8694551025220868191">"Hlukanisa phansi"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Ukusebenzisa imodi yesandla esisodwa"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Ukuze uphume, swayipha ngaphezulu kusuka ngezansi kwesikrini noma thepha noma kuphi ngenhla kohlelo lokusebenza"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Qalisa imodi yesandla esisodwa"</string> @@ -100,9 +96,19 @@ <string name="close_button_text" msgid="2913281996024033299">"Vala"</string> <string name="back_button_text" msgid="1469718707134137085">"Emuva"</string> <string name="handle_text" msgid="1766582106752184456">"Isibambo"</string> + <!-- no translation found for app_icon_text (2823268023931811747) --> + <skip /> <string name="fullscreen_text" msgid="1162316685217676079">"Isikrini esigcwele"</string> <string name="desktop_text" msgid="1077633567027630454">"Imodi Yedeskithophu"</string> <string name="split_screen_text" msgid="1396336058129570886">"Hlukanisa isikrini"</string> <string name="more_button_text" msgid="3655388105592893530">"Okwengeziwe"</string> <string name="float_button_text" msgid="9221657008391364581">"Iflowuthi"</string> + <!-- no translation found for select_text (5139083974039906583) --> + <skip /> + <!-- no translation found for screenshot_text (1477704010087786671) --> + <skip /> + <!-- no translation found for close_text (4986518933445178928) --> + <skip /> + <!-- no translation found for collapse_menu_text (7515008122450342029) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 111cfd8fc3c1..f11836ea5bee 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -650,7 +650,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } mPipUiEventLoggerLogger.setTaskInfo(mTaskInfo); - mPipUiEventLoggerLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER); // If the displayId of the task is different than what PipBoundsHandler has, then update // it. This is possible if we entered PiP on an external display. @@ -659,6 +658,17 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mOnDisplayIdChangeCallback.accept(info.displayId); } + // UiEvent logging. + final PipUiEventLogger.PipUiEventEnum uiEventEnum; + if (isLaunchIntoPipTask()) { + uiEventEnum = PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER_CONTENT_PIP; + } else if (mPipTransitionState.getInSwipePipToHomeTransition()) { + uiEventEnum = PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_AUTO_ENTER; + } else { + uiEventEnum = PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER; + } + mPipUiEventLoggerLogger.log(uiEventEnum); + if (mPipTransitionState.getInSwipePipToHomeTransition()) { if (!mWaitForFixedRotation) { onEndOfSwipePipToHomeTransition(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java index 513ebba59258..3e5a19b69a59 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java @@ -78,6 +78,12 @@ public class PipUiEventLogger { @UiEvent(doc = "Activity enters picture-in-picture mode") PICTURE_IN_PICTURE_ENTER(603), + @UiEvent(doc = "Activity enters picture-in-picture mode with auto-enter-pip API") + PICTURE_IN_PICTURE_AUTO_ENTER(1313), + + @UiEvent(doc = "Activity enters picture-in-picture mode from content-pip API") + PICTURE_IN_PICTURE_ENTER_CONTENT_PIP(1314), + @UiEvent(doc = "Expands from picture-in-picture to fullscreen") PICTURE_IN_PICTURE_EXPAND_TO_FULLSCREEN(604), 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 a42820d2e765..0c3eaf0b904f 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 @@ -535,6 +535,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(wrapper, 0 /* duration */, 0 /* statusBarTransitionDelay */); ActivityOptions activityOptions = ActivityOptions.fromBundle(options); + // Flag this as a no-user-action launch to prevent sending user leaving event to the current + // top activity since it's going to be put into another side of the split. This prevents the + // current top activity from going into pip mode due to user leaving event. + activityOptions.setApplyNoUserActionFlagForShortcut(true); activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter)); try { LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class); @@ -1222,8 +1226,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Notify recents if we are exiting in a way that breaks the pair, and disable further // updates to splits in the recents until we enter split again if (shouldBreakPairedTaskInRecents(exitReason) && mShouldUpdateRecents) { - recentTasks.removeSplitPair(mMainStage.getTopVisibleChildTaskId()); - recentTasks.removeSplitPair(mSideStage.getTopVisibleChildTaskId()); + recentTasks.removeSplitPair(mMainStage.getLastVisibleTaskId()); + recentTasks.removeSplitPair(mSideStage.getLastVisibleTaskId()); } }); mShouldUpdateRecents = false; 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 a841b7f96d3c..0359761388dc 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 @@ -92,6 +92,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { protected SurfaceControl mDimLayer; protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>(); private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>(); + private int mLastVisibleTaskId = INVALID_TASK_ID; // TODO(b/204308910): Extracts SplitDecorManager related code to common package. private SplitDecorManager mSplitDecorManager; @@ -123,6 +124,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } /** + * Returns the last visible task's id. + */ + int getLastVisibleTaskId() { + return mLastVisibleTaskId; + } + + /** * Returns the top visible child task's id. */ int getTopVisibleChildTaskId() { @@ -221,6 +229,9 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { return; } mChildrenTaskInfo.put(taskInfo.taskId, taskInfo); + if (taskInfo.isVisible && taskInfo.taskId != mLastVisibleTaskId) { + mLastVisibleTaskId = taskInfo.taskId; + } mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */, taskInfo.isVisible); if (!ENABLE_SHELL_TRANSITIONS) { @@ -253,6 +264,9 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } else if (mChildrenTaskInfo.contains(taskId)) { mChildrenTaskInfo.remove(taskId); mChildrenLeashes.remove(taskId); + if (taskId == mLastVisibleTaskId) { + mLastVisibleTaskId = INVALID_TASK_ID; + } mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible); if (ENABLE_SHELL_TRANSITIONS) { // Status is managed/synchronized by the transition lifecycle. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index 44e4a31c36f0..de5f2f467e99 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -250,25 +250,30 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { @Override public boolean onTouch(View v, MotionEvent e) { - boolean isDrag = false; final int id = v.getId(); if (id != R.id.caption_handle && id != R.id.desktop_mode_caption) { return false; } - if (id == R.id.caption_handle) { - isDrag = mDragDetector.onMotionEvent(e); - } - if (e.getAction() != MotionEvent.ACTION_DOWN) { - return isDrag; - } - final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); - if (taskInfo.isFocused) { - return isDrag; + switch (e.getAction()) { + case MotionEvent.ACTION_DOWN: + mDragDetector.onMotionEvent(e); + final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); + if (taskInfo.isFocused) { + return mDragDetector.isDragEvent(); + } + final WindowContainerTransaction wct = new WindowContainerTransaction(); + wct.reorder(mTaskToken, true /* onTop */); + mSyncQueue.queue(wct); + return false; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + boolean res = mDragDetector.isDragEvent(); + mDragDetector.onMotionEvent(e); + return res; + default: + mDragDetector.onMotionEvent(e); + return mDragDetector.isDragEvent(); } - final WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.reorder(mTaskToken, true /* onTop */); - mSyncQueue.queue(wct); - return true; } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java index 4fac843b05db..cf1850b92373 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java @@ -94,6 +94,10 @@ class DragDetector { mTouchSlop = touchSlop; } + boolean isDragEvent() { + return mIsDragEvent; + } + private void resetState() { mIsDragEvent = false; mInputDownPoint.set(0, 0); diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 2afcf7173171..b5eaa4b776b8 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -131,6 +131,7 @@ public class SecureSettings { Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO, Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED, Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, + Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, Settings.Secure.VR_DISPLAY_MODE, Settings.Secure.NOTIFICATION_BADGING, Settings.Secure.NOTIFICATION_DISMISS_RTL, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 53ae9268f49e..534e31ae42ee 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -191,6 +191,8 @@ public class SecureSettingsValidators { ANY_STRING_VALIDATOR); VALIDATORS.put(Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, ANY_STRING_VALIDATOR); + VALIDATORS.put(Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + ANY_STRING_VALIDATOR); VALIDATORS.put(Secure.ASSIST_GESTURE_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ASSIST_GESTURE_WAKE_ENABLED, BOOLEAN_VALIDATOR); diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt index ed6e6198f139..ab36d5899739 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt @@ -51,9 +51,12 @@ open class ClockRegistry( defaultClockProvider: ClockProvider, val fallbackClockId: ClockId = DEFAULT_CLOCK_ID, ) { - // Usually this would be a typealias, but a SAM provides better java interop - fun interface ClockChangeListener { - fun onClockChanged() + interface ClockChangeListener { + // Called when the active clock changes + fun onCurrentClockChanged() {} + + // Called when the list of available clocks changes + fun onAvailableClocksChanged() {} } private val availableClocks = mutableMapOf<ClockId, ClockInfo>() @@ -92,7 +95,7 @@ open class ClockRegistry( protected set(value) { if (field != value) { field = value - scope.launch(mainDispatcher) { onClockChanged() } + scope.launch(mainDispatcher) { onClockChanged { it.onCurrentClockChanged() } } } } @@ -164,9 +167,9 @@ open class ClockRegistry( Assert.isNotMainThread() } - private fun onClockChanged() { + private fun onClockChanged(func: (ClockChangeListener) -> Unit) { assertMainThread() - clockChangeListeners.forEach { it.onClockChanged() } + clockChangeListeners.forEach(func) } private fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) { @@ -241,6 +244,7 @@ open class ClockRegistry( } private fun connectClocks(provider: ClockProvider) { + var isAvailableChanged = false val currentId = currentClockId for (clock in provider.getClocks()) { val id = clock.clockId @@ -251,10 +255,11 @@ open class ClockRegistry( "Clock Id conflict: $id is registered by both " + "${provider::class.simpleName} and ${current.provider::class.simpleName}" ) - return + continue } availableClocks[id] = ClockInfo(clock, provider) + isAvailableChanged = true if (DEBUG) { Log.i(TAG, "Added ${clock.clockId}") } @@ -263,24 +268,35 @@ open class ClockRegistry( if (DEBUG) { Log.i(TAG, "Current clock ($currentId) was connected") } - onClockChanged() + onClockChanged { it.onCurrentClockChanged() } } } + + if (isAvailableChanged) { + onClockChanged { it.onAvailableClocksChanged() } + } } private fun disconnectClocks(provider: ClockProvider) { + var isAvailableChanged = false val currentId = currentClockId for (clock in provider.getClocks()) { availableClocks.remove(clock.clockId) + isAvailableChanged = true + if (DEBUG) { Log.i(TAG, "Removed ${clock.clockId}") } if (currentId == clock.clockId) { Log.w(TAG, "Current clock ($currentId) was disconnected") - onClockChanged() + onClockChanged { it.onCurrentClockChanged() } } } + + if (isAvailableChanged) { + onClockChanged { it.onAvailableClocksChanged() } + } } fun getClocks(): List<ClockMetadata> { diff --git a/packages/SystemUI/docs/qs-tiles.md b/packages/SystemUI/docs/qs-tiles.md index 4cb765dab741..488f8c728d82 100644 --- a/packages/SystemUI/docs/qs-tiles.md +++ b/packages/SystemUI/docs/qs-tiles.md @@ -301,9 +301,13 @@ This section describes necessary and recommended steps when implementing a Quick * Use only `handleUpdateState` to modify the values of the state to the new ones. This can be done by polling controllers or through the `arg` parameter. * If the controller is not a `CallbackController`, respond to `handleSetListening` by attaching/dettaching from controllers. * Implement `isAvailable` so the tile will not be created when it's not necessary. -4. In `QSFactoryImpl`: - * Inject a `Provider` for the tile created before. - * Add a case to the `switch` with a unique String spec for the chosen tile. +4. Either create a new feature module or find an existing related feature module and add the following binding method: + * ```kotlin + @Binds + @IntoMap + @StringKey(YourNewTile.TILE_SPEC) // A unique word that will map to YourNewTile + fun bindYourNewTile(yourNewTile: YourNewTile): QSTileImpl<*> + ``` 5. In [SystemUI/res/values/config.xml](/packages/SystemUI/res/values/config.xml), modify `quick_settings_tiles_stock` and add the spec defined in the previous step. If necessary, add it also to `quick_settings_tiles_default`. The first one contains a list of all the tiles that SystemUI knows how to create (to show to the user in the customization screen). The second one contains only the default tiles that the user will experience on a fresh boot or after they reset their tiles. 6. In [SystemUI/res/values/tiles_states_strings.xml](/packages/SystemUI/res/values/tiles_states_strings.xml), add a new array for your tile. The name has to be `tile_states_<spec>`. Use a good description to help the translators. 7. In [`SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt`](/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt), add a new element to the map in `SubtitleArrayMapping` corresponding to the resource created in the previous step. diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt index 1a67691e30bf..943d7996dd89 100644 --- a/packages/SystemUI/ktfmt_includes.txt +++ b/packages/SystemUI/ktfmt_includes.txt @@ -451,13 +451,6 @@ -packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt -packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt -packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt --packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt --packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiActivityModel.kt --packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt --packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt --packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt --packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt --packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt -packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt -packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt -packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt @@ -742,11 +735,6 @@ -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/ShadeExpansionStateManagerTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java index 2b169997168b..1d28c63f8398 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java @@ -16,9 +16,11 @@ package com.android.systemui.plugins.qs; import android.annotation.NonNull; import android.content.Context; +import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.metrics.LogMaker; import android.service.quicksettings.Tile; +import android.text.TextUtils; import android.view.View; import androidx.annotation.Nullable; @@ -175,6 +177,24 @@ public interface QSTile { public Drawable sideViewCustomDrawable; public String spec; + /** Get the state text. */ + public String getStateText(int arrayResId, Resources resources) { + if (state == Tile.STATE_UNAVAILABLE || this instanceof QSTile.BooleanState) { + String[] array = resources.getStringArray(arrayResId); + return array[state]; + } else { + return ""; + } + } + + /** Get the text for secondaryLabel. */ + public String getSecondaryLabel(String stateText) { + if (TextUtils.isEmpty(secondaryLabel)) { + return stateText; + } + return secondaryLabel.toString(); + } + public boolean copyTo(State other) { if (other == null) throw new IllegalArgumentException(); if (!other.getClass().equals(getClass())) throw new IllegalArgumentException(); diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml index 8497ff094c03..426cfafb190e 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- ** -** Copyright 2012, The Android Open Source Project +** Copyright 2023, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License") ** you may not use this file except in compliance with the License. @@ -17,12 +17,10 @@ */ --> -<!-- This is the host view that generally contains two sub views: the widget view - and the security view. --> -<com.android.keyguard.KeyguardHostView +<com.android.keyguard.KeyguardSecurityContainer xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/res-auto" - android:id="@+id/keyguard_host_view" + android:id="@+id/keyguard_security_container" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" @@ -30,27 +28,15 @@ android:paddingTop="@dimen/keyguard_lock_padding" android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent from this view when bouncer is shown --> - - <com.android.keyguard.KeyguardSecurityContainer - android:id="@+id/keyguard_security_container" - android:layout_width="match_parent" + <com.android.keyguard.KeyguardSecurityViewFlipper + android:id="@+id/view_flipper" + android:layout_width="wrap_content" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" - android:padding="0dp" - android:fitsSystemWindows="true" - android:layout_gravity="center"> - <com.android.keyguard.KeyguardSecurityViewFlipper - android:id="@+id/view_flipper" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:clipChildren="false" - android:clipToPadding="false" - android:paddingTop="@dimen/keyguard_security_view_top_margin" - android:layout_gravity="center" - android:gravity="center"> - </com.android.keyguard.KeyguardSecurityViewFlipper> - </com.android.keyguard.KeyguardSecurityContainer> - -</com.android.keyguard.KeyguardHostView> + android:paddingTop="@dimen/keyguard_security_view_top_margin" + android:layout_gravity="center" + android:gravity="center"> + </com.android.keyguard.KeyguardSecurityViewFlipper> +</com.android.keyguard.KeyguardSecurityContainer> diff --git a/packages/SystemUI/res/layout/clipboard_overlay.xml b/packages/SystemUI/res/layout/clipboard_overlay.xml index 9b01bd8c7d80..297cf2b94a19 100644 --- a/packages/SystemUI/res/layout/clipboard_overlay.xml +++ b/packages/SystemUI/res/layout/clipboard_overlay.xml @@ -61,8 +61,6 @@ android:id="@+id/share_chip"/> <include layout="@layout/overlay_action_chip" android:id="@+id/remote_copy_chip"/> - <include layout="@layout/overlay_action_chip" - android:id="@+id/edit_chip"/> </LinearLayout> </HorizontalScrollView> <View diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml index e60f23329212..da24a79759f7 100644 --- a/packages/SystemUI/res/values-af/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Af"</item> <item msgid="5966994759929723339">"Aan"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-am/tiles_states_strings.xml b/packages/SystemUI/res/values-am/tiles_states_strings.xml index bbf2d2385f05..26ef52d996ac 100644 --- a/packages/SystemUI/res/values-am/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-am/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ጠፍቷል"</item> <item msgid="5966994759929723339">"በርቷል"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml index 44b58f964ce9..b88d09706595 100644 --- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"غير مفعّلة"</item> <item msgid="5966994759929723339">"مفعَّلة"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-as/tiles_states_strings.xml b/packages/SystemUI/res/values-as/tiles_states_strings.xml index 3145341cabe4..e7dc9b4e180a 100644 --- a/packages/SystemUI/res/values-as/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-as/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"অফ আছে"</item> <item msgid="5966994759929723339">"অন আছে"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml index fb745b251bc9..e0fcf890a505 100644 --- a/packages/SystemUI/res/values-az/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Deaktiv"</item> <item msgid="5966994759929723339">"Aktiv"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml index b69b06419281..fd604b5f079f 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Isključeno"</item> <item msgid="5966994759929723339">"Uključeno"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml index 8fb2da26edc2..4050129df5c4 100644 --- a/packages/SystemUI/res/values-be/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Выключана"</item> <item msgid="5966994759929723339">"Уключана"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml index b85133b6bd43..011c62490606 100644 --- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Изкл."</item> <item msgid="5966994759929723339">"Вкл."</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml index d70afc0f7f4f..00ce04e42e13 100644 --- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"বন্ধ আছে"</item> <item msgid="5966994759929723339">"চালু আছে"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml index b69b06419281..32051ef19743 100644 --- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml @@ -176,4 +176,9 @@ <item msgid="8014986104355098744">"Isključeno"</item> <item msgid="5966994759929723339">"Uključeno"</item> </string-array> + <string-array name="tile_states_font_scaling"> + <item msgid="3173069902082305985">"Nedostupno"</item> + <item msgid="2478289035899842865">"Isključeno"</item> + <item msgid="5137565285664080143">"Uključeno"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml index aaf19c7c0cc6..067b970226d8 100644 --- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Desactivat"</item> <item msgid="5966994759929723339">"Activat"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml index 64e83e0c31b8..df3d403d14dc 100644 --- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Vypnuto"</item> <item msgid="5966994759929723339">"Zapnuto"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml index f0132dc66130..7e2f87de778e 100644 --- a/packages/SystemUI/res/values-da/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Fra"</item> <item msgid="5966994759929723339">"Til"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml index bc50e1603ea4..bd73a0583c53 100644 --- a/packages/SystemUI/res/values-de/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Aus"</item> <item msgid="5966994759929723339">"An"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml index 352af39bfe11..5c7c7380943a 100644 --- a/packages/SystemUI/res/values-el/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Ανενεργό"</item> <item msgid="5966994759929723339">"Ενεργό"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml index 56cdbef092f2..0cf28684aa48 100644 --- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml @@ -176,4 +176,9 @@ <item msgid="8014986104355098744">"Off"</item> <item msgid="5966994759929723339">"On"</item> </string-array> + <string-array name="tile_states_font_scaling"> + <item msgid="3173069902082305985">"Unavailable"</item> + <item msgid="2478289035899842865">"Off"</item> + <item msgid="5137565285664080143">"On"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml index 56cdbef092f2..0cf28684aa48 100644 --- a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml @@ -176,4 +176,9 @@ <item msgid="8014986104355098744">"Off"</item> <item msgid="5966994759929723339">"On"</item> </string-array> + <string-array name="tile_states_font_scaling"> + <item msgid="3173069902082305985">"Unavailable"</item> + <item msgid="2478289035899842865">"Off"</item> + <item msgid="5137565285664080143">"On"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml index 56cdbef092f2..0cf28684aa48 100644 --- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml @@ -176,4 +176,9 @@ <item msgid="8014986104355098744">"Off"</item> <item msgid="5966994759929723339">"On"</item> </string-array> + <string-array name="tile_states_font_scaling"> + <item msgid="3173069902082305985">"Unavailable"</item> + <item msgid="2478289035899842865">"Off"</item> + <item msgid="5137565285664080143">"On"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml index 56cdbef092f2..0cf28684aa48 100644 --- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml @@ -176,4 +176,9 @@ <item msgid="8014986104355098744">"Off"</item> <item msgid="5966994759929723339">"On"</item> </string-array> + <string-array name="tile_states_font_scaling"> + <item msgid="3173069902082305985">"Unavailable"</item> + <item msgid="2478289035899842865">"Off"</item> + <item msgid="5137565285664080143">"On"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml index 3a8e34c2ebdc..b9c8e5fcdd6a 100644 --- a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml @@ -176,4 +176,9 @@ <item msgid="8014986104355098744">"Off"</item> <item msgid="5966994759929723339">"On"</item> </string-array> + <string-array name="tile_states_font_scaling"> + <item msgid="3173069902082305985">"Unavailable"</item> + <item msgid="2478289035899842865">"Off"</item> + <item msgid="5137565285664080143">"On"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml index 89ee62d1cd87..e15610096626 100644 --- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"No"</item> <item msgid="5966994759929723339">"Sí"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml index fe4cbedb6b36..cee83711077c 100644 --- a/packages/SystemUI/res/values-es/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Desactivado"</item> <item msgid="5966994759929723339">"Activado"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml index 07eddef9383e..7bf520f581c3 100644 --- a/packages/SystemUI/res/values-et/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Väljas"</item> <item msgid="5966994759929723339">"Sees"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml index 3bf49c8e0c77..333ede134f45 100644 --- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Desaktibatuta"</item> <item msgid="5966994759929723339">"Aktibatuta"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml index 85f0bfdf86dd..436ea31f2044 100644 --- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"خاموش"</item> <item msgid="5966994759929723339">"روشن"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml index 1505dc5c06bb..4bec4b3157cb 100644 --- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Poissa päältä"</item> <item msgid="5966994759929723339">"Päällä"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml index c4088652fbdd..788f56de1bdc 100644 --- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Désactivé"</item> <item msgid="5966994759929723339">"Activé"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml index 8c6c4f555a5c..3f63a9639a80 100644 --- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Désactivé"</item> <item msgid="5966994759929723339">"Activé"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml index 590ec4ac515c..94fc3f487d17 100644 --- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Desactivado"</item> <item msgid="5966994759929723339">"Activado"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml index cc062a772149..e92168c37cb8 100644 --- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"બંધ છે"</item> <item msgid="5966994759929723339">"ચાલુ છે"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml index a156b0c43ca6..0abf8b31ca1a 100644 --- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"बंद है"</item> <item msgid="5966994759929723339">"चालू है"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml index b69b06419281..32051ef19743 100644 --- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml @@ -176,4 +176,9 @@ <item msgid="8014986104355098744">"Isključeno"</item> <item msgid="5966994759929723339">"Uključeno"</item> </string-array> + <string-array name="tile_states_font_scaling"> + <item msgid="3173069902082305985">"Nedostupno"</item> + <item msgid="2478289035899842865">"Isključeno"</item> + <item msgid="5137565285664080143">"Uključeno"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml index 050bc14d54ff..0416a5504ae9 100644 --- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Ki"</item> <item msgid="5966994759929723339">"Be"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml index 6015fbd75b3c..9f30f1cd3a87 100644 --- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Անջատված է"</item> <item msgid="5966994759929723339">"Միացված է"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml index 5416c8f77ca6..c31404089220 100644 --- a/packages/SystemUI/res/values-in/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Nonaktif"</item> <item msgid="5966994759929723339">"Aktif"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml index 12dd776a357c..cca4943a062e 100644 --- a/packages/SystemUI/res/values-is/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Slökkt"</item> <item msgid="5966994759929723339">"Kveikt"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml index 5ec557bbaf7d..79e5aca07162 100644 --- a/packages/SystemUI/res/values-it/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Off"</item> <item msgid="5966994759929723339">"On"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml index 91577b81a5d3..374f5af7f513 100644 --- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"כבוי"</item> <item msgid="5966994759929723339">"מופעל"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ja/tiles_states_strings.xml b/packages/SystemUI/res/values-ja/tiles_states_strings.xml index c2a3321dc19f..64f7c394499c 100644 --- a/packages/SystemUI/res/values-ja/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ja/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"OFF"</item> <item msgid="5966994759929723339">"ON"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ka/tiles_states_strings.xml b/packages/SystemUI/res/values-ka/tiles_states_strings.xml index c95187404d48..99c5263a1102 100644 --- a/packages/SystemUI/res/values-ka/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ka/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"გამორთულია"</item> <item msgid="5966994759929723339">"ჩართულია"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-kk/tiles_states_strings.xml b/packages/SystemUI/res/values-kk/tiles_states_strings.xml index c312b4957615..be7546eb7686 100644 --- a/packages/SystemUI/res/values-kk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-kk/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Өшірулі."</item> <item msgid="5966994759929723339">"Қосулы."</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-km/tiles_states_strings.xml b/packages/SystemUI/res/values-km/tiles_states_strings.xml index ec748cfac142..37e839f01dfc 100644 --- a/packages/SystemUI/res/values-km/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-km/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"បិទ"</item> <item msgid="5966994759929723339">"បើក"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml index 864a607c8a39..8a2ad2a8bb13 100644 --- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ಆಫ್ ಮಾಡಿ"</item> <item msgid="5966994759929723339">"ಆನ್ ಮಾಡಿ"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml index c52c17cedc32..c3d9d44db26a 100644 --- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"꺼짐"</item> <item msgid="5966994759929723339">"켜짐"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml index f872926aa945..f4b84478d56b 100644 --- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Өчүк"</item> <item msgid="5966994759929723339">"Күйүк"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-lo/tiles_states_strings.xml b/packages/SystemUI/res/values-lo/tiles_states_strings.xml index 6ae37e472b0c..f7f4b623402c 100644 --- a/packages/SystemUI/res/values-lo/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lo/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ປິດ"</item> <item msgid="5966994759929723339">"ເປີດ"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml index 03d98c42ff19..58379150e4a7 100644 --- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Išjungta"</item> <item msgid="5966994759929723339">"Įjungta"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml index 6e9264d2a347..9a534c4eaeed 100644 --- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Izslēgts"</item> <item msgid="5966994759929723339">"Ieslēgts"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml index 96c8a49ae0b6..d088f120b362 100644 --- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Исклучено"</item> <item msgid="5966994759929723339">"Вклучено"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ml/tiles_states_strings.xml b/packages/SystemUI/res/values-ml/tiles_states_strings.xml index 7a078737aa96..108e173e003a 100644 --- a/packages/SystemUI/res/values-ml/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ml/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ഓഫാണ്"</item> <item msgid="5966994759929723339">"ഓണാണ്"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml index 776c4877d1ad..5cd21c1d2ec8 100644 --- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Унтраалттай"</item> <item msgid="5966994759929723339">"Асаалттай"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml index f75f0d097998..78560c4314c6 100644 --- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"बंद आहे"</item> <item msgid="5966994759929723339">"सुरू आहे"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ms/tiles_states_strings.xml b/packages/SystemUI/res/values-ms/tiles_states_strings.xml index 9fa7ab51d064..f3dafa519140 100644 --- a/packages/SystemUI/res/values-ms/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ms/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Mati"</item> <item msgid="5966994759929723339">"Hidup"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-my/tiles_states_strings.xml b/packages/SystemUI/res/values-my/tiles_states_strings.xml index 493a7f0977c6..cadf00975048 100644 --- a/packages/SystemUI/res/values-my/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-my/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ပိတ်"</item> <item msgid="5966994759929723339">"ဖွင့်"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml index 6fa902a662ff..b465617aa6fd 100644 --- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Av"</item> <item msgid="5966994759929723339">"På"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml index 17193bafd9a3..bbdf72a3fa44 100644 --- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"अफ"</item> <item msgid="5966994759929723339">"अन"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml index fbccd78eeb8f..b51dc653912b 100644 --- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Uit"</item> <item msgid="5966994759929723339">"Aan"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml index acaa3fb6f6a8..5e4b730f6144 100644 --- a/packages/SystemUI/res/values-or/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ବନ୍ଦ ଅଛି"</item> <item msgid="5966994759929723339">"ଚାଲୁ ଅଛି"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml index 9653b923224a..5628a3167b87 100644 --- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ਬੰਦ"</item> <item msgid="5966994759929723339">"ਚਾਲੂ"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml index 50650986c517..c32aa1a69a43 100644 --- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Wyłączono"</item> <item msgid="5966994759929723339">"Włączono"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml index ebe67d86ca23..cea45323069f 100644 --- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Desativado"</item> <item msgid="5966994759929723339">"Ativado"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml index bda7473ba15b..b58b8488a3e4 100644 --- a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml @@ -176,4 +176,9 @@ <item msgid="8014986104355098744">"Desativado"</item> <item msgid="5966994759929723339">"Ativado"</item> </string-array> + <string-array name="tile_states_font_scaling"> + <item msgid="3173069902082305985">"Indisponível"</item> + <item msgid="2478289035899842865">"Desativado"</item> + <item msgid="5137565285664080143">"Ativado"</item> + </string-array> </resources> diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml index ebe67d86ca23..cea45323069f 100644 --- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Desativado"</item> <item msgid="5966994759929723339">"Ativado"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml index 7b7bb3ac11d8..782afc5d7299 100644 --- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Dezactivat"</item> <item msgid="5966994759929723339">"Activat"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml index 6255bd8ee26d..9a4960b1ada9 100644 --- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Отключено"</item> <item msgid="5966994759929723339">"Включено"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml index 327e0b92c967..c9312ff08040 100644 --- a/packages/SystemUI/res/values-si/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ක්රියාවිරහිතයි"</item> <item msgid="5966994759929723339">"ක්රියාත්මකයි"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-sk/tiles_states_strings.xml b/packages/SystemUI/res/values-sk/tiles_states_strings.xml index 3cbde1c9574c..3540eabb8205 100644 --- a/packages/SystemUI/res/values-sk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sk/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Vypnuté"</item> <item msgid="5966994759929723339">"Zapnuté"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml index e720819b4b60..985b7796c567 100644 --- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Izklopljeno"</item> <item msgid="5966994759929723339">"Vklopljeno"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml index 7a09f2450354..5862e2ef2b1c 100644 --- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Joaktiv"</item> <item msgid="5966994759929723339">"Aktiv"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-sr/tiles_states_strings.xml b/packages/SystemUI/res/values-sr/tiles_states_strings.xml index dace491993ba..e817eea952ec 100644 --- a/packages/SystemUI/res/values-sr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sr/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Искључено"</item> <item msgid="5966994759929723339">"Укључено"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml index 9e69b00adf64..45169aa8b1f4 100644 --- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Av"</item> <item msgid="5966994759929723339">"På"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-sw/tiles_states_strings.xml b/packages/SystemUI/res/values-sw/tiles_states_strings.xml index 2f765ef5320a..aad00999f0f6 100644 --- a/packages/SystemUI/res/values-sw/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sw/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Imezimwa"</item> <item msgid="5966994759929723339">"Imewashwa"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml index 41f64125753c..1a22d9fa1476 100644 --- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"முடக்கப்பட்டுள்ளது"</item> <item msgid="5966994759929723339">"இயக்கப்பட்டுள்ளது"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml index 44ba47781ae7..c5a525cb611f 100644 --- a/packages/SystemUI/res/values-te/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ఆఫ్"</item> <item msgid="5966994759929723339">"ఆన్"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml index 9cd060f2cabf..61e0fe6bde77 100644 --- a/packages/SystemUI/res/values-th/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"ปิด"</item> <item msgid="5966994759929723339">"เปิด"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-tl/tiles_states_strings.xml b/packages/SystemUI/res/values-tl/tiles_states_strings.xml index cd7dcf51b279..4522945908c9 100644 --- a/packages/SystemUI/res/values-tl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-tl/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Naka-off"</item> <item msgid="5966994759929723339">"Naka-on"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-tr/tiles_states_strings.xml b/packages/SystemUI/res/values-tr/tiles_states_strings.xml index 28ba7dcb9010..5d6a7f429614 100644 --- a/packages/SystemUI/res/values-tr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-tr/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Kapalı"</item> <item msgid="5966994759929723339">"Açık"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml index 3f6ca461ac1d..a0cc1c19d46d 100644 --- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Вимкнено"</item> <item msgid="5966994759929723339">"Увімкнено"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-ur/tiles_states_strings.xml b/packages/SystemUI/res/values-ur/tiles_states_strings.xml index 05aa4e91e5cc..5e2b0736ec8f 100644 --- a/packages/SystemUI/res/values-ur/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ur/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"آف"</item> <item msgid="5966994759929723339">"آن"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-uz/tiles_states_strings.xml b/packages/SystemUI/res/values-uz/tiles_states_strings.xml index a84f7698d861..6d55fc1f1225 100644 --- a/packages/SystemUI/res/values-uz/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-uz/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Oʻchiq"</item> <item msgid="5966994759929723339">"Yoniq"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-vi/tiles_states_strings.xml b/packages/SystemUI/res/values-vi/tiles_states_strings.xml index 482a32f902b4..5b816fb9e62e 100644 --- a/packages/SystemUI/res/values-vi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-vi/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Tắt"</item> <item msgid="5966994759929723339">"Đang bật"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml index 6ce948def69e..5d7d02f2dbeb 100644 --- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"关闭"</item> <item msgid="5966994759929723339">"已开启"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml index ab8e961a1f47..2e51f920055a 100644 --- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"已關閉"</item> <item msgid="5966994759929723339">"已開啟"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml index 3d6a546e6103..f1f01853d342 100644 --- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"已關閉"</item> <item msgid="5966994759929723339">"已開啟"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values-zu/tiles_states_strings.xml b/packages/SystemUI/res/values-zu/tiles_states_strings.xml index 81c46364a9fd..a8ccbb58366a 100644 --- a/packages/SystemUI/res/values-zu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zu/tiles_states_strings.xml @@ -176,4 +176,7 @@ <item msgid="8014986104355098744">"Valiwe"</item> <item msgid="5966994759929723339">"Vuliwe"</item> </string-array> + <!-- no translation found for tile_states_font_scaling:0 (3173069902082305985) --> + <!-- no translation found for tile_states_font_scaling:1 (2478289035899842865) --> + <!-- no translation found for tile_states_font_scaling:2 (5137565285664080143) --> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 031d40e074a3..3f84ddb2a067 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -450,7 +450,7 @@ <integer name="watch_heap_limit">256000</integer> <!-- SystemUI Plugins that can be loaded on user builds. --> - <string-array name="config_pluginWhitelist" translatable="false"> + <string-array name="config_pluginAllowlist" translatable="false"> <item>com.android.systemui</item> </string-array> @@ -829,7 +829,7 @@ <string name="config_wallpaperPickerPackage" translatable="false"> com.android.wallpaper </string> - + <!-- Whether the floating rotation button should be on the left/right in the device's natural orientation --> <bool name="floating_rotation_button_position_left">true</bool> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 199bc67bb54c..e6ac59e6b106 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2842,4 +2842,19 @@ [CHAR LIMIT=32] --> <string name="lock_screen_settings">Lock screen settings</string> + + <!-- Content description for Wi-Fi not available icon on dream [CHAR LIMIT=NONE]--> + <string name="wifi_unavailable_dream_overlay_content_description">Wi-Fi not available</string> + + <!-- Content description for camera blocked icon on dream [CHAR LIMIT=NONE] --> + <string name="camera_blocked_dream_overlay_content_description">Camera blocked</string> + + <!-- Content description for camera and microphone blocked icon on dream [CHAR LIMIT=NONE] --> + <string name="camera_and_microphone_blocked_dream_overlay_content_description">Camera and microphone blocked</string> + + <!-- Content description for camera and microphone disabled icon on dream [CHAR LIMIT=NONE] --> + <string name="microphone_blocked_dream_overlay_content_description">Microphone blocked</string> + + <!-- Content description for priority mode icon on dream [CHAR LIMIT=NONE] --> + <string name="priority_mode_dream_overlay_content_description">Priority mode on</string> </resources> diff --git a/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt b/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt index 54ae84f97b17..c4f1ce8f5d3b 100644 --- a/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt +++ b/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt @@ -29,8 +29,9 @@ import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ERRORS import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED -import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_WAKE +import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS +import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD import android.util.Log import com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser import com.android.systemui.Dumpable @@ -60,9 +61,27 @@ class ActiveUnlockConfig @Inject constructor( * Indicates the origin for an active unlock request. */ enum class ActiveUnlockRequestOrigin { + /** + * Trigger ActiveUnlock on wake ups that'd trigger FaceAuth, see [FaceWakeUpTriggersConfig] + */ WAKE, + + /** + * Trigger ActiveUnlock on unlock intents. This includes the bouncer showing or tapping on + * a notification. May also include wakeups: [wakeupsConsideredUnlockIntents]. + */ UNLOCK_INTENT, + + /** + * Trigger ActiveUnlock on biometric failures. This may include soft errors depending on + * the other settings. See: [faceErrorsToTriggerBiometricFailOn], + * [faceAcquireInfoToTriggerBiometricFailOn]. + */ BIOMETRIC_FAIL, + + /** + * Trigger ActiveUnlock when the assistant is triggered. + */ ASSISTANT, } @@ -85,6 +104,7 @@ class ActiveUnlockConfig @Inject constructor( private var faceAcquireInfoToTriggerBiometricFailOn = mutableSetOf<Int>() private var onUnlockIntentWhenBiometricEnrolled = mutableSetOf<Int>() private var wakeupsConsideredUnlockIntents = mutableSetOf<Int>() + private var wakeupsToForceDismissKeyguard = mutableSetOf<Int>() private val settingsObserver = object : ContentObserver(handler) { private val wakeUri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_WAKE) @@ -97,6 +117,8 @@ class ActiveUnlockConfig @Inject constructor( secureSettings.getUriFor(ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED) private val wakeupsConsideredUnlockIntentsUri = secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS) + private val wakeupsToForceDismissKeyguardUri = + secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD) fun register() { registerUri( @@ -108,6 +130,7 @@ class ActiveUnlockConfig @Inject constructor( faceAcquireInfoUri, unlockIntentWhenBiometricEnrolledUri, wakeupsConsideredUnlockIntentsUri, + wakeupsToForceDismissKeyguardUri, ) ) @@ -182,6 +205,15 @@ class ActiveUnlockConfig @Inject constructor( wakeupsConsideredUnlockIntents, setOf(WAKE_REASON_UNFOLD_DEVICE)) } + + if (selfChange || uris.contains(wakeupsToForceDismissKeyguardUri)) { + processStringArray( + secureSettings.getStringForUser( + ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + getCurrentUser()), + wakeupsToForceDismissKeyguard, + setOf(WAKE_REASON_UNFOLD_DEVICE)) + } } /** @@ -249,6 +281,14 @@ class ActiveUnlockConfig @Inject constructor( } /** + * Whether the PowerManager wake reason should force dismiss the keyguard if active + * unlock is successful. + */ + fun shouldWakeupForceDismissKeyguard(pmWakeReason: Int): Boolean { + return wakeupsToForceDismissKeyguard.contains(pmWakeReason) + } + + /** * Whether to trigger active unlock based on where the request is coming from and * the current settings. */ @@ -303,15 +343,27 @@ class ActiveUnlockConfig @Inject constructor( pw.println(" requestActiveUnlockOnWakeup=$requestActiveUnlockOnWakeup") pw.println(" requestActiveUnlockOnUnlockIntent=$requestActiveUnlockOnUnlockIntent") pw.println(" requestActiveUnlockOnBioFail=$requestActiveUnlockOnBioFail") - pw.println(" requestActiveUnlockOnUnlockIntentWhenBiometricEnrolled=${ - onUnlockIntentWhenBiometricEnrolled.map { BiometricType.values()[it] } - }") + + val onUnlockIntentWhenBiometricEnrolledString = + onUnlockIntentWhenBiometricEnrolled.map { + for (biometricType in BiometricType.values()) { + if (biometricType.intValue == it) { + return@map biometricType.name + } + } + return@map "UNKNOWN" + } + pw.println(" requestActiveUnlockOnUnlockIntentWhenBiometricEnrolled=" + + "$onUnlockIntentWhenBiometricEnrolledString") pw.println(" requestActiveUnlockOnFaceError=$faceErrorsToTriggerBiometricFailOn") pw.println(" requestActiveUnlockOnFaceAcquireInfo=" + "$faceAcquireInfoToTriggerBiometricFailOn") pw.println(" activeUnlockWakeupsConsideredUnlockIntents=${ wakeupsConsideredUnlockIntents.map { PowerManager.wakeReasonToString(it) } }") + pw.println(" activeUnlockFromWakeupsToAlwaysDismissKeyguard=${ + wakeupsToForceDismissKeyguard.map { PowerManager.wakeReasonToString(it) } + }") pw.println("Current state:") keyguardUpdateMonitor?.let { diff --git a/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt b/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt index a0c43fba4bc1..788a66dcf281 100644 --- a/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt +++ b/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt @@ -29,7 +29,7 @@ import java.io.PrintWriter import java.util.stream.Collectors import javax.inject.Inject -/** Determines which device wake-ups should trigger face authentication. */ +/** Determines which device wake-ups should trigger passive authentication. */ @SysUISingleton class FaceWakeUpTriggersConfig @Inject diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index baaeb2a1b3a5..b85b2b8314ed 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -151,8 +151,13 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mLogBuffer = logBuffer; mView.setLogBuffer(mLogBuffer); - mClockChangedListener = () -> { - setClock(mClockRegistry.createCurrentClock()); + mClockChangedListener = new ClockRegistry.ClockChangeListener() { + @Override + public void onCurrentClockChanged() { + setClock(mClockRegistry.createCurrentClock()); + } + @Override + public void onAvailableClocksChanged() { } }; } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt index 998dc09aa5ab..57130ed80d26 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt @@ -27,6 +27,7 @@ data class KeyguardFingerprintListenModel( override var userId: Int = 0, override var listening: Boolean = false, // keepSorted + var alternateBouncerShowing: Boolean = false, var biometricEnabledForUser: Boolean = false, var bouncerIsOrWillShow: Boolean = false, var canSkipBouncer: Boolean = false, @@ -57,6 +58,7 @@ data class KeyguardFingerprintListenModel( userId.toString(), listening.toString(), // keep sorted + alternateBouncerShowing.toString(), biometricEnabledForUser.toString(), bouncerIsOrWillShow.toString(), canSkipBouncer.toString(), @@ -96,6 +98,7 @@ data class KeyguardFingerprintListenModel( userId = model.userId listening = model.listening // keep sorted + alternateBouncerShowing = model.alternateBouncerShowing biometricEnabledForUser = model.biometricEnabledForUser bouncerIsOrWillShow = model.bouncerIsOrWillShow canSkipBouncer = model.canSkipBouncer @@ -141,6 +144,7 @@ data class KeyguardFingerprintListenModel( "userId", "listening", // keep sorted + "alternateBouncerShowing", "biometricAllowedForUser", "bouncerIsOrWillShow", "canSkipBouncer", diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java deleted file mode 100644 index 2a389b6132e9..000000000000 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.keyguard; - -import android.content.Context; -import android.graphics.Canvas; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.widget.FrameLayout; - -/** - * Base class for keyguard view. {@link #reset} is where you should - * reset the state of your view. Use the {@link KeyguardViewCallback} via - * {@link #getCallback()} to send information back (such as poking the wake lock, - * or finishing the keyguard). - * - * Handles intercepting of media keys that still work when the keyguard is - * showing. - */ -public class KeyguardHostView extends FrameLayout { - - protected ViewMediatorCallback mViewMediatorCallback; - private boolean mIsInteractable; - - public KeyguardHostView(Context context) { - this(context, null); - } - - public KeyguardHostView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - if (mViewMediatorCallback != null) { - mViewMediatorCallback.keyguardDoneDrawing(); - } - } - - public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) { - mViewMediatorCallback = viewMediatorCallback; - } - - /** Set true if the view can be interacted with */ - public void setInteractable(boolean isInteractable) { - mIsInteractable = isInteractable; - } - - /** - * Make sure to disallow touches while transitioning the bouncer, otherwise - * it can remain interactable even when barely visible. - */ - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return !mIsInteractable; - } - - /** True to consume any events that are sent to it */ - @Override - public boolean onTouchEvent(MotionEvent ev) { - return true; - } -} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java deleted file mode 100644 index 61394035d731..000000000000 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.keyguard; - -import android.app.ActivityManager; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.media.AudioManager; -import android.os.SystemClock; -import android.telephony.TelephonyManager; -import android.util.Log; -import android.util.MathUtils; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnKeyListener; -import android.view.ViewTreeObserver; -import android.widget.FrameLayout; -import android.window.OnBackAnimationCallback; - -import androidx.annotation.NonNull; - -import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback; -import com.android.keyguard.KeyguardSecurityModel.SecurityMode; -import com.android.keyguard.dagger.KeyguardBouncerScope; -import com.android.settingslib.Utils; -import com.android.systemui.R; -import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.util.ViewController; - -import java.io.File; - -import javax.inject.Inject; - -/** Controller for a {@link KeyguardHostView}. */ -@KeyguardBouncerScope -public class KeyguardHostViewController extends ViewController<KeyguardHostView> { - private static final String TAG = "KeyguardViewBase"; - public static final boolean DEBUG = KeyguardConstants.DEBUG; - // Whether the volume keys should be handled by keyguard. If true, then - // they will be handled here for specific media types such as music, otherwise - // the audio service will bring up the volume dialog. - private static final boolean KEYGUARD_MANAGES_VOLUME = false; - - private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key"; - - private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final KeyguardSecurityContainerController mKeyguardSecurityContainerController; - private final TelephonyManager mTelephonyManager; - private final ViewMediatorCallback mViewMediatorCallback; - private final AudioManager mAudioManager; - - private ActivityStarter.OnDismissAction mDismissAction; - private Runnable mCancelAction; - private int mTranslationY; - - private final KeyguardUpdateMonitorCallback mUpdateCallback = - new KeyguardUpdateMonitorCallback() { - @Override - public void onTrustGrantedForCurrentUser( - boolean dismissKeyguard, - boolean newlyUnlocked, - TrustGrantFlags flags, - String message - ) { - if (dismissKeyguard) { - if (!mView.isVisibleToUser()) { - // The trust agent dismissed the keyguard without the user proving - // that they are present (by swiping up to show the bouncer). That's - // fine if the user proved presence via some other way to the trust - // agent. - Log.i(TAG, "TrustAgent dismissed Keyguard."); - } - mSecurityCallback.dismiss( - false /* authenticated */, - KeyguardUpdateMonitor.getCurrentUser(), - /* bypassSecondaryLockScreen */ false, - SecurityMode.Invalid - ); - } else { - if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) { - mViewMediatorCallback.playTrustedSound(); - } - } - } - }; - - private final SecurityCallback mSecurityCallback = new SecurityCallback() { - - @Override - public boolean dismiss(boolean authenticated, int targetUserId, - boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { - return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish( - authenticated, targetUserId, bypassSecondaryLockScreen, expectedSecurityMode); - } - - @Override - public void userActivity() { - mViewMediatorCallback.userActivity(); - } - - @Override - public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) { - mViewMediatorCallback.setNeedsInput(needsInput); - } - - /** - * Authentication has happened and it's time to dismiss keyguard. This function - * should clean up and inform KeyguardViewMediator. - * - * @param strongAuth whether the user has authenticated with strong authentication like - * pattern, password or PIN but not by trust agents or fingerprint - * @param targetUserId a user that needs to be the foreground user at the dismissal - * completion. - */ - @Override - public void finish(boolean strongAuth, int targetUserId) { - // If there's a pending runnable because the user interacted with a widget - // and we're leaving keyguard, then run it. - boolean deferKeyguardDone = false; - if (mDismissAction != null) { - deferKeyguardDone = mDismissAction.onDismiss(); - mDismissAction = null; - mCancelAction = null; - } - if (mViewMediatorCallback != null) { - if (deferKeyguardDone) { - mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId); - } else { - mViewMediatorCallback.keyguardDone(strongAuth, targetUserId); - } - } - } - - @Override - public void reset() { - mViewMediatorCallback.resetKeyguard(); - } - - @Override - public void onCancelClicked() { - mViewMediatorCallback.onCancelClicked(); - } - }; - - private OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event); - - @Inject - public KeyguardHostViewController(KeyguardHostView view, - KeyguardUpdateMonitor keyguardUpdateMonitor, - AudioManager audioManager, - TelephonyManager telephonyManager, - ViewMediatorCallback viewMediatorCallback, - KeyguardSecurityContainerController.Factory - keyguardSecurityContainerControllerFactory) { - super(view); - mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mAudioManager = audioManager; - mTelephonyManager = telephonyManager; - mViewMediatorCallback = viewMediatorCallback; - mKeyguardSecurityContainerController = keyguardSecurityContainerControllerFactory.create( - mSecurityCallback); - } - - /** Initialize the Controller. */ - public void onInit() { - mKeyguardSecurityContainerController.init(); - updateResources(); - } - - @Override - protected void onViewAttached() { - mView.setViewMediatorCallback(mViewMediatorCallback); - // Update ViewMediator with the current input method requirements - mViewMediatorCallback.setNeedsInput(mKeyguardSecurityContainerController.needsInput()); - mKeyguardUpdateMonitor.registerCallback(mUpdateCallback); - mView.setOnKeyListener(mOnKeyListener); - mKeyguardSecurityContainerController.showPrimarySecurityScreen(false); - } - - @Override - protected void onViewDetached() { - mKeyguardUpdateMonitor.removeCallback(mUpdateCallback); - mView.setOnKeyListener(null); - } - - /** Called before this view is being removed. */ - public void cleanUp() { - mKeyguardSecurityContainerController.onPause(); - } - - public void resetSecurityContainer() { - mKeyguardSecurityContainerController.reset(); - } - - /** - * Dismisses the keyguard by going to the next screen or making it gone. - * @param targetUserId a user that needs to be the foreground user at the dismissal completion. - * @return True if the keyguard is done. - */ - public boolean dismiss(int targetUserId) { - return mSecurityCallback.dismiss(false, targetUserId, false, - getCurrentSecurityMode()); - } - - /** - * Called when the Keyguard is actively shown on the screen. - */ - public void onResume() { - if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode())); - mKeyguardSecurityContainerController.onResume(KeyguardSecurityView.SCREEN_ON); - mView.requestFocus(); - } - - public CharSequence getAccessibilityTitleForCurrentMode() { - return mKeyguardSecurityContainerController.getTitle(); - } - - /** - * Starts the animation when the Keyguard gets shown. - */ - public void appear(int statusBarHeight) { - // We might still be collapsed and the view didn't have time to layout yet or still - // be small, let's wait on the predraw to do the animation in that case. - if (mView.getHeight() != 0 && mView.getHeight() != statusBarHeight) { - mKeyguardSecurityContainerController.startAppearAnimation(); - } else { - mView.getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - mView.getViewTreeObserver().removeOnPreDrawListener(this); - mKeyguardSecurityContainerController.startAppearAnimation(); - return true; - } - }); - mView.requestLayout(); - } - } - - /** - * Show a string explaining why the security view needs to be solved. - * - * @param reason a flag indicating which string should be shown, see - * {@link KeyguardSecurityView#PROMPT_REASON_NONE}, - * {@link KeyguardSecurityView#PROMPT_REASON_RESTART}, - * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and - * {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}. - */ - public void showPromptReason(int reason) { - mKeyguardSecurityContainerController.showPromptReason(reason); - } - - public void showMessage(CharSequence message, ColorStateList colorState) { - mKeyguardSecurityContainerController.showMessage(message, colorState); - } - - public void showErrorMessage(CharSequence customMessage) { - showMessage(customMessage, Utils.getColorError(mView.getContext())); - } - - /** - * Sets an action to run when keyguard finishes. - * - * @param action - */ - public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) { - if (mCancelAction != null) { - mCancelAction.run(); - mCancelAction = null; - } - mDismissAction = action; - mCancelAction = cancelAction; - } - - public void cancelDismissAction() { - setOnDismissAction(null, null); - } - - public void startDisappearAnimation(Runnable finishRunnable) { - if (!mKeyguardSecurityContainerController.startDisappearAnimation(finishRunnable) - && finishRunnable != null) { - finishRunnable.run(); - } - } - - /** - * Called when the Keyguard is not actively shown anymore on the screen. - */ - public void onPause() { - if (DEBUG) { - Log.d(TAG, String.format("screen off, instance %s at %s", - Integer.toHexString(hashCode()), SystemClock.uptimeMillis())); - } - mKeyguardSecurityContainerController.showPrimarySecurityScreen(true); - mKeyguardSecurityContainerController.onPause(); - mView.clearFocus(); - } - - /** - * Called when the view needs to be shown. - */ - public void showPrimarySecurityScreen() { - if (DEBUG) Log.d(TAG, "show()"); - mKeyguardSecurityContainerController.showPrimarySecurityScreen(false); - } - - /** - * Fades and translates in/out the security screen. - * Fades in as expansion approaches 0. - * Animation duration is between 0.33f and 0.67f of panel expansion fraction. - * @param fraction amount of the screen that should show. - */ - public void setExpansion(float fraction) { - float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction); - mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f)); - mView.setTranslationY(scaledFraction * mTranslationY); - } - - /** - * When bouncer was visible and is starting to become hidden. - */ - public void onStartingToHide() { - mKeyguardSecurityContainerController.onStartingToHide(); - } - - /** Called when bouncer visibility changes. */ - public void onBouncerVisibilityChanged(@View.Visibility int visibility) { - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(visibility); - } - - public boolean hasDismissActions() { - return mDismissAction != null || mCancelAction != null; - } - - public SecurityMode getCurrentSecurityMode() { - return mKeyguardSecurityContainerController.getCurrentSecurityMode(); - } - - public int getTop() { - int top = mView.getTop(); - // The password view has an extra top padding that should be ignored. - if (getCurrentSecurityMode() == SecurityMode.Password) { - View messageArea = mView.findViewById(R.id.keyguard_message_area); - top += messageArea.getTop(); - } - return top; - } - - public boolean handleBackKey() { - SecurityMode securityMode = mKeyguardSecurityContainerController.getCurrentSecurityMode(); - if (securityMode != SecurityMode.None) { - mKeyguardSecurityContainerController.dismiss( - false, KeyguardUpdateMonitor.getCurrentUser(), securityMode); - return true; - } - return false; - } - - /** - * In general, we enable unlocking the insecure keyguard with the menu key. However, there are - * some cases where we wish to disable it, notably when the menu button placement or technology - * is prone to false positives. - * - * @return true if the menu key should be enabled - */ - public boolean shouldEnableMenuKey() { - final Resources res = mView.getResources(); - final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen); - final boolean isTestHarness = ActivityManager.isRunningInTestHarness(); - final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists(); - return !configDisabled || isTestHarness || fileOverride; - } - - /** - * @return true if the current bouncer is password - */ - public boolean dispatchBackKeyEventPreIme() { - if (mKeyguardSecurityContainerController.getCurrentSecurityMode() - == SecurityMode.Password) { - return true; - } - return false; - } - - /** - * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture. - */ - @NonNull - public OnBackAnimationCallback getBackCallback() { - return mKeyguardSecurityContainerController.getBackCallback(); - } - - /** - * Allows the media keys to work when the keyguard is showing. - * The media keys should be of no interest to the actual keyguard view(s), - * so intercepting them here should not be of any harm. - * @param event The key event - * @return whether the event was consumed as a media key. - */ - public boolean interceptMediaKey(KeyEvent event) { - int keyCode = event.getKeyCode(); - if (event.getAction() == KeyEvent.ACTION_DOWN) { - switch (keyCode) { - case KeyEvent.KEYCODE_MEDIA_PLAY: - case KeyEvent.KEYCODE_MEDIA_PAUSE: - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - /* Suppress PLAY/PAUSE toggle when phone is ringing or - * in-call to avoid music playback */ - if (mTelephonyManager != null && - mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { - return true; // suppress key event - } - case KeyEvent.KEYCODE_MUTE: - case KeyEvent.KEYCODE_HEADSETHOOK: - case KeyEvent.KEYCODE_MEDIA_STOP: - case KeyEvent.KEYCODE_MEDIA_NEXT: - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - case KeyEvent.KEYCODE_MEDIA_REWIND: - case KeyEvent.KEYCODE_MEDIA_RECORD: - case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: - case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { - handleMediaKeyEvent(event); - return true; - } - - case KeyEvent.KEYCODE_VOLUME_UP: - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_VOLUME_MUTE: { - if (KEYGUARD_MANAGES_VOLUME) { - // Volume buttons should only function for music (local or remote). - // TODO: Actually handle MUTE. - mAudioManager.adjustSuggestedStreamVolume( - keyCode == KeyEvent.KEYCODE_VOLUME_UP - ? AudioManager.ADJUST_RAISE - : AudioManager.ADJUST_LOWER /* direction */, - AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */); - // Don't execute default volume behavior - return true; - } else { - return false; - } - } - } - } else if (event.getAction() == KeyEvent.ACTION_UP) { - switch (keyCode) { - case KeyEvent.KEYCODE_MUTE: - case KeyEvent.KEYCODE_HEADSETHOOK: - case KeyEvent.KEYCODE_MEDIA_PLAY: - case KeyEvent.KEYCODE_MEDIA_PAUSE: - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - case KeyEvent.KEYCODE_MEDIA_STOP: - case KeyEvent.KEYCODE_MEDIA_NEXT: - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - case KeyEvent.KEYCODE_MEDIA_REWIND: - case KeyEvent.KEYCODE_MEDIA_RECORD: - case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: - case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { - handleMediaKeyEvent(event); - return true; - } - } - } - return false; - } - - - private void handleMediaKeyEvent(KeyEvent keyEvent) { - mAudioManager.dispatchMediaKeyEvent(keyEvent); - } - - public void finish(boolean strongAuth, int currentUser) { - mSecurityCallback.finish(strongAuth, currentUser); - } - - /** - * Apply keyguard configuration from the currently active resources. This can be called when the - * device configuration changes, to re-apply some resources that are qualified on the device - * configuration. - */ - public void updateResources() { - int gravity; - - Resources resources = mView.getResources(); - - if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) { - gravity = resources.getInteger( - R.integer.keyguard_host_view_one_handed_gravity); - } else { - gravity = resources.getInteger(R.integer.keyguard_host_view_gravity); - } - - mTranslationY = resources - .getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y); - // Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout. - // We're just changing the gravity here though (which can't be applied to RelativeLayout), - // so only attempt the update if mView is inside a FrameLayout. - if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams(); - if (lp.gravity != gravity) { - lp.gravity = gravity; - mView.setLayoutParams(lp); - } - } - - if (mKeyguardSecurityContainerController != null) { - mKeyguardSecurityContainerController.updateResources(); - } - } - - /** Update keyguard position based on a tapped X coordinate. */ - public void updateKeyguardPosition(float x) { - if (mKeyguardSecurityContainerController != null) { - mKeyguardSecurityContainerController.updateKeyguardPosition(x); - } - } - - /** Set true if the view can be interacted with */ - public void setInteractable(boolean isInteractable) { - mView.setInteractable(isInteractable); - } -} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java index b143c5b90373..7054393f5fed 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java @@ -51,26 +51,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView> // The following is used to ignore callbacks from SecurityViews that are no longer current // (e.g. face unlock). This avoids unwanted asynchronous events from messing with the // state for the current security method. - private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() { - @Override - public void userActivity() { } - @Override - public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { } - @Override - public boolean isVerifyUnlockOnly() { - return false; - } - @Override - public void dismiss(boolean securityVerified, int targetUserId, - SecurityMode expectedSecurityMode) { } - @Override - public void dismiss(boolean authenticated, int targetId, - boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { } - @Override - public void onUserInput() { } - @Override - public void reset() {} - }; + private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {}; protected KeyguardInputViewController(T view, SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java index bc72f7979a74..bf9c3bbddc30 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java @@ -25,7 +25,9 @@ public interface KeyguardSecurityCallback { * @param targetUserId a user that needs to be the foreground user at the dismissal completion. * @param expectedSecurityMode The security mode that is invoking this dismiss. */ - void dismiss(boolean securityVerified, int targetUserId, SecurityMode expectedSecurityMode); + default void dismiss(boolean securityVerified, int targetUserId, + SecurityMode expectedSecurityMode) { + } /** * Dismiss the given security screen. @@ -35,19 +37,26 @@ public interface KeyguardSecurityCallback { * if any, during this dismissal. * @param expectedSecurityMode The security mode that is invoking this dismiss. */ - void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen, - SecurityMode expectedSecurityMode); + default boolean dismiss(boolean securityVerified, int targetUserId, + boolean bypassSecondaryLockScreen, + SecurityMode expectedSecurityMode) { + return false; + } /** * Manually report user activity to keep the device awake. */ - void userActivity(); + default void userActivity() { + } /** * Checks if keyguard is in "verify credentials" mode. + * * @return true if user has been asked to verify security. */ - boolean isVerifyUnlockOnly(); + default boolean isVerifyUnlockOnly() { + return false; + } /** * Call to report an unlock attempt. @@ -56,12 +65,14 @@ public interface KeyguardSecurityCallback { * @param timeoutMs timeout in milliseconds to wait before reattempting an unlock. * Only nonzero if 'success' is false */ - void reportUnlockAttempt(int userId, boolean success, int timeoutMs); + default void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { + } /** * Resets the keyguard view. */ - void reset(); + default void reset() { + } /** * Call when cancel button is pressed in bouncer. @@ -73,5 +84,19 @@ public interface KeyguardSecurityCallback { /** * Invoked whenever users are typing their password or drawing a pattern. */ - void onUserInput(); + default void onUserInput() { + } + + + /** + * Dismisses keyguard and go to unlocked state. + */ + default void finish(boolean strongAuth, int targetUserId) { + } + + /** + * Specifies that security mode has changed. + */ + default void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) { + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 9f07a20ce812..eec788b7add8 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -50,6 +50,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BlendMode; +import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; @@ -164,6 +165,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout { private boolean mDisappearAnimRunning; private SwipeListener mSwipeListener; private ViewMode mViewMode = new DefaultViewMode(); + private boolean mIsInteractable; + protected ViewMediatorCallback mViewMediatorCallback; /* * Using MODE_UNINITIALIZED to mean the view mode is set to DefaultViewMode, but init() has not * yet been called on it. This will happen when the ViewController is initialized. @@ -265,31 +268,6 @@ public class KeyguardSecurityContainer extends ConstraintLayout { return mBackCallback; } - // Used to notify the container when something interesting happens. - public interface SecurityCallback { - /** - * Potentially dismiss the current security screen, after validating that all device - * security has been unlocked. Otherwise show the next screen. - */ - boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen, - SecurityMode expectedSecurityMode); - - void userActivity(); - - void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput); - - /** - * @param strongAuth wheher the user has authenticated with strong authentication like - * pattern, password or PIN but not by trust agents or fingerprint - * @param targetUserId a user that needs to be the foreground user at the finish completion. - */ - void finish(boolean strongAuth, int targetUserId); - - void reset(); - - void onCancelClicked(); - } - public interface SwipeListener { void onSwipeUp(); } @@ -342,7 +320,7 @@ public class KeyguardSecurityContainer extends ConstraintLayout { public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y); + mSpringAnimation = new SpringAnimation(this, DynamicAnimation.TRANSLATION_Y); mViewConfiguration = ViewConfiguration.get(context); mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener()); } @@ -445,6 +423,11 @@ public class KeyguardSecurityContainer extends ConstraintLayout { mViewMode.reset(); } + /** Set true if the view can be interacted with */ + public void setInteractable(boolean isInteractable) { + mIsInteractable = isInteractable; + } + @Override public boolean shouldDelayChildPressedState() { return true; @@ -452,6 +435,10 @@ public class KeyguardSecurityContainer extends ConstraintLayout { @Override public boolean onInterceptTouchEvent(MotionEvent event) { + if (!mIsInteractable) { + return true; + } + boolean result = mMotionEventListeners.stream().anyMatch( listener -> listener.onInterceptTouchEvent(event)) || super.onInterceptTouchEvent(event); @@ -639,6 +626,18 @@ public class KeyguardSecurityContainer extends ConstraintLayout { return insets.inset(0, 0, 0, inset); } + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (mViewMediatorCallback != null) { + mViewMediatorCallback.keyguardDoneDrawing(); + } + } + + public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) { + mViewMediatorCallback = viewMediatorCallback; + } + private void showDialog(String title, String message) { if (mAlertDialog != null) { mAlertDialog.dismiss(); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 9fcacce311d1..92cbb296f270 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -29,17 +29,27 @@ import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_SECONDARY import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_WORK_PROFILE; import static com.android.systemui.DejankUtils.whitelistIpcs; +import android.app.ActivityManager; import android.app.admin.DevicePolicyManager; import android.content.Intent; import android.content.res.ColorStateList; import android.content.res.Configuration; +import android.content.res.Resources; +import android.hardware.biometrics.BiometricOverlayConstants; import android.hardware.biometrics.BiometricSourceType; +import android.media.AudioManager; import android.metrics.LogMaker; +import android.os.SystemClock; import android.os.UserHandle; +import android.telephony.TelephonyManager; import android.util.Log; +import android.util.MathUtils; import android.util.Slog; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.ViewTreeObserver; +import android.widget.FrameLayout; import android.window.OnBackAnimationCallback; import androidx.annotation.NonNull; @@ -53,7 +63,6 @@ import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardSecurityContainer.BouncerUiEvent; -import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback; import com.android.keyguard.KeyguardSecurityContainer.SwipeListener; import com.android.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.keyguard.dagger.KeyguardBouncerScope; @@ -67,6 +76,7 @@ import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.log.SessionTracker; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -75,6 +85,7 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.util.ViewController; import com.android.systemui.util.settings.GlobalSettings; +import java.io.File; import java.util.Optional; import javax.inject.Inject; @@ -95,7 +106,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard private final UiEventLogger mUiEventLogger; private final KeyguardStateController mKeyguardStateController; private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController; - private final SecurityCallback mSecurityCallback; private final ConfigurationController mConfigurationController; private final FalsingCollector mFalsingCollector; private final FalsingManager mFalsingManager; @@ -105,6 +115,20 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard private final SessionTracker mSessionTracker; private final Optional<SideFpsController> mSideFpsController; private final FalsingA11yDelegate mFalsingA11yDelegate; + private int mTranslationY; + // Whether the volume keys should be handled by keyguard. If true, then + // they will be handled here for specific media types such as music, otherwise + // the audio service will bring up the volume dialog. + private static final boolean KEYGUARD_MANAGES_VOLUME = false; + + private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key"; + + private final TelephonyManager mTelephonyManager; + private final ViewMediatorCallback mViewMediatorCallback; + private final AudioManager mAudioManager; + private View.OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event); + private ActivityStarter.OnDismissAction mDismissAction; + private Runnable mCancelAction; private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED; @@ -149,11 +173,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard }; private KeyguardSecurityCallback mKeyguardSecurityCallback = new KeyguardSecurityCallback() { - public void userActivity() { - if (mSecurityCallback != null) { - mSecurityCallback.userActivity(); - } - } @Override public void onUserInput() { @@ -168,16 +187,23 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard } @Override - public void dismiss(boolean authenticated, int targetId, + public boolean dismiss(boolean authenticated, int targetId, boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { - mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen, - expectedSecurityMode); + return showNextSecurityScreenOrFinish( + authenticated, targetId, bypassSecondaryLockScreen, expectedSecurityMode); } + @Override + public void userActivity() { + mViewMediatorCallback.userActivity(); + } + + @Override public boolean isVerifyUnlockOnly() { return false; } + @Override public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT; if (mView.isSidedSecurityMode()) { @@ -214,12 +240,47 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard : BouncerUiEvent.BOUNCER_PASSWORD_FAILURE, getSessionId()); } + @Override public void reset() { - mSecurityCallback.reset(); + mViewMediatorCallback.resetKeyguard(); } + @Override public void onCancelClicked() { - mSecurityCallback.onCancelClicked(); + mViewMediatorCallback.onCancelClicked(); + } + + /** + * Authentication has happened and it's time to dismiss keyguard. This function + * should clean up and inform KeyguardViewMediator. + * + * @param strongAuth whether the user has authenticated with strong authentication like + * pattern, password or PIN but not by trust agents or fingerprint + * @param targetUserId a user that needs to be the foreground user at the dismissal + * completion. + */ + @Override + public void finish(boolean strongAuth, int targetUserId) { + // If there's a pending runnable because the user interacted with a widget + // and we're leaving keyguard, then run it. + boolean deferKeyguardDone = false; + if (mDismissAction != null) { + deferKeyguardDone = mDismissAction.onDismiss(); + mDismissAction = null; + mCancelAction = null; + } + if (mViewMediatorCallback != null) { + if (deferKeyguardDone) { + mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId); + } else { + mViewMediatorCallback.keyguardDone(strongAuth, targetUserId); + } + } + } + + @Override + public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) { + mViewMediatorCallback.setNeedsInput(needsInput); } }; @@ -263,6 +324,34 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override + public void onTrustGrantedForCurrentUser( + boolean dismissKeyguard, + boolean newlyUnlocked, + TrustGrantFlags flags, + String message + ) { + if (dismissKeyguard) { + if (!mView.isVisibleToUser()) { + // The trust agent dismissed the keyguard without the user proving + // that they are present (by swiping up to show the bouncer). That's + // fine if the user proved presence via some other way to the trust + // agent. + Log.i(TAG, "TrustAgent dismissed Keyguard."); + } + mKeyguardSecurityCallback.dismiss( + false /* authenticated */, + KeyguardUpdateMonitor.getCurrentUser(), + /* bypassSecondaryLockScreen */ false, + SecurityMode.Invalid + ); + } else { + if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) { + mViewMediatorCallback.playTrustedSound(); + } + } + } + + @Override public void onDevicePolicyManagerStateChanged() { showPrimarySecurityScreen(false); } @@ -281,7 +370,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard } }; - private KeyguardSecurityContainerController(KeyguardSecurityContainer view, + @Inject + public KeyguardSecurityContainerController(KeyguardSecurityContainer view, AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory, LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor keyguardUpdateMonitor, @@ -289,7 +379,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard MetricsLogger metricsLogger, UiEventLogger uiEventLogger, KeyguardStateController keyguardStateController, - SecurityCallback securityCallback, KeyguardSecurityViewFlipperController securityViewFlipperController, ConfigurationController configurationController, FalsingCollector falsingCollector, @@ -299,7 +388,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard GlobalSettings globalSettings, SessionTracker sessionTracker, Optional<SideFpsController> sideFpsController, - FalsingA11yDelegate falsingA11yDelegate) { + FalsingA11yDelegate falsingA11yDelegate, + TelephonyManager telephonyManager, + ViewMediatorCallback viewMediatorCallback, + AudioManager audioManager + ) { super(view); mLockPatternUtils = lockPatternUtils; mUpdateMonitor = keyguardUpdateMonitor; @@ -307,7 +400,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mMetricsLogger = metricsLogger; mUiEventLogger = uiEventLogger; mKeyguardStateController = keyguardStateController; - mSecurityCallback = securityCallback; mSecurityViewFlipperController = securityViewFlipperController; mAdminSecondaryLockScreenController = adminSecondaryLockScreenControllerFactory.create( mKeyguardSecurityCallback); @@ -321,11 +413,15 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mSessionTracker = sessionTracker; mSideFpsController = sideFpsController; mFalsingA11yDelegate = falsingA11yDelegate; + mTelephonyManager = telephonyManager; + mViewMediatorCallback = viewMediatorCallback; + mAudioManager = audioManager; } @Override public void onInit() { mSecurityViewFlipperController.init(); + updateResources(); configureMode(); } @@ -336,6 +432,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mView.addMotionEventListener(mGlobalTouchListener); mConfigurationController.addCallback(mConfigurationListener); mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback); + mView.setViewMediatorCallback(mViewMediatorCallback); + // Update ViewMediator with the current input method requirements + mViewMediatorCallback.setNeedsInput(needsInput()); + mView.setOnKeyListener(mOnKeyListener); + showPrimarySecurityScreen(false); } @Override @@ -348,6 +449,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard /** */ public void onPause() { + if (DEBUG) { + Log.d(TAG, String.format("screen off, instance %s at %s", + Integer.toHexString(hashCode()), SystemClock.uptimeMillis())); + } + showPrimarySecurityScreen(true); mAdminSecondaryLockScreenController.hide(); if (mCurrentSecurityMode != SecurityMode.None) { getCurrentSecurityController().onPause(); @@ -356,6 +462,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard // It might happen that onStartingToHide is not called when the device is locked while on // bouncer. setBouncerVisible(false); + mView.clearFocus(); } private void updateSideFpsVisibility() { @@ -379,7 +486,8 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard + "isUnlockingWithFpAllowed=" + isUnlockingWithFpAllowed); } if (toShow) { - mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER); + mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD); } else { mSideFpsController.get().hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); } @@ -391,12 +499,22 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard * @param turningOff true if the device is being turned off */ public void showPrimarySecurityScreen(boolean turningOff) { + if (DEBUG) Log.d(TAG, "show()"); SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode( KeyguardUpdateMonitor.getCurrentUser())); if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")"); showSecurityScreen(securityMode); } + /** + * Show a string explaining why the security view needs to be solved. + * + * @param reason a flag indicating which string should be shown, see + * {@link KeyguardSecurityView#PROMPT_REASON_NONE}, + * {@link KeyguardSecurityView#PROMPT_REASON_RESTART}, + * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and + * {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}. + */ @Override public void showPromptReason(int reason) { if (mCurrentSecurityMode != SecurityMode.None) { @@ -413,8 +531,32 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard } } - public SecurityMode getCurrentSecurityMode() { - return mCurrentSecurityMode; + /** + * Sets an action to run when keyguard finishes. + * + * @param action callback to be invoked when keyguard disappear animation completes. + */ + public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) { + if (mCancelAction != null) { + mCancelAction.run(); + mCancelAction = null; + } + mDismissAction = action; + mCancelAction = cancelAction; + } + + /** + * @return whether dismiss action or cancel action has been set. + */ + public boolean hasDismissActions() { + return mDismissAction != null || mCancelAction != null; + } + + /** + * Remove any dismiss action or cancel action that was set. + */ + public void cancelDismissAction() { + setOnDismissAction(null, null); } /** @@ -426,17 +568,64 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mKeyguardSecurityCallback.dismiss(authenticated, targetUserId, expectedSecurityMode); } - public void reset() { - mView.reset(); - mSecurityViewFlipperController.reset(); + /** + * Dismisses the keyguard by going to the next screen or making it gone. + * @param targetUserId a user that needs to be the foreground user at the dismissal completion. + * @return True if the keyguard is done. + */ + public boolean dismiss(int targetUserId) { + return mKeyguardSecurityCallback.dismiss(false, targetUserId, false, + getCurrentSecurityMode()); + } + + public SecurityMode getCurrentSecurityMode() { + return mCurrentSecurityMode; } + /** + * @return the top of the corresponding view. + */ + public int getTop() { + int top = mView.getTop(); + // The password view has an extra top padding that should be ignored. + if (getCurrentSecurityMode() == SecurityMode.Password) { + View messageArea = mView.findViewById(R.id.keyguard_message_area); + top += messageArea.getTop(); + } + return top; + } + + /** Set true if the view can be interacted with */ + public void setInteractable(boolean isInteractable) { + mView.setInteractable(isInteractable); + } + + /** + * Dismiss keyguard due to a user unlock event. + */ + public void finish(boolean strongAuth, int currentUser) { + mKeyguardSecurityCallback.finish(strongAuth, currentUser); + } + + /** + * @return the text of the KeyguardMessageArea. + */ public CharSequence getTitle() { return mView.getTitle(); } + /** + * Resets the state of the views. + */ + public void reset() { + mView.reset(); + mSecurityViewFlipperController.reset(); + } + @Override public void onResume(int reason) { + if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode())); + mView.requestFocus(); if (mCurrentSecurityMode != SecurityMode.None) { int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN; if (mView.isSidedSecurityMode()) { @@ -454,6 +643,25 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mKeyguardStateController.isFaceAuthEnabled()); } + /** + * Show the bouncer and start appear animations. + * + */ + public void appear() { + // We might still be collapsed and the view didn't have time to layout yet or still + // be small, let's wait on the predraw to do the animation in that case. + mView.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + mView.getViewTreeObserver().removeOnPreDrawListener(this); + startAppearAnimation(); + return true; + } + }); + mView.requestLayout(); + } + public void startAppearAnimation() { if (mCurrentSecurityMode != SecurityMode.None) { mView.setAlpha(1f); @@ -463,12 +671,19 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard } public boolean startDisappearAnimation(Runnable onFinishRunnable) { + boolean didRunAnimation = false; + if (mCurrentSecurityMode != SecurityMode.None) { mView.startDisappearAnimation(mCurrentSecurityMode); - return getCurrentSecurityController().startDisappearAnimation(onFinishRunnable); + didRunAnimation = getCurrentSecurityController().startDisappearAnimation( + onFinishRunnable); } - return false; + if (!didRunAnimation && onFinishRunnable != null) { + onFinishRunnable.run(); + } + + return didRunAnimation; } public void onStartingToHide() { @@ -583,7 +798,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mUiEventLogger.log(uiEvent, getSessionId()); } if (finish) { - mSecurityCallback.finish(strongAuth, targetUserId); + mKeyguardSecurityCallback.finish(strongAuth, targetUserId); } return finish; } @@ -596,11 +811,114 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture. */ @NonNull - OnBackAnimationCallback getBackCallback() { + public OnBackAnimationCallback getBackCallback() { return mView.getBackCallback(); } /** + * @return whether we should dispatch the back key event before Ime. + */ + public boolean dispatchBackKeyEventPreIme() { + return getCurrentSecurityMode() == SecurityMode.Password; + } + + /** + * Allows the media keys to work when the keyguard is showing. + * The media keys should be of no interest to the actual keyguard view(s), + * so intercepting them here should not be of any harm. + * @param event The key event + * @return whether the event was consumed as a media key. + */ + public boolean interceptMediaKey(KeyEvent event) { + int keyCode = event.getKeyCode(); + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (keyCode) { + case KeyEvent.KEYCODE_MEDIA_PLAY: + case KeyEvent.KEYCODE_MEDIA_PAUSE: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + /* Suppress PLAY/PAUSE toggle when phone is ringing or + * in-call to avoid music playback */ + if (mTelephonyManager != null + && mTelephonyManager.getCallState() + != TelephonyManager.CALL_STATE_IDLE) { + return true; // suppress key event + } + return false; + case KeyEvent.KEYCODE_MUTE: + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_RECORD: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: + case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { + handleMediaKeyEvent(event); + return true; + } + + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_MUTE: { + if (KEYGUARD_MANAGES_VOLUME) { + // Volume buttons should only function for music (local or remote). + // TODO: Actually handle MUTE. + mAudioManager.adjustSuggestedStreamVolume( + keyCode == KeyEvent.KEYCODE_VOLUME_UP + ? AudioManager.ADJUST_RAISE + : AudioManager.ADJUST_LOWER /* direction */, + AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */); + // Don't execute default volume behavior + return true; + } else { + return false; + } + } + } + } else if (event.getAction() == KeyEvent.ACTION_UP) { + switch (keyCode) { + case KeyEvent.KEYCODE_MUTE: + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_PLAY: + case KeyEvent.KEYCODE_MEDIA_PAUSE: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_RECORD: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: + case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { + handleMediaKeyEvent(event); + return true; + } + } + } + return false; + } + + + private void handleMediaKeyEvent(KeyEvent keyEvent) { + mAudioManager.dispatchMediaKeyEvent(keyEvent); + } + + /** + * In general, we enable unlocking the insecure keyguard with the menu key. However, there are + * some cases where we wish to disable it, notably when the menu button placement or technology + * is prone to false positives. + * + * @return true if the menu key should be enabled + */ + public boolean shouldEnableMenuKey() { + final Resources res = mView.getResources(); + final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen); + final boolean isTestHarness = ActivityManager.isRunningInTestHarness(); + final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists(); + return !configDisabled || isTestHarness || fileOverride; + } + + + /** * Switches to the given security view unless it's already being shown, in which case * this is a no-op. * @@ -628,7 +946,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard configureMode(); } - mSecurityCallback.onSecurityModeChanged( + mKeyguardSecurityCallback.onSecurityModeChanged( securityMode, newView != null && newView.needsInput()); } @@ -726,6 +1044,30 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard * configuration. */ public void updateResources() { + int gravity; + + Resources resources = mView.getResources(); + + if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) { + gravity = resources.getInteger( + R.integer.keyguard_host_view_one_handed_gravity); + } else { + gravity = resources.getInteger(R.integer.keyguard_host_view_gravity); + } + + mTranslationY = resources + .getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y); + // Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout. + // We're just changing the gravity here though (which can't be applied to RelativeLayout), + // so only attempt the update if mView is inside a FrameLayout. + if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) { + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams(); + if (lp.gravity != gravity) { + lp.gravity = gravity; + mView.setLayoutParams(lp); + } + } + int newOrientation = getResources().getConfiguration().orientation; if (newOrientation != mLastOrientation) { mLastOrientation = newOrientation; @@ -743,93 +1085,34 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard } private void reloadColors() { - resetViewFlipper(); + reinflateViewFlipper(); mView.reloadColors(); } /** Handles density or font scale changes. */ private void onDensityOrFontScaleChanged() { - resetViewFlipper(); + reinflateViewFlipper(); mView.onDensityOrFontScaleChanged(); } - private void resetViewFlipper() { + /** + * Reinflate the view flipper child view. + */ + public void reinflateViewFlipper() { mSecurityViewFlipperController.clearViews(); mSecurityViewFlipperController.getSecurityView(mCurrentSecurityMode, mKeyguardSecurityCallback); } - static class Factory { - - private final KeyguardSecurityContainer mView; - private final AdminSecondaryLockScreenController.Factory - mAdminSecondaryLockScreenControllerFactory; - private final LockPatternUtils mLockPatternUtils; - private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final KeyguardSecurityModel mKeyguardSecurityModel; - private final MetricsLogger mMetricsLogger; - private final UiEventLogger mUiEventLogger; - private final KeyguardStateController mKeyguardStateController; - private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController; - private final ConfigurationController mConfigurationController; - private final FalsingCollector mFalsingCollector; - private final FalsingManager mFalsingManager; - private final GlobalSettings mGlobalSettings; - private final FeatureFlags mFeatureFlags; - private final UserSwitcherController mUserSwitcherController; - private final SessionTracker mSessionTracker; - private final Optional<SideFpsController> mSidefpsController; - private final FalsingA11yDelegate mFalsingA11yDelegate; - - @Inject - Factory(KeyguardSecurityContainer view, - AdminSecondaryLockScreenController.Factory - adminSecondaryLockScreenControllerFactory, - LockPatternUtils lockPatternUtils, - KeyguardUpdateMonitor keyguardUpdateMonitor, - KeyguardSecurityModel keyguardSecurityModel, - MetricsLogger metricsLogger, - UiEventLogger uiEventLogger, - KeyguardStateController keyguardStateController, - KeyguardSecurityViewFlipperController securityViewFlipperController, - ConfigurationController configurationController, - FalsingCollector falsingCollector, - FalsingManager falsingManager, - UserSwitcherController userSwitcherController, - FeatureFlags featureFlags, - GlobalSettings globalSettings, - SessionTracker sessionTracker, - Optional<SideFpsController> sidefpsController, - FalsingA11yDelegate falsingA11yDelegate) { - mView = view; - mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory; - mLockPatternUtils = lockPatternUtils; - mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mKeyguardSecurityModel = keyguardSecurityModel; - mMetricsLogger = metricsLogger; - mUiEventLogger = uiEventLogger; - mKeyguardStateController = keyguardStateController; - mSecurityViewFlipperController = securityViewFlipperController; - mConfigurationController = configurationController; - mFalsingCollector = falsingCollector; - mFalsingManager = falsingManager; - mFeatureFlags = featureFlags; - mGlobalSettings = globalSettings; - mUserSwitcherController = userSwitcherController; - mSessionTracker = sessionTracker; - mSidefpsController = sidefpsController; - mFalsingA11yDelegate = falsingA11yDelegate; - } - - public KeyguardSecurityContainerController create( - SecurityCallback securityCallback) { - return new KeyguardSecurityContainerController(mView, - mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils, - mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger, - mKeyguardStateController, securityCallback, mSecurityViewFlipperController, - mConfigurationController, mFalsingCollector, mFalsingManager, - mUserSwitcherController, mFeatureFlags, mGlobalSettings, mSessionTracker, - mSidefpsController, mFalsingA11yDelegate); - } + /** + * Fades and translates in/out the security screen. + * Fades in as expansion approaches 0. + * Animation duration is between 0.33f and 0.67f of panel expansion fraction. + * @param fraction amount of the screen that should show. + */ + public void setExpansion(float fraction) { + float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction); + mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f)); + mView.setTranslationY(scaledFraction * mTranslationY); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index bb29a7e123d8..be9264dbfcf3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1927,11 +1927,23 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab FACE_AUTH_UPDATED_STARTED_WAKING_UP.setExtraInfo(pmWakeReason); updateFaceListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_STARTED_WAKING_UP); - requestActiveUnlock( + + final ActiveUnlockConfig.ActiveUnlockRequestOrigin requestOrigin = mActiveUnlockConfig.isWakeupConsideredUnlockIntent(pmWakeReason) ? ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT - : ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE, - "wakingUp - " + PowerManager.wakeReasonToString(pmWakeReason)); + : ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE; + final String reason = "wakingUp - " + PowerManager.wakeReasonToString(pmWakeReason); + if (mActiveUnlockConfig.shouldWakeupForceDismissKeyguard(pmWakeReason)) { + requestActiveUnlockDismissKeyguard( + requestOrigin, + reason + ); + } else { + requestActiveUnlock( + requestOrigin, + reason + ); + } } else { mLogger.logSkipUpdateFaceListeningOnWakeup(pmWakeReason); } @@ -2590,6 +2602,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } + /** * Attempts to trigger active unlock from trust agent. * Only dismisses the keyguard under certain conditions. @@ -2632,6 +2645,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT, "alternateBouncer"); } + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); } private boolean shouldTriggerActiveUnlock() { @@ -2716,7 +2730,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab || shouldListenForFingerprintAssistant || (mKeyguardOccluded && mIsDreaming) || (mKeyguardOccluded && userDoesNotHaveTrust - && (mOccludingAppRequestingFp || isUdfps)); + && (mOccludingAppRequestingFp || isUdfps || mAlternateBouncerShowing)); // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. @@ -2757,6 +2771,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab System.currentTimeMillis(), user, shouldListen, + mAlternateBouncerShowing, biometricEnabledForUser, mPrimaryBouncerIsOrWillBeShowing, userCanSkipBouncer, @@ -3783,7 +3798,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } // TODO: use these callbacks elsewhere in place of the existing notifyScreen*() - // (KeyguardViewMediator, KeyguardHostView) + // (KeyguardViewMediator, KeyguardSecurityContainer) /** * Dispatch wakeup events to: * - update biometric listening states diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 8071a5de1ce9..0887b220dee1 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -466,6 +466,17 @@ public class LockIconViewController extends ViewController<LockIconView> impleme } } + /** + * @return whether the userUnlockedWithBiometric state changed + */ + private boolean updateUserUnlockedWithBiometric() { + final boolean wasUserUnlockedWithBiometric = mUserUnlockedWithBiometric; + mUserUnlockedWithBiometric = + mKeyguardUpdateMonitor.getUserUnlockedWithBiometric( + KeyguardUpdateMonitor.getCurrentUser()); + return wasUserUnlockedWithBiometric != mUserUnlockedWithBiometric; + } + private StatusBarStateController.StateListener mStatusBarStateListener = new StatusBarStateController.StateListener() { @Override @@ -503,11 +514,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @Override public void onBiometricsCleared() { - final boolean wasUserUnlockedWithBiometric = mUserUnlockedWithBiometric; - mUserUnlockedWithBiometric = - mKeyguardUpdateMonitor.getUserUnlockedWithBiometric( - KeyguardUpdateMonitor.getCurrentUser()); - if (wasUserUnlockedWithBiometric != mUserUnlockedWithBiometric) { + if (updateUserUnlockedWithBiometric()) { updateVisibility(); } } @@ -516,10 +523,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme public void onBiometricRunningStateChanged(boolean running, BiometricSourceType biometricSourceType) { final boolean wasRunningFps = mRunningFPS; - final boolean wasUserUnlockedWithBiometric = mUserUnlockedWithBiometric; - mUserUnlockedWithBiometric = - mKeyguardUpdateMonitor.getUserUnlockedWithBiometric( - KeyguardUpdateMonitor.getCurrentUser()); + final boolean userUnlockedWithBiometricChanged = + updateUserUnlockedWithBiometric(); if (biometricSourceType == FINGERPRINT) { mRunningFPS = running; @@ -537,8 +542,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme } } - if (wasUserUnlockedWithBiometric != mUserUnlockedWithBiometric - || wasRunningFps != mRunningFPS) { + if (userUnlockedWithBiometricChanged || wasRunningFps != mRunningFPS) { updateVisibility(); } } @@ -549,6 +553,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @Override public void onUnlockedChanged() { mCanDismissLockScreen = mKeyguardStateController.canDismissLockScreen(); + updateUserUnlockedWithBiometric(); updateKeyguardShowing(); updateVisibility(); } @@ -566,9 +571,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme updateKeyguardShowing(); if (mIsKeyguardShowing) { - mUserUnlockedWithBiometric = - mKeyguardUpdateMonitor.getUserUnlockedWithBiometric( - KeyguardUpdateMonitor.getCurrentUser()); + updateUserUnlockedWithBiometric(); } updateVisibility(); } diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java index 5ad21df1e652..154b0ed2c4d1 100644 --- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java +++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java @@ -18,7 +18,7 @@ package com.android.keyguard.dagger; import android.view.ViewGroup; -import com.android.keyguard.KeyguardHostViewController; +import com.android.keyguard.KeyguardSecurityContainerController; import com.android.systemui.dagger.qualifiers.RootView; import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor; @@ -37,6 +37,6 @@ public interface KeyguardBouncerComponent { KeyguardBouncerComponent create(@BindsInstance @RootView ViewGroup bouncerContainer); } - /** Returns a {@link KeyguardHostViewController}. */ - KeyguardHostViewController getKeyguardHostViewController(); + /** Returns a {@link KeyguardSecurityContainerController}. */ + KeyguardSecurityContainerController getSecurityContainerController(); } diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java index cb7a0a9b1653..38f252a221eb 100644 --- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java +++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java @@ -23,7 +23,6 @@ import android.hardware.fingerprint.FingerprintManager; import android.view.LayoutInflater; import android.view.ViewGroup; -import com.android.keyguard.KeyguardHostView; import com.android.keyguard.KeyguardSecurityContainer; import com.android.keyguard.KeyguardSecurityViewFlipper; import com.android.systemui.R; @@ -47,19 +46,13 @@ public interface KeyguardBouncerModule { /** */ @Provides @KeyguardBouncerScope - static KeyguardHostView providesKeyguardHostView(@RootView ViewGroup rootView, + static KeyguardSecurityContainer providesKeyguardSecurityContainer(@RootView ViewGroup rootView, LayoutInflater layoutInflater) { - KeyguardHostView hostView = (KeyguardHostView) layoutInflater.inflate( - R.layout.keyguard_host_view, rootView, false); - rootView.addView(hostView); - return hostView; - } - - /** */ - @Provides - @KeyguardBouncerScope - static KeyguardSecurityContainer providesKeyguardSecurityContainer(KeyguardHostView hostView) { - return hostView.findViewById(R.id.keyguard_security_container); + KeyguardSecurityContainer securityContainer = + (KeyguardSecurityContainer) layoutInflater.inflate( + R.layout.keyguard_security_container_view, rootView, false); + rootView.addView(securityContainer); + return securityContainer; } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt new file mode 100644 index 000000000000..799a4d597168 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility + +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.qs.tiles.ColorCorrectionTile +import com.android.systemui.qs.tiles.ColorInversionTile +import com.android.systemui.qs.tiles.DreamTile +import com.android.systemui.qs.tiles.FontScalingTile +import com.android.systemui.qs.tiles.NightDisplayTile +import com.android.systemui.qs.tiles.OneHandedModeTile +import com.android.systemui.qs.tiles.ReduceBrightColorsTile +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface AccessibilityModule { + + /** Inject ColorInversionTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(ColorInversionTile.TILE_SPEC) + fun bindColorInversionTile(colorInversionTile: ColorInversionTile): QSTileImpl<*> + + /** Inject NightDisplayTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(NightDisplayTile.TILE_SPEC) + fun bindNightDisplayTile(nightDisplayTile: NightDisplayTile): QSTileImpl<*> + + /** Inject ReduceBrightColorsTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(ReduceBrightColorsTile.TILE_SPEC) + fun bindReduceBrightColorsTile(reduceBrightColorsTile: ReduceBrightColorsTile): QSTileImpl<*> + + /** Inject OneHandedModeTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(OneHandedModeTile.TILE_SPEC) + fun bindOneHandedModeTile(oneHandedModeTile: OneHandedModeTile): QSTileImpl<*> + + /** Inject ColorCorrectionTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(ColorCorrectionTile.TILE_SPEC) + fun bindColorCorrectionTile(colorCorrectionTile: ColorCorrectionTile): QSTileImpl<*> + + /** Inject DreamTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(DreamTile.TILE_SPEC) + fun bindDreamTile(dreamTile: DreamTile): QSTileImpl<*> + + /** Inject FontScalingTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(FontScalingTile.TILE_SPEC) + fun bindFontScalingTile(fontScalingTile: FontScalingTile): QSTileImpl<*> +} diff --git a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt index 621b99d6804a..6721c5d5e413 100644 --- a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt @@ -31,6 +31,7 @@ import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapper import com.android.systemui.controls.controller.ControlsFavoritePersistenceWrapper import com.android.systemui.keyguard.domain.backup.KeyguardQuickAffordanceBackupHelper import com.android.systemui.people.widget.PeopleBackupHelper +import com.android.systemui.settings.UserFileManagerImpl /** * Helper for backing up elements in SystemUI @@ -58,17 +59,8 @@ open class BackupHelper : BackupAgentHelper() { override fun onCreate(userHandle: UserHandle, operationType: Int) { super.onCreate() - // The map in mapOf is guaranteed to be order preserving - val controlsMap = mapOf(CONTROLS to getPPControlsFile(this)) - NoOverwriteFileBackupHelper(controlsDataLock, this, controlsMap).also { - addHelper(NO_OVERWRITE_FILES_BACKUP_KEY, it) - } - // Conversations widgets backup only works for system user, because widgets' information is - // stored in system user's SharedPreferences files and we can't open those from other users. - if (!userHandle.isSystem) { - return - } + addControlsHelper(userHandle.identifier) val keys = PeopleBackupHelper.getFilesToBackup() addHelper( @@ -95,6 +87,18 @@ open class BackupHelper : BackupAgentHelper() { sendBroadcastAsUser(intent, UserHandle.SYSTEM, PERMISSION_SELF) } + private fun addControlsHelper(userId: Int) { + val file = UserFileManagerImpl.createFile( + userId = userId, + fileName = CONTROLS, + ) + // The map in mapOf is guaranteed to be order preserving + val controlsMap = mapOf(file.getPath() to getPPControlsFile(this, userId)) + NoOverwriteFileBackupHelper(controlsDataLock, this, controlsMap).also { + addHelper(NO_OVERWRITE_FILES_BACKUP_KEY, it) + } + } + /** * Helper class for restoring files ONLY if they are not present. * @@ -136,17 +140,21 @@ open class BackupHelper : BackupAgentHelper() { } } -private fun getPPControlsFile(context: Context): () -> Unit { +private fun getPPControlsFile(context: Context, userId: Int): () -> Unit { return { - val filesDir = context.filesDir - val file = Environment.buildPath(filesDir, BackupHelper.CONTROLS) + val file = UserFileManagerImpl.createFile( + userId = userId, + fileName = BackupHelper.CONTROLS, + ) if (file.exists()) { - val dest = - Environment.buildPath(filesDir, AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME) + val dest = UserFileManagerImpl.createFile( + userId = userId, + fileName = AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME, + ) file.copyTo(dest) val jobScheduler = context.getSystemService(JobScheduler::class.java) jobScheduler?.schedule( - AuxiliaryPersistenceWrapper.DeletionJobService.getJobForContext(context) + AuxiliaryPersistenceWrapper.DeletionJobService.getJobForContext(context, userId) ) } } diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatterySaverModule.kt b/packages/SystemUI/src/com/android/systemui/battery/BatterySaverModule.kt new file mode 100644 index 000000000000..41737902983a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/battery/BatterySaverModule.kt @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.battery + +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.qs.tiles.BatterySaverTile +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface BatterySaverModule { + + /** Inject BatterySaverTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(BatterySaverTile.TILE_SPEC) + fun bindBatterySaverTile(batterySaverTile: BatterySaverTile): QSTileImpl<*> +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt index c799e91ad36b..6c490780b79a 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt @@ -19,6 +19,8 @@ import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.app.ActivityTaskManager import android.content.Context +import android.content.res.Configuration +import android.graphics.Color import android.graphics.PixelFormat import android.graphics.PorterDuff import android.graphics.PorterDuffColorFilter @@ -90,7 +92,7 @@ constructor( private val featureFlags: FeatureFlags, dumpManager: DumpManager ) : Dumpable { - val requests: HashSet<SideFpsUiRequestSource> = HashSet() + private val requests: HashSet<SideFpsUiRequestSource> = HashSet() @VisibleForTesting val sensorProps: FingerprintSensorPropertiesInternal = @@ -98,13 +100,17 @@ constructor( ?: throw IllegalStateException("no side fingerprint sensor") @VisibleForTesting - val orientationListener = - BiometricDisplayListener( + val orientationReasonListener = + OrientationReasonListener( context, displayManager, handler, - BiometricDisplayListener.SensorType.SideFingerprint(sensorProps) - ) { onOrientationChanged() } + sensorProps, + { reason -> onOrientationChanged(reason) }, + BiometricOverlayConstants.REASON_UNKNOWN + ) + + @VisibleForTesting val orientationListener = orientationReasonListener.orientationListener @VisibleForTesting val overviewProxyListener = @@ -168,7 +174,7 @@ constructor( @BiometricOverlayConstants.ShowReason reason: Int ) = if (reason.isReasonToAutoShow(activityTaskManager)) { - show(SideFpsUiRequestSource.AUTO_SHOW) + show(SideFpsUiRequestSource.AUTO_SHOW, reason) } else { hide(SideFpsUiRequestSource.AUTO_SHOW) } @@ -198,11 +204,14 @@ constructor( } /** Shows the side fps overlay if not already shown. */ - fun show(request: SideFpsUiRequestSource) { + fun show( + request: SideFpsUiRequestSource, + @BiometricOverlayConstants.ShowReason reason: Int = BiometricOverlayConstants.REASON_UNKNOWN + ) { requests.add(request) mainExecutor.execute { if (overlayView == null) { - createOverlayForDisplay() + createOverlayForDisplay(reason) } else { Log.v(TAG, "overlay already shown") } @@ -226,13 +235,13 @@ constructor( } } - private fun onOrientationChanged() { + private fun onOrientationChanged(@BiometricOverlayConstants.ShowReason reason: Int) { if (overlayView != null) { - createOverlayForDisplay() + createOverlayForDisplay(reason) } } - private fun createOverlayForDisplay() { + private fun createOverlayForDisplay(@BiometricOverlayConstants.ShowReason reason: Int) { val view = layoutInflater.inflate(R.layout.sidefps_view, null, false) overlayView = view val display = context.display!! @@ -263,7 +272,8 @@ constructor( updateOverlayParams(display, it.bounds) } } - lottie.addOverlayDynamicColor(context) + orientationReasonListener.reason = reason + lottie.addOverlayDynamicColor(context, reason) /** * Intercepts TYPE_WINDOW_STATE_CHANGED accessibility event, preventing Talkback from @@ -418,17 +428,36 @@ private fun Display.isNaturalOrientation(): Boolean = private fun WindowInsets.hasBigNavigationBar(): Boolean = getInsets(WindowInsets.Type.navigationBars()).bottom >= 70 -private fun LottieAnimationView.addOverlayDynamicColor(context: Context) { +private fun LottieAnimationView.addOverlayDynamicColor( + context: Context, + @BiometricOverlayConstants.ShowReason reason: Int +) { fun update() { val c = context.getColor(R.color.biometric_dialog_accent) val chevronFill = context.getColor(R.color.sfps_chevron_fill) - for (key in listOf(".blue600", ".blue400")) { - addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) { - PorterDuffColorFilter(c, PorterDuff.Mode.SRC_ATOP) + val isKeyguard = reason == REASON_AUTH_KEYGUARD + if (isKeyguard) { + for (key in listOf(".blue600", ".blue400")) { + addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) { + PorterDuffColorFilter(c, PorterDuff.Mode.SRC_ATOP) + } + } + addValueCallback(KeyPath(".black", "**"), LottieProperty.COLOR_FILTER) { + PorterDuffColorFilter(chevronFill, PorterDuff.Mode.SRC_ATOP) + } + } else if (!isDarkMode(context)) { + addValueCallback(KeyPath(".black", "**"), LottieProperty.COLOR_FILTER) { + PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP) + } + } else if (isDarkMode(context)) { + for (key in listOf(".blue600", ".blue400")) { + addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) { + PorterDuffColorFilter( + context.getColor(R.color.settingslib_color_blue400), + PorterDuff.Mode.SRC_ATOP + ) + } } - } - addValueCallback(KeyPath(".black", "**"), LottieProperty.COLOR_FILTER) { - PorterDuffColorFilter(chevronFill, PorterDuff.Mode.SRC_ATOP) } } @@ -439,6 +468,29 @@ private fun LottieAnimationView.addOverlayDynamicColor(context: Context) { } } +private fun isDarkMode(context: Context): Boolean { + val darkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK + return darkMode == Configuration.UI_MODE_NIGHT_YES +} + +@VisibleForTesting +class OrientationReasonListener( + context: Context, + displayManager: DisplayManager, + handler: Handler, + sensorProps: FingerprintSensorPropertiesInternal, + onOrientationChanged: (reason: Int) -> Unit, + @BiometricOverlayConstants.ShowReason var reason: Int +) { + val orientationListener = + BiometricDisplayListener( + context, + displayManager, + handler, + BiometricDisplayListener.SensorType.SideFingerprint(sensorProps) + ) { onOrientationChanged(reason) } +} + /** * The source of a request to show the side fps visual indicator. This is distinct from * [BiometricOverlayConstants] which corrresponds with the reason fingerprint authentication is diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java index 82bb7237cab0..edda87527b1d 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java @@ -97,8 +97,9 @@ public class ClipboardListener implements return; } - if (!isUserSetupComplete()) { - // just show a toast, user should not access intents from this state + if (!isUserSetupComplete() // user should not access intents from this state + || clipData == null // shouldn't happen, but just in case + || clipData.getItemCount() == 0) { if (shouldShowToast(clipData)) { mUiEventLogger.log(CLIPBOARD_TOAST_SHOWN, 0, clipSource); mClipboardToast.showCopiedToast(); diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardModel.kt b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardModel.kt index c7aaf09d6551..789833c6d849 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardModel.kt +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardModel.kt @@ -19,19 +19,23 @@ import android.content.ClipData import android.content.ClipDescription.EXTRA_IS_SENSITIVE import android.content.Context import android.graphics.Bitmap +import android.net.Uri import android.text.TextUtils import android.util.Log import android.util.Size +import android.view.textclassifier.TextLinks import com.android.systemui.R import java.io.IOException data class ClipboardModel( - val clipData: ClipData?, + val clipData: ClipData, val source: String, - val type: Type = Type.OTHER, - val item: ClipData.Item? = null, - val isSensitive: Boolean = false, - val isRemote: Boolean = false, + val type: Type, + val text: CharSequence?, + val textLinks: TextLinks?, + val uri: Uri?, + val isSensitive: Boolean, + val isRemote: Boolean, ) { private var _bitmap: Bitmap? = null @@ -41,17 +45,16 @@ data class ClipboardModel( } return source == other.source && type == other.type && - item?.text == other.item?.text && - item?.uri == other.item?.uri && + text == other.text && + uri == other.uri && isSensitive == other.isSensitive } fun loadThumbnail(context: Context): Bitmap? { - if (_bitmap == null && type == Type.IMAGE && item?.uri != null) { + if (_bitmap == null && type == Type.IMAGE && uri != null) { try { val size = context.resources.getDimensionPixelSize(R.dimen.overlay_x_scale) - _bitmap = - context.contentResolver.loadThumbnail(item.uri, Size(size, size * 4), null) + _bitmap = context.contentResolver.loadThumbnail(uri, Size(size, size * 4), null) } catch (e: IOException) { Log.e(TAG, "Thumbnail loading failed!", e) } @@ -66,27 +69,34 @@ data class ClipboardModel( fun fromClipData( context: Context, utils: ClipboardOverlayUtils, - clipData: ClipData?, + clipData: ClipData, source: String ): ClipboardModel { - if (clipData == null || clipData.itemCount == 0) { - return ClipboardModel(clipData, source) - } val sensitive = clipData.description?.extras?.getBoolean(EXTRA_IS_SENSITIVE) ?: false val item = clipData.getItemAt(0)!! val type = getType(context, item) val remote = utils.isRemoteCopy(context, clipData, source) - return ClipboardModel(clipData, source, type, item, sensitive, remote) + return ClipboardModel( + clipData, + source, + type, + item.text, + item.textLinks, + item.uri, + sensitive, + remote + ) } private fun getType(context: Context, item: ClipData.Item): Type { return if (!TextUtils.isEmpty(item.text)) { Type.TEXT - } else if ( - item.uri != null && - context.contentResolver.getType(item.uri)?.startsWith("image") == true - ) { - Type.IMAGE + } else if (item.uri != null) { + if (context.contentResolver.getType(item.uri)?.startsWith("image") == true) { + Type.IMAGE + } else { + Type.URI + } } else { Type.OTHER } @@ -96,6 +106,7 @@ data class ClipboardModel( enum class Type { TEXT, IMAGE, + URI, OTHER } } diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java index b41f30844e27..c214f5341450 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java @@ -19,7 +19,6 @@ package com.android.systemui.clipboardoverlay; import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_ACTIONS; -import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_TAPPED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISSED_OTHER; @@ -103,7 +102,6 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv private Runnable mOnSessionCompleteListener; private Runnable mOnRemoteCopyTapped; private Runnable mOnShareTapped; - private Runnable mOnEditTapped; private Runnable mOnPreviewTapped; private InputMonitor mInputMonitor; @@ -155,13 +153,6 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv } @Override - public void onEditButtonTapped() { - if (mOnEditTapped != null) { - mOnEditTapped.run(); - } - } - - @Override public void onRemoteCopyButtonTapped() { if (mOnRemoteCopyTapped != null) { mOnRemoteCopyTapped.run(); @@ -309,14 +300,14 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv if ((mFeatureFlags.isEnabled(CLIPBOARD_REMOTE_BEHAVIOR) && model.isRemote()) || DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_SHOW_ACTIONS, false)) { - if (model.getItem().getTextLinks() != null) { + if (model.getTextLinks() != null) { classifyText(model); } } if (model.isSensitive()) { mView.showTextPreview(mContext.getString(R.string.clipboard_asterisks), true); } else { - mView.showTextPreview(model.getItem().getText(), false); + mView.showTextPreview(model.getText(), false); } mView.setEditAccessibilityAction(true); mOnPreviewTapped = this::editText; @@ -326,12 +317,13 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv mView.showImagePreview( model.isSensitive() ? null : model.loadThumbnail(mContext)); mView.setEditAccessibilityAction(true); - mOnPreviewTapped = () -> editImage(model.getItem().getUri()); + mOnPreviewTapped = () -> editImage(model.getUri()); } else { // image loading failed mView.showDefaultTextPreview(); } break; + case URI: case OTHER: mView.showDefaultTextPreview(); break; @@ -371,8 +363,8 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv private void classifyText(ClipboardModel model) { mBgExecutor.execute(() -> { - Optional<RemoteAction> remoteAction = - mClipboardUtils.getAction(model.getItem(), model.getSource()); + Optional<RemoteAction> remoteAction = mClipboardUtils.getAction( + model.getText(), model.getTextLinks(), model.getSource()); if (model.equals(mClipboardModel)) { remoteAction.ifPresent(action -> { mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_ACTION_SHOWN); @@ -419,10 +411,10 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv accessibilityAnnouncement = mContext.getString(R.string.clipboard_text_copied); } else if (clipData.getItemAt(0).getUri() != null) { if (tryShowEditableImage(clipData.getItemAt(0).getUri(), isSensitive)) { - mOnShareTapped = () -> shareContent(clipData); - mView.showShareChip(); accessibilityAnnouncement = mContext.getString(R.string.clipboard_image_copied); } + mOnShareTapped = () -> shareContent(clipData); + mView.showShareChip(); } else { mView.showDefaultTextPreview(); } @@ -522,11 +514,6 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv mView.showTextPreview(text, hidden); mView.setEditAccessibilityAction(true); mOnPreviewTapped = this::editText; - if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, - CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON, false)) { - mOnEditTapped = this::editText; - mView.showEditChip(mContext.getString(R.string.clipboard_edit_text_description)); - } } private boolean tryShowEditableImage(Uri uri, boolean isSensitive) { @@ -557,10 +544,6 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv } else { mView.showDefaultTextPreview(); } - if (isEditableImage && DeviceConfig.getBoolean( - DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON, false)) { - mView.showEditChip(mContext.getString(R.string.clipboard_edit_image_description)); - } return isEditableImage; } @@ -636,7 +619,6 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv private void reset() { mOnRemoteCopyTapped = null; mOnShareTapped = null; - mOnEditTapped = null; mOnPreviewTapped = null; mView.reset(); mTimeoutHandler.cancelTimeout(); diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java index 785e4a0743e4..a85f8b9357f5 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java @@ -65,6 +65,23 @@ class ClipboardOverlayUtils { return false; } + public Optional<RemoteAction> getAction(CharSequence text, TextLinks textLinks, String source) { + return getActions(text, textLinks).stream().filter(remoteAction -> { + ComponentName component = remoteAction.getActionIntent().getIntent().getComponent(); + return component != null && !TextUtils.equals(source, component.getPackageName()); + }).findFirst(); + } + + private ArrayList<RemoteAction> getActions(CharSequence text, TextLinks textLinks) { + ArrayList<RemoteAction> actions = new ArrayList<>(); + for (TextLinks.TextLink link : textLinks.getLinks()) { + TextClassification classification = mTextClassifier.classifyText( + text, link.getStart(), link.getEnd(), null); + actions.addAll(classification.getActions()); + } + return actions; + } + public Optional<RemoteAction> getAction(ClipData.Item item, String source) { return getActions(item).stream().filter(remoteAction -> { ComponentName component = remoteAction.getActionIntent().getIntent().getComponent(); diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java index c9e01ce179f6..f372bb4bc7f2 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java @@ -70,8 +70,6 @@ public class ClipboardOverlayView extends DraggableConstraintLayout { void onRemoteCopyButtonTapped(); - void onEditButtonTapped(); - void onShareButtonTapped(); void onPreviewTapped(); @@ -94,7 +92,6 @@ public class ClipboardOverlayView extends DraggableConstraintLayout { private TextView mHiddenPreview; private LinearLayout mMinimizedPreview; private View mPreviewBorder; - private OverlayActionChip mEditChip; private OverlayActionChip mShareChip; private OverlayActionChip mRemoteCopyChip; private View mActionContainerBackground; @@ -126,18 +123,14 @@ public class ClipboardOverlayView extends DraggableConstraintLayout { mTextPreview = requireViewById(R.id.text_preview); mHiddenPreview = requireViewById(R.id.hidden_preview); mMinimizedPreview = requireViewById(R.id.minimized_preview); - mEditChip = requireViewById(R.id.edit_chip); mShareChip = requireViewById(R.id.share_chip); mRemoteCopyChip = requireViewById(R.id.remote_copy_chip); mDismissButton = requireViewById(R.id.dismiss_button); - mEditChip.setAlpha(1); mShareChip.setAlpha(1); mRemoteCopyChip.setAlpha(1); mShareChip.setContentDescription(mContext.getString(com.android.internal.R.string.share)); - mEditChip.setIcon( - Icon.createWithResource(mContext, R.drawable.ic_screenshot_edit), true); mRemoteCopyChip.setIcon( Icon.createWithResource(mContext, R.drawable.ic_baseline_devices_24), true); mShareChip.setIcon( @@ -159,7 +152,6 @@ public class ClipboardOverlayView extends DraggableConstraintLayout { public void setCallbacks(SwipeDismissCallbacks callbacks) { super.setCallbacks(callbacks); ClipboardOverlayCallbacks clipboardCallbacks = (ClipboardOverlayCallbacks) callbacks; - mEditChip.setOnClickListener(v -> clipboardCallbacks.onEditButtonTapped()); mShareChip.setOnClickListener(v -> clipboardCallbacks.onShareButtonTapped()); mDismissButton.setOnClickListener(v -> clipboardCallbacks.onDismissButtonTapped()); mRemoteCopyChip.setOnClickListener(v -> clipboardCallbacks.onRemoteCopyButtonTapped()); @@ -259,7 +251,6 @@ public class ClipboardOverlayView extends DraggableConstraintLayout { updateTextSize(text, textView); } }); - mEditChip.setVisibility(View.GONE); } void showImagePreview(@Nullable Bitmap thumbnail) { @@ -272,12 +263,6 @@ public class ClipboardOverlayView extends DraggableConstraintLayout { } } - void showEditChip(String contentDescription) { - mEditChip.setVisibility(View.VISIBLE); - mActionContainerBackground.setVisibility(View.VISIBLE); - mEditChip.setContentDescription(contentDescription); - } - void showShareChip() { mShareChip.setVisibility(View.VISIBLE); mActionContainerBackground.setVisibility(View.VISIBLE); @@ -289,7 +274,6 @@ public class ClipboardOverlayView extends DraggableConstraintLayout { mActionContainerBackground.setVisibility(View.GONE); mDismissButton.setVisibility(View.GONE); mShareChip.setVisibility(View.GONE); - mEditChip.setVisibility(View.GONE); mRemoteCopyChip.setVisibility(View.GONE); setEditAccessibilityAction(false); resetActionChips(); diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt index 0a6335e01f9f..b3c18fb3cd98 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt @@ -21,8 +21,10 @@ import android.app.job.JobParameters import android.app.job.JobService import android.content.ComponentName import android.content.Context +import android.os.PersistableBundle import com.android.internal.annotations.VisibleForTesting import com.android.systemui.backup.BackupHelper +import com.android.systemui.settings.UserFileManagerImpl import java.io.File import java.util.concurrent.Executor import java.util.concurrent.TimeUnit @@ -33,14 +35,14 @@ import java.util.concurrent.TimeUnit * This file is a copy of the `controls_favorites.xml` file restored from a back up. It is used to * keep track of controls that were restored but its corresponding app has not been installed yet. */ -class AuxiliaryPersistenceWrapper @VisibleForTesting internal constructor( - wrapper: ControlsFavoritePersistenceWrapper -) { +class AuxiliaryPersistenceWrapper +@VisibleForTesting +internal constructor(wrapper: ControlsFavoritePersistenceWrapper) { constructor( file: File, executor: Executor - ): this(ControlsFavoritePersistenceWrapper(file, executor)) + ) : this(ControlsFavoritePersistenceWrapper(file, executor)) companion object { const val AUXILIARY_FILE_NAME = "aux_controls_favorites.xml" @@ -48,9 +50,7 @@ class AuxiliaryPersistenceWrapper @VisibleForTesting internal constructor( private var persistenceWrapper: ControlsFavoritePersistenceWrapper = wrapper - /** - * Access the current list of favorites as tracked by the auxiliary file - */ + /** Access the current list of favorites as tracked by the auxiliary file */ var favorites: List<StructureInfo> = emptyList() private set @@ -73,18 +73,19 @@ class AuxiliaryPersistenceWrapper @VisibleForTesting internal constructor( * exist, it will be initialized to an empty list. */ fun initialize() { - favorites = if (persistenceWrapper.fileExists) { - persistenceWrapper.readFavorites() - } else { - emptyList() - } + favorites = + if (persistenceWrapper.fileExists) { + persistenceWrapper.readFavorites() + } else { + emptyList() + } } /** * Gets the list of favorite controls as persisted in the auxiliary file for a given component. * - * When the favorites for that application are returned, they will be removed from the - * auxiliary file immediately, so they won't be retrieved again. + * When the favorites for that application are returned, they will be removed from the auxiliary + * file immediately, so they won't be retrieved again. * @param componentName the name of the service that provided the controls * @return a list of structures with favorites */ @@ -103,20 +104,20 @@ class AuxiliaryPersistenceWrapper @VisibleForTesting internal constructor( } } - /** - * [JobService] to delete the auxiliary file after a week. - */ + /** [JobService] to delete the auxiliary file after a week. */ class DeletionJobService : JobService() { companion object { - @VisibleForTesting - internal val DELETE_FILE_JOB_ID = 1000 + @VisibleForTesting internal val DELETE_FILE_JOB_ID = 1000 + @VisibleForTesting internal val USER = "USER" private val WEEK_IN_MILLIS = TimeUnit.DAYS.toMillis(7) - fun getJobForContext(context: Context): JobInfo { + fun getJobForContext(context: Context, targetUserId: Int): JobInfo { val jobId = DELETE_FILE_JOB_ID + context.userId val componentName = ComponentName(context, DeletionJobService::class.java) + val bundle = PersistableBundle().also { it.putInt(USER, targetUserId) } return JobInfo.Builder(jobId, componentName) .setMinimumLatency(WEEK_IN_MILLIS) .setPersisted(true) + .setExtras(bundle) .build() } } @@ -127,8 +128,14 @@ class AuxiliaryPersistenceWrapper @VisibleForTesting internal constructor( } override fun onStartJob(params: JobParameters): Boolean { + val userId = params.getExtras()?.getInt(USER, 0) ?: 0 synchronized(BackupHelper.controlsDataLock) { - baseContext.deleteFile(AUXILIARY_FILE_NAME) + val file = + UserFileManagerImpl.createFile( + userId = userId, + fileName = AUXILIARY_FILE_NAME, + ) + baseContext.deleteFile(file.getPath()) } return false } @@ -137,4 +144,4 @@ class AuxiliaryPersistenceWrapper @VisibleForTesting internal constructor( return true // reschedule and try again if the job was stopped without completing } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt index 6af8e73c8d25..d949d1119222 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt @@ -44,12 +44,15 @@ import com.android.systemui.controls.ui.ControlsActivity import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.controls.ui.ControlsUiControllerImpl import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.qs.tiles.DeviceControlsTile import dagger.Binds import dagger.BindsOptionalOf import dagger.Module import dagger.Provides import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey /** * Module for injecting classes in `com.android.systemui.controls`- @@ -149,4 +152,9 @@ abstract class ControlsModule { @IntoMap @ClassKey(ControlsActivity::class) abstract fun provideControlsActivity(activity: ControlsActivity): Activity + + @Binds + @IntoMap + @StringKey(DeviceControlsTile.TILE_SPEC) + abstract fun bindDeviceControlsTile(controlsTile: DeviceControlsTile): QSTileImpl<*> } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java index fd690dfd5dfa..03a1dc068d3d 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java @@ -27,6 +27,7 @@ import androidx.annotation.Nullable; import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardViewController; +import com.android.systemui.battery.BatterySaverModule; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerImpl; @@ -40,6 +41,7 @@ import com.android.systemui.qs.dagger.QSModule; import com.android.systemui.qs.tileimpl.QSFactoryImpl; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsImplementation; +import com.android.systemui.rotationlock.RotationLockModule; import com.android.systemui.screenshot.ReferenceScreenshotModule; import com.android.systemui.shade.NotificationShadeWindowControllerImpl; import com.android.systemui.shade.ShadeController; @@ -92,11 +94,13 @@ import dagger.Provides; */ @Module(includes = { AospPolicyModule.class, + BatterySaverModule.class, GestureModule.class, MediaModule.class, PowerModule.class, QSModule.class, ReferenceScreenshotModule.class, + RotationLockModule.class, StartCentralSurfacesModule.class, VolumeModule.class }) diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt index cb7c765d0549..947888bfb187 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt @@ -30,6 +30,7 @@ import com.android.systemui.controls.dagger.StartControlsStartableModule import com.android.systemui.dagger.qualifiers.PerUser import com.android.systemui.dreams.DreamMonitor import com.android.systemui.globalactions.GlobalActionsComponent +import com.android.systemui.keyboard.PhysicalKeyboardCoreStartable import com.android.systemui.keyboard.KeyboardUI import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.data.quickaffordance.MuteQuickAffordanceCoreStartable @@ -55,7 +56,6 @@ import com.android.systemui.theme.ThemeOverlayController import com.android.systemui.toast.ToastUI import com.android.systemui.usb.StorageNotification import com.android.systemui.util.NotificationChannels -import com.android.systemui.util.leak.GarbageMonitor import com.android.systemui.volume.VolumeUI import com.android.systemui.wmshell.WMShell import dagger.Binds @@ -107,12 +107,6 @@ abstract class SystemUICoreStartableModule { @ClassKey(FsiChromeViewBinder::class) abstract fun bindFsiChromeWindowBinder(sysui: FsiChromeViewBinder): CoreStartable - /** Inject into GarbageMonitor.Service. */ - @Binds - @IntoMap - @ClassKey(GarbageMonitor::class) - abstract fun bindGarbageMonitorService(sysui: GarbageMonitor.Service): CoreStartable - /** Inject into GlobalActionsComponent. */ @Binds @IntoMap @@ -293,6 +287,11 @@ abstract class SystemUICoreStartableModule { @ClassKey(StylusUsiPowerStartable::class) abstract fun bindStylusUsiPowerStartable(sysui: StylusUsiPowerStartable): CoreStartable + @Binds + @IntoMap + @ClassKey(PhysicalKeyboardCoreStartable::class) + abstract fun bindKeyboardCoreStartable(listener: PhysicalKeyboardCoreStartable): CoreStartable + /** Inject into MuteQuickAffordanceCoreStartable*/ @Binds @IntoMap diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index c3ee9bee19db..5b4ce065791d 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -28,6 +28,7 @@ import com.android.keyguard.dagger.ClockRegistryModule; import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.systemui.BootCompleteCache; import com.android.systemui.BootCompleteCacheImpl; +import com.android.systemui.accessibility.AccessibilityModule; import com.android.systemui.appops.dagger.AppOpsModule; import com.android.systemui.assist.AssistModule; import com.android.systemui.biometrics.AlternateUdfpsTouchProvider; @@ -46,6 +47,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FlagsModule; import com.android.systemui.fragments.FragmentService; +import com.android.systemui.keyboard.KeyboardModule; import com.android.systemui.keyguard.data.BouncerViewModule; import com.android.systemui.log.dagger.LogModule; import com.android.systemui.mediaprojection.appselector.MediaProjectionModule; @@ -57,10 +59,12 @@ import com.android.systemui.people.PeopleModule; import com.android.systemui.plugins.BcSmartspaceConfigPlugin; import com.android.systemui.plugins.BcSmartspaceDataPlugin; import com.android.systemui.privacy.PrivacyModule; +import com.android.systemui.qrcodescanner.dagger.QRCodeScannerModule; import com.android.systemui.qs.FgsManagerController; import com.android.systemui.qs.FgsManagerControllerImpl; import com.android.systemui.qs.footer.dagger.FooterActionsModule; import com.android.systemui.recents.Recents; +import com.android.systemui.screenrecord.ScreenRecordModule; import com.android.systemui.screenshot.dagger.ScreenshotModule; import com.android.systemui.security.data.repository.SecurityRepositoryModule; import com.android.systemui.settings.DisplayTracker; @@ -70,6 +74,7 @@ import com.android.systemui.smartspace.dagger.SmartspaceModule; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.connectivity.ConnectivityModule; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl; @@ -85,6 +90,7 @@ import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent; import com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.policy.PolicyModule; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.dagger.SmartRepliesInflationModule; import com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule; @@ -97,6 +103,7 @@ import com.android.systemui.user.UserModule; import com.android.systemui.util.concurrency.SysUIConcurrencyModule; import com.android.systemui.util.dagger.UtilModule; import com.android.systemui.util.kotlin.CoroutinesModule; +import com.android.systemui.util.leak.GarbageMonitorModule; import com.android.systemui.util.sensors.SensorModule; import com.android.systemui.util.settings.SettingsUtilModule; import com.android.systemui.util.time.SystemClock; @@ -126,6 +133,7 @@ import dagger.Provides; * may not appreciate that. */ @Module(includes = { + AccessibilityModule.class, AppOpsModule.class, AssistModule.class, BiometricsModule.class, @@ -133,6 +141,7 @@ import dagger.Provides; ClipboardOverlayModule.class, ClockInfoModule.class, ClockRegistryModule.class, + ConnectivityModule.class, CoroutinesModule.class, DreamModule.class, ControlsModule.class, @@ -141,17 +150,22 @@ import dagger.Provides; FlagsModule.class, SystemPropertiesFlagsModule.class, FooterActionsModule.class, + GarbageMonitorModule.class, + KeyboardModule.class, LogModule.class, MediaProjectionModule.class, MotionToolModule.class, PeopleHubModule.class, PeopleModule.class, PluginModule.class, + PolicyModule.class, PrivacyModule.class, + QRCodeScannerModule.class, ScreenshotModule.class, SensorModule.class, MultiUserUtilsModule.class, SecurityRepositoryModule.class, + ScreenRecordModule.class, SettingsUtilModule.class, SmartRepliesInflationModule.class, SmartspaceModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index dd01be0ef031..5aebc3268b90 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -243,6 +243,8 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ */ private void addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) { mWindow = new PhoneWindow(mContext); + // Default to SystemUI name for TalkBack. + mWindow.setTitle(""); mWindow.setAttributes(layoutParams); mWindow.setWindowManager(null, layoutParams.token, "DreamOverlay", true); diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java index 90c440c403ec..7394e2366ac9 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java @@ -257,7 +257,8 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve mConnectivityManager.getActiveNetwork()); final boolean available = capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI); - showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, !available); + showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, !available, + R.string.wifi_unavailable_dream_overlay_content_description); } private void updateAlarmStatusIcon() { @@ -294,13 +295,16 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve @DreamOverlayStatusBarView.StatusIconType int iconType = Resources.ID_NULL; showIcon( DreamOverlayStatusBarView.STATUS_ICON_CAMERA_DISABLED, - !micBlocked && cameraBlocked); + !micBlocked && cameraBlocked, + R.string.camera_blocked_dream_overlay_content_description); showIcon( DreamOverlayStatusBarView.STATUS_ICON_MIC_DISABLED, - micBlocked && !cameraBlocked); + micBlocked && !cameraBlocked, + R.string.microphone_blocked_dream_overlay_content_description); showIcon( DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, - micBlocked && cameraBlocked); + micBlocked && cameraBlocked, + R.string.camera_and_microphone_blocked_dream_overlay_content_description); } private String buildNotificationsContentDescription(int notificationCount) { @@ -313,11 +317,13 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve private void updatePriorityModeStatusIcon() { showIcon( DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, - mZenModeController.getZen() != Settings.Global.ZEN_MODE_OFF); + mZenModeController.getZen() != Settings.Global.ZEN_MODE_OFF, + R.string.priority_mode_dream_overlay_content_description); } - private void showIcon(@DreamOverlayStatusBarView.StatusIconType int iconType, boolean show) { - showIcon(iconType, show, null); + private void showIcon(@DreamOverlayStatusBarView.StatusIconType int iconType, boolean show, + int contentDescriptionResId) { + showIcon(iconType, show, mResources.getString(contentDescriptionResId)); } private void showIcon( diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt index dc7fc28f3c0d..06ca0adfa928 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt @@ -22,6 +22,7 @@ import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.dump.DumpManager import com.android.systemui.statusbar.commandline.CommandRegistry import com.android.systemui.util.InitializationChecker +import com.android.systemui.util.concurrency.DelayableExecutor import dagger.Binds import dagger.Module import dagger.multibindings.ClassKey @@ -36,7 +37,9 @@ constructor( private val flagCommand: FlagCommand, private val featureFlags: FeatureFlagsDebug, private val broadcastSender: BroadcastSender, - private val initializationChecker: InitializationChecker + private val initializationChecker: InitializationChecker, + private val restartDozeListener: RestartDozeListener, + private val delayableExecutor: DelayableExecutor ) : CoreStartable { init { @@ -52,6 +55,9 @@ constructor( // protected broadcast should only be sent for the main process val intent = Intent(FlagManager.ACTION_SYSUI_STARTED) broadcastSender.sendBroadcast(intent) + + restartDozeListener.init() + delayableExecutor.executeDelayed({ restartDozeListener.maybeRestartSleep() }, 1000) } } } diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseStartable.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseStartable.kt index d088d7414035..133e67f2822b 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseStartable.kt @@ -18,6 +18,8 @@ package com.android.systemui.flags import com.android.systemui.CoreStartable import com.android.systemui.dump.DumpManager +import com.android.systemui.util.InitializationChecker +import com.android.systemui.util.concurrency.DelayableExecutor import dagger.Binds import dagger.Module import dagger.multibindings.ClassKey @@ -26,7 +28,13 @@ import javax.inject.Inject class FeatureFlagsReleaseStartable @Inject -constructor(dumpManager: DumpManager, featureFlags: FeatureFlags) : CoreStartable { +constructor( + dumpManager: DumpManager, + featureFlags: FeatureFlags, + private val initializationChecker: InitializationChecker, + private val restartDozeListener: RestartDozeListener, + private val delayableExecutor: DelayableExecutor +) : CoreStartable { init { dumpManager.registerCriticalDumpable(FeatureFlagsRelease.TAG) { pw, args -> @@ -35,7 +43,10 @@ constructor(dumpManager: DumpManager, featureFlags: FeatureFlags) : CoreStartabl } override fun start() { - // no-op + if (initializationChecker.initializeComponents()) { + restartDozeListener.init() + delayableExecutor.executeDelayed({ restartDozeListener.maybeRestartSleep() }, 1000) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 4d89c6cb9a9f..343fcb0e9c5f 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -100,7 +100,7 @@ object Flags { // TODO(b/260335638): Tracking Bug @JvmField val NOTIFICATION_INLINE_REPLY_ANIMATION = - unreleasedFlag(174148361, "notification_inline_reply_animation", teamfood = true) + releasedFlag(174148361, "notification_inline_reply_animation") val FILTER_UNSEEN_NOTIFS_ON_KEYGUARD = releasedFlag(254647461, "filter_unseen_notifs_on_keyguard", teamfood = true) @@ -556,7 +556,8 @@ object Flags { // 1700 - clipboard @JvmField val CLIPBOARD_REMOTE_BEHAVIOR = releasedFlag(1701, "clipboard_remote_behavior") // TODO(b/267162944): Tracking bug - @JvmField val CLIPBOARD_MINIMIZED_LAYOUT = unreleasedFlag(1702, "clipboard_data_model") + @JvmField + val CLIPBOARD_MINIMIZED_LAYOUT = unreleasedFlag(1702, "clipboard_data_model", teamfood = true) // 1800 - shade container @JvmField @@ -578,6 +579,12 @@ object Flags { val CONTROLS_MANAGEMENT_NEW_FLOWS = unreleasedFlag(2002, "controls_management_new_flows", teamfood = true) + // Enables removing app from Home control panel as a part of a new flow + // TODO(b/269132640): Tracking Bug + @JvmField + val APP_PANELS_REMOVE_APPS_ALLOWED = + unreleasedFlag(2003, "app_panels_remove_apps_allowed", teamfood = false) + // 2100 - Falsing Manager @JvmField val FALSING_FOR_LONG_TAPS = releasedFlag(2100, "falsing_for_long_taps") @@ -613,7 +620,7 @@ object Flags { // TODO(b/20911786): Tracking Bug @JvmField val OUTPUT_SWITCHER_SHOW_API_ENABLED = - unreleasedFlag(2503, "output_switcher_show_api_enabled", teamfood = true) + releasedFlag(2503, "output_switcher_show_api_enabled", teamfood = true) // 2700 - unfold transitions // TODO(b/265764985): Tracking Bug diff --git a/packages/SystemUI/src/com/android/systemui/flags/RestartDozeListener.kt b/packages/SystemUI/src/com/android/systemui/flags/RestartDozeListener.kt new file mode 100644 index 000000000000..bd74f4e5daab --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/flags/RestartDozeListener.kt @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.flags + +import android.os.PowerManager +import android.util.Log +import com.android.internal.annotations.VisibleForTesting +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.util.settings.SecureSettings +import com.android.systemui.util.time.SystemClock +import javax.inject.Inject + +@SysUISingleton +class RestartDozeListener +@Inject +constructor( + private val settings: SecureSettings, + private val statusBarStateController: StatusBarStateController, + private val powerManager: PowerManager, + private val systemClock: SystemClock, +) { + + companion object { + @VisibleForTesting val RESTART_NAP_KEY = "restart_nap_after_start" + } + + private var inited = false + + val listener = + object : StatusBarStateController.StateListener { + override fun onDreamingChanged(isDreaming: Boolean) { + settings.putBool(RESTART_NAP_KEY, isDreaming) + } + } + + fun init() { + if (inited) { + return + } + inited = true + + statusBarStateController.addCallback(listener) + } + + fun destroy() { + statusBarStateController.removeCallback(listener) + } + + fun maybeRestartSleep() { + if (settings.getBool(RESTART_NAP_KEY, false)) { + Log.d("RestartDozeListener", "Restarting sleep state") + powerManager.wakeUp(systemClock.uptimeMillis()) + powerManager.goToSleep(systemClock.uptimeMillis()) + settings.putBool(RESTART_NAP_KEY, false) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt index e225b10d4e52..7acd3f3447dd 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt @@ -62,11 +62,10 @@ class ServerFlagReaderImpl @Inject constructor( return } - for ((listener, flags) in listeners) { propLoop@ for (propName in properties.keyset) { for (flag in flags) { - if (propName == getServerOverrideName(flag.id) || propName == flag.name) { + if (propName == flag.name) { listener.onChange(flag) break@propLoop } @@ -103,10 +102,6 @@ class ServerFlagReaderImpl @Inject constructor( } listeners.add(Pair(listener, flags)) } - - private fun getServerOverrideName(flagId: Int): String { - return "flag_override_$flagId" - } } @Module diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt new file mode 100644 index 000000000000..e9b8908214fc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.android.systemui.keyboard + +import dagger.Module + +@Module abstract class KeyboardModule diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt new file mode 100644 index 000000000000..b0f9c4edb073 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.android.systemui.keyboard + +import com.android.systemui.CoreStartable +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags +import javax.inject.Inject + +/** A [CoreStartable] that launches components interested in physical keyboard interaction. */ +@SysUISingleton +class PhysicalKeyboardCoreStartable +@Inject +constructor( + private val featureFlags: FeatureFlags, +) : CoreStartable { + override fun start() { + if (featureFlags.isEnabled(Flags.KEYBOARD_BACKLIGHT_INDICATOR)) { + // TODO(b/268645743) start listening for keyboard backlight brightness + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index 228320b107cd..f964cb39a8d4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -933,7 +933,7 @@ class KeyguardUnlockAnimationController @Inject constructor( } // The smartspace is not visible if the bouncer is showing, so don't shared element it. - if (keyguardStateController.isBouncerShowing) { + if (keyguardStateController.isPrimaryBouncerShowing) { return false } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 09eaf756ec6c..6db1f8959e8a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1148,12 +1148,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private final KeyguardStateController.Callback mKeyguardStateControllerCallback = new KeyguardStateController.Callback() { @Override - public void onBouncerShowingChanged() { + public void onPrimaryBouncerShowingChanged() { synchronized (KeyguardViewMediator.this) { - if (mKeyguardStateController.isBouncerShowing()) { + if (mKeyguardStateController.isPrimaryBouncerShowing()) { mPendingPinLock = false; } - adjustStatusBarLocked(mKeyguardStateController.isBouncerShowing(), false); + adjustStatusBarLocked(mKeyguardStateController.isPrimaryBouncerShowing(), false); } } }; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt index 5a9f7752277e..c9f645dddd8d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.data.quickaffordance import android.app.StatusBarManager +import android.app.admin.DevicePolicyManager import android.content.Context import android.content.pm.PackageManager import com.android.systemui.R @@ -27,10 +28,14 @@ import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.settings.UserTracker import dagger.Lazy import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.withContext @SysUISingleton class CameraQuickAffordanceConfig @@ -39,6 +44,9 @@ constructor( @Application private val context: Context, private val packageManager: PackageManager, private val cameraGestureHelper: Lazy<CameraGestureHelper>, + private val userTracker: UserTracker, + private val devicePolicyManager: DevicePolicyManager, + @Background private val backgroundDispatcher: CoroutineDispatcher, ) : KeyguardQuickAffordanceConfig { override val key: String @@ -79,7 +87,12 @@ constructor( return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } - private fun isLaunchable(): Boolean { - return packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) + private suspend fun isLaunchable(): Boolean { + return packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) && + withContext(backgroundDispatcher) { + !devicePolicyManager.getCameraDisabled(null, userTracker.userId) && + devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId) and + DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA == 0 + } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfig.kt index d9ec3b1c2f87..6f821a2b5228 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfig.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.data.quickaffordance import android.app.StatusBarManager +import android.app.admin.DevicePolicyManager import android.content.Context import android.content.Intent import com.android.systemui.ActivityIntentHelper @@ -29,10 +30,13 @@ import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.settings.UserTracker import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.withContext @SysUISingleton class VideoCameraQuickAffordanceConfig @@ -42,6 +46,8 @@ constructor( private val cameraIntents: CameraIntentsWrapper, private val activityIntentHelper: ActivityIntentHelper, private val userTracker: UserTracker, + private val devicePolicyManager: DevicePolicyManager, + @Background private val backgroundDispatcher: CoroutineDispatcher, ) : KeyguardQuickAffordanceConfig { private val intent: Intent by lazy { @@ -63,8 +69,8 @@ constructor( get() = R.drawable.ic_videocam override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> - get() = - flowOf( + get() = flow { + emit( if (isLaunchable()) { KeyguardQuickAffordanceConfig.LockScreenState.Visible( icon = @@ -77,6 +83,7 @@ constructor( KeyguardQuickAffordanceConfig.LockScreenState.Hidden } ) + } override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState { return if (isLaunchable()) { @@ -95,11 +102,14 @@ constructor( ) } - private fun isLaunchable(): Boolean { + private suspend fun isLaunchable(): Boolean { return activityIntentHelper.getTargetActivityInfo( intent, userTracker.userId, true, - ) != null + ) != null && + withContext(backgroundDispatcher) { + !devicePolicyManager.getCameraDisabled(null, userTracker.userId) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt index 091acadea632..4331fe66a0dc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt @@ -68,8 +68,8 @@ interface KeyguardBouncerRepository { val resourceUpdateRequests: StateFlow<Boolean> val bouncerPromptReason: Int val bouncerErrorMessage: CharSequence? - val isAlternateBouncerVisible: StateFlow<Boolean> - val isAlternateBouncerUIAvailable: StateFlow<Boolean> + val alternateBouncerVisible: StateFlow<Boolean> + val alternateBouncerUIAvailable: StateFlow<Boolean> var lastAlternateBouncerVisibleTime: Long fun setPrimaryScrimmed(isScrimmed: Boolean) @@ -159,12 +159,12 @@ constructor( get() = viewMediatorCallback.consumeCustomMessage() /** Values associated with the AlternateBouncer */ - private val _isAlternateBouncerVisible = MutableStateFlow(false) - override val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow() + private val _alternateBouncerVisible = MutableStateFlow(false) + override val alternateBouncerVisible = _alternateBouncerVisible.asStateFlow() override var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE - private val _isAlternateBouncerUIAvailable = MutableStateFlow(false) - override val isAlternateBouncerUIAvailable: StateFlow<Boolean> = - _isAlternateBouncerUIAvailable.asStateFlow() + private val _alternateBouncerUIAvailable = MutableStateFlow(false) + override val alternateBouncerUIAvailable: StateFlow<Boolean> = + _alternateBouncerUIAvailable.asStateFlow() init { setUpLogging() @@ -179,16 +179,16 @@ constructor( } override fun setAlternateVisible(isVisible: Boolean) { - if (isVisible && !_isAlternateBouncerVisible.value) { + if (isVisible && !_alternateBouncerVisible.value) { lastAlternateBouncerVisibleTime = clock.uptimeMillis() } else if (!isVisible) { lastAlternateBouncerVisibleTime = NOT_VISIBLE } - _isAlternateBouncerVisible.value = isVisible + _alternateBouncerVisible.value = isVisible } override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) { - _isAlternateBouncerUIAvailable.value = isAvailable + _alternateBouncerUIAvailable.value = isAvailable } override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) { @@ -290,7 +290,7 @@ constructor( resourceUpdateRequests .logDiffsForTable(buffer, "", "ResourceUpdateRequests", false) .launchIn(applicationScope) - isAlternateBouncerUIAvailable + alternateBouncerUIAvailable .logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false) .launchIn(applicationScope) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt index db955622f707..a3b3d0fd0681 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt @@ -86,9 +86,6 @@ interface KeyguardRepository { /** Observable for the signal that keyguard is about to go away. */ val isKeyguardGoingAway: Flow<Boolean> - /** Observable for whether the bouncer is showing. */ - val isBouncerShowing: Flow<Boolean> - /** Is the always-on display available to be used? */ val isAodAvailable: Flow<Boolean> @@ -304,29 +301,6 @@ constructor( awaitClose { keyguardStateController.removeCallback(callback) } } - override val isBouncerShowing: Flow<Boolean> = conflatedCallbackFlow { - val callback = - object : KeyguardStateController.Callback { - override fun onBouncerShowingChanged() { - trySendWithFailureLogging( - keyguardStateController.isBouncerShowing, - TAG, - "updated isBouncerShowing" - ) - } - } - - keyguardStateController.addCallback(callback) - // Adding the callback does not send an initial update. - trySendWithFailureLogging( - keyguardStateController.isBouncerShowing, - TAG, - "initial isBouncerShowing" - ) - - awaitClose { keyguardStateController.removeCallback(callback) } - } - override val isDozing: Flow<Boolean> = conflatedCallbackFlow { val callback = diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/backup/KeyguardQuickAffordanceBackupHelper.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/backup/KeyguardQuickAffordanceBackupHelper.kt index 0e865cee0b76..fa6efa504623 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/backup/KeyguardQuickAffordanceBackupHelper.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/backup/KeyguardQuickAffordanceBackupHelper.kt @@ -29,16 +29,9 @@ class KeyguardQuickAffordanceBackupHelper( ) : SharedPreferencesBackupHelper( context, - if (UserFileManagerImpl.isPrimaryUser(userId)) { - KeyguardQuickAffordanceSelectionManager.FILE_NAME - } else { - UserFileManagerImpl.secondaryUserFile( - context = context, - fileName = KeyguardQuickAffordanceSelectionManager.FILE_NAME, - directoryName = UserFileManagerImpl.SHARED_PREFS, - userId = userId, - ) - .also { UserFileManagerImpl.ensureParentDirExists(it) } - .toString() - } + UserFileManagerImpl.createFile( + userId = userId, + fileName = KeyguardQuickAffordanceSelectionManager.FILE_NAME, + ) + .getPath() ) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt index 6452e0e094ce..dfe10381720c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt @@ -44,7 +44,7 @@ constructor( var legacyAlternateBouncer: LegacyAlternateBouncer? = null var legacyAlternateBouncerVisibleTime: Long = NOT_VISIBLE - val isVisible: Flow<Boolean> = bouncerRepository.isAlternateBouncerVisible + val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible /** * Sets the correct bouncer states to show the alternate bouncer if it can show. @@ -86,7 +86,7 @@ constructor( fun isVisibleState(): Boolean { return if (isModernAlternateBouncerEnabled) { - bouncerRepository.isAlternateBouncerVisible.value + bouncerRepository.alternateBouncerVisible.value } else { legacyAlternateBouncer?.isShowingAlternateBouncer ?: false } @@ -98,7 +98,7 @@ constructor( fun canShowAlternateBouncerForFingerprint(): Boolean { return if (isModernAlternateBouncerEnabled) { - bouncerRepository.isAlternateBouncerUIAvailable.value && + bouncerRepository.alternateBouncerUIAvailable.value && biometricSettingsRepository.isFingerprintEnrolled.value && biometricSettingsRepository.isStrongBiometricAllowed.value && biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value && diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt new file mode 100644 index 000000000000..310f44da6e66 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.keyguard.domain.interactor + +import android.animation.ValueAnimator +import com.android.systemui.animation.Interpolators +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionInfo +import com.android.systemui.keyguard.shared.model.WakefulnessState +import com.android.systemui.util.kotlin.sample +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch + +@SysUISingleton +class FromAlternateBouncerTransitionInteractor +@Inject +constructor( + @Application private val scope: CoroutineScope, + private val keyguardInteractor: KeyguardInteractor, + private val keyguardTransitionRepository: KeyguardTransitionRepository, + private val keyguardTransitionInteractor: KeyguardTransitionInteractor, +) : TransitionInteractor(FromAlternateBouncerTransitionInteractor::class.simpleName!!) { + + override fun start() { + listenForAlternateBouncerToGone() + listenForAlternateBouncerToLockscreenAodOrDozing() + listenForAlternateBouncerToPrimaryBouncer() + } + + private fun listenForAlternateBouncerToLockscreenAodOrDozing() { + scope.launch { + keyguardInteractor.alternateBouncerShowing + // Add a slight delay, as alternateBouncer and primaryBouncer showing event changes + // will arrive with a small gap in time. This prevents a transition to LOCKSCREEN + // happening prematurely. + .onEach { delay(50) } + .sample( + combine( + keyguardInteractor.primaryBouncerShowing, + keyguardTransitionInteractor.startedKeyguardTransitionStep, + keyguardInteractor.wakefulnessModel, + keyguardInteractor.isAodAvailable, + ::toQuad + ), + ::toQuint + ) + .collect { + ( + isAlternateBouncerShowing, + isPrimaryBouncerShowing, + lastStartedTransitionStep, + wakefulnessState, + isAodAvailable + ) -> + if ( + !isAlternateBouncerShowing && + !isPrimaryBouncerShowing && + lastStartedTransitionStep.to == KeyguardState.ALTERNATE_BOUNCER + ) { + val to = + if ( + wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP || + wakefulnessState.state == WakefulnessState.ASLEEP + ) { + if (isAodAvailable) { + KeyguardState.AOD + } else { + KeyguardState.DOZING + } + } else { + KeyguardState.LOCKSCREEN + } + keyguardTransitionRepository.startTransition( + TransitionInfo( + ownerName = name, + from = KeyguardState.ALTERNATE_BOUNCER, + to = to, + animator = getAnimator(), + ) + ) + } + } + } + } + + private fun listenForAlternateBouncerToGone() { + scope.launch { + keyguardInteractor.isKeyguardGoingAway + .sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair) + .collect { (isKeyguardGoingAway, keyguardState) -> + if (isKeyguardGoingAway && keyguardState == KeyguardState.ALTERNATE_BOUNCER) { + keyguardTransitionRepository.startTransition( + TransitionInfo( + ownerName = name, + from = KeyguardState.ALTERNATE_BOUNCER, + to = KeyguardState.GONE, + animator = getAnimator(), + ) + ) + } + } + } + } + + private fun listenForAlternateBouncerToPrimaryBouncer() { + scope.launch { + keyguardInteractor.primaryBouncerShowing + .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair) + .collect { (isPrimaryBouncerShowing, startedKeyguardState) -> + if ( + isPrimaryBouncerShowing && + startedKeyguardState.to == KeyguardState.ALTERNATE_BOUNCER + ) { + keyguardTransitionRepository.startTransition( + TransitionInfo( + ownerName = name, + from = KeyguardState.ALTERNATE_BOUNCER, + to = KeyguardState.PRIMARY_BOUNCER, + animator = getAnimator(), + ) + ) + } + } + } + } + + private fun getAnimator(): ValueAnimator { + return ValueAnimator().apply { + interpolator = Interpolators.LINEAR + duration = TRANSITION_DURATION_MS + } + } + + companion object { + private const val TRANSITION_DURATION_MS = 300L + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt index 5674e2a15271..d01f48970c97 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt @@ -33,7 +33,6 @@ import javax.inject.Inject import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch @@ -53,9 +52,10 @@ constructor( listenForLockscreenToOccluded() listenForLockscreenToCamera() listenForLockscreenToAodOrDozing() - listenForLockscreenToBouncer() + listenForLockscreenToPrimaryBouncer() listenForLockscreenToDreaming() - listenForLockscreenToBouncerDragging() + listenForLockscreenToPrimaryBouncerDragging() + listenForLockscreenToAlternateBouncer() } private fun listenForLockscreenToDreaming() { @@ -78,9 +78,9 @@ constructor( } } - private fun listenForLockscreenToBouncer() { + private fun listenForLockscreenToPrimaryBouncer() { scope.launch { - keyguardInteractor.isBouncerShowing + keyguardInteractor.primaryBouncerShowing .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair) .collect { pair -> val (isBouncerShowing, lastStartedTransitionStep) = pair @@ -91,7 +91,30 @@ constructor( TransitionInfo( ownerName = name, from = KeyguardState.LOCKSCREEN, - to = KeyguardState.BOUNCER, + to = KeyguardState.PRIMARY_BOUNCER, + animator = getAnimator(), + ) + ) + } + } + } + } + + private fun listenForLockscreenToAlternateBouncer() { + scope.launch { + keyguardInteractor.alternateBouncerShowing + .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair) + .collect { pair -> + val (isAlternateBouncerShowing, lastStartedTransitionStep) = pair + if ( + isAlternateBouncerShowing && + lastStartedTransitionStep.to == KeyguardState.LOCKSCREEN + ) { + keyguardTransitionRepository.startTransition( + TransitionInfo( + ownerName = name, + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.ALTERNATE_BOUNCER, animator = getAnimator(), ) ) @@ -101,7 +124,7 @@ constructor( } /* Starts transitions when manually dragging up the bouncer from the lockscreen. */ - private fun listenForLockscreenToBouncerDragging() { + private fun listenForLockscreenToPrimaryBouncerDragging() { var transitionId: UUID? = null scope.launch { shadeRepository.shadeModel @@ -144,7 +167,7 @@ constructor( keyguardTransitionRepository.startTransition( TransitionInfo( ownerName = name, - from = KeyguardState.BOUNCER, + from = KeyguardState.PRIMARY_BOUNCER, to = KeyguardState.LOCKSCREEN, animator = getAnimator(0.milliseconds) ) @@ -163,7 +186,7 @@ constructor( TransitionInfo( ownerName = name, from = KeyguardState.LOCKSCREEN, - to = KeyguardState.BOUNCER, + to = KeyguardState.PRIMARY_BOUNCER, animator = null, ) ) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt index 0e9c44703205..b59b413d7a40 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt @@ -24,62 +24,63 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionInfo import com.android.systemui.keyguard.shared.model.WakefulnessState -import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.util.kotlin.sample -import java.util.UUID import javax.inject.Inject import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch @SysUISingleton -class FromBouncerTransitionInteractor +class FromPrimaryBouncerTransitionInteractor @Inject constructor( @Application private val scope: CoroutineScope, private val keyguardInteractor: KeyguardInteractor, - private val shadeRepository: ShadeRepository, private val keyguardTransitionRepository: KeyguardTransitionRepository, private val keyguardTransitionInteractor: KeyguardTransitionInteractor -) : TransitionInteractor(FromBouncerTransitionInteractor::class.simpleName!!) { - - private var transitionId: UUID? = null +) : TransitionInteractor(FromPrimaryBouncerTransitionInteractor::class.simpleName!!) { override fun start() { - listenForBouncerToGone() - listenForBouncerToLockscreenOrAod() + listenForPrimaryBouncerToGone() + listenForPrimaryBouncerToLockscreenAodOrDozing() } - private fun listenForBouncerToLockscreenOrAod() { + private fun listenForPrimaryBouncerToLockscreenAodOrDozing() { scope.launch { - keyguardInteractor.isBouncerShowing + keyguardInteractor.primaryBouncerShowing .sample( combine( keyguardInteractor.wakefulnessModel, keyguardTransitionInteractor.startedKeyguardTransitionStep, - ::Pair + keyguardInteractor.isAodAvailable, + ::toTriple ), - ::toTriple + ::toQuad ) - .collect { triple -> - val (isBouncerShowing, wakefulnessState, lastStartedTransitionStep) = triple + .collect { + (isBouncerShowing, wakefulnessState, lastStartedTransitionStep, isAodAvailable) + -> if ( - !isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.BOUNCER + !isBouncerShowing && + lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER ) { val to = if ( wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP || wakefulnessState.state == WakefulnessState.ASLEEP ) { - KeyguardState.AOD + if (isAodAvailable) { + KeyguardState.AOD + } else { + KeyguardState.DOZING + } } else { KeyguardState.LOCKSCREEN } keyguardTransitionRepository.startTransition( TransitionInfo( ownerName = name, - from = KeyguardState.BOUNCER, + from = KeyguardState.PRIMARY_BOUNCER, to = to, animator = getAnimator(), ) @@ -89,17 +90,17 @@ constructor( } } - private fun listenForBouncerToGone() { + private fun listenForPrimaryBouncerToGone() { scope.launch { keyguardInteractor.isKeyguardGoingAway - .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) }) + .sample(keyguardTransitionInteractor.finishedKeyguardState) { a, b -> Pair(a, b) } .collect { pair -> val (isKeyguardGoingAway, keyguardState) = pair - if (isKeyguardGoingAway && keyguardState == KeyguardState.BOUNCER) { + if (isKeyguardGoingAway && keyguardState == KeyguardState.PRIMARY_BOUNCER) { keyguardTransitionRepository.startTransition( TransitionInfo( ownerName = name, - from = KeyguardState.BOUNCER, + from = KeyguardState.PRIMARY_BOUNCER, to = KeyguardState.GONE, animator = getAnimator(), ) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt index 7e86a5d4d02d..d25aff0add86 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt @@ -24,6 +24,7 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockModel import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel @@ -56,6 +57,7 @@ constructor( private val repository: KeyguardRepository, private val commandQueue: CommandQueue, featureFlags: FeatureFlags, + bouncerRepository: KeyguardBouncerRepository, ) { /** * The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at @@ -121,8 +123,10 @@ constructor( val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded /** Whether the keyguard is going away. */ val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway - /** Whether the bouncer is showing or not. */ - val isBouncerShowing: Flow<Boolean> = repository.isBouncerShowing + /** Whether the primary bouncer is showing or not. */ + val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerVisible + /** Whether the alternate bouncer is showing or not. */ + val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible /** The device wake/sleep state */ val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness /** Observable for the [StatusBarState] */ @@ -142,12 +146,12 @@ constructor( if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) { combine( isKeyguardVisible, - repository.isBouncerShowing, + bouncerRepository.primaryBouncerVisible, onCameraLaunchDetected, - ) { isKeyguardVisible, isBouncerShowing, cameraLaunchEvent -> + ) { isKeyguardVisible, isPrimaryBouncerShowing, cameraLaunchEvent -> when { isKeyguardVisible -> false - isBouncerShowing -> false + isPrimaryBouncerShowing -> false else -> cameraLaunchEvent == CameraLaunchSourceModel.POWER_DOUBLE_TAP } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt index d4e2349907bc..51b02779a89f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt @@ -22,7 +22,6 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.plugins.log.LogLevel.VERBOSE import javax.inject.Inject import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch private val TAG = KeyguardTransitionAuditLogger::class.simpleName!! @@ -46,8 +45,14 @@ constructor( } scope.launch { - keyguardInteractor.isBouncerShowing.collect { - logger.log(TAG, VERBOSE, "Bouncer showing", it) + keyguardInteractor.primaryBouncerShowing.collect { + logger.log(TAG, VERBOSE, "Primary bouncer showing", it) + } + } + + scope.launch { + keyguardInteractor.alternateBouncerShowing.collect { + logger.log(TAG, VERBOSE, "Alternate bouncer showing", it) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt index fbed446b7d9a..efc1bd0fff04 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt @@ -37,13 +37,14 @@ constructor( // exhaustive val ret = when (it) { - is FromBouncerTransitionInteractor -> Log.d(TAG, "Started $it") + is FromPrimaryBouncerTransitionInteractor -> Log.d(TAG, "Started $it") is FromAodTransitionInteractor -> Log.d(TAG, "Started $it") is FromGoneTransitionInteractor -> Log.d(TAG, "Started $it") is FromLockscreenTransitionInteractor -> Log.d(TAG, "Started $it") is FromDreamingTransitionInteractor -> Log.d(TAG, "Started $it") is FromOccludedTransitionInteractor -> Log.d(TAG, "Started $it") is FromDozingTransitionInteractor -> Log.d(TAG, "Started $it") + is FromAlternateBouncerTransitionInteractor -> Log.d(TAG, "Started $it") } it.start() } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt index 84bcdf9f645f..1b7da5b65a03 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt @@ -21,13 +21,12 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState.AOD -import com.android.systemui.keyguard.shared.model.KeyguardState.BOUNCER import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED +import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER import com.android.systemui.keyguard.shared.model.TransitionState -import com.android.systemui.keyguard.shared.model.TransitionState.STARTED import com.android.systemui.keyguard.shared.model.TransitionStep import javax.inject.Inject import kotlinx.coroutines.flow.Flow @@ -63,9 +62,9 @@ constructor( /** LOCKSCREEN->AOD transition information. */ val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD) - /** LOCKSCREEN->BOUNCER transition information. */ - val lockscreenToBouncerTransition: Flow<TransitionStep> = - repository.transition(LOCKSCREEN, BOUNCER) + /** LOCKSCREEN->PRIMARY_BOUNCER transition information. */ + val mLockscreenToPrimaryBouncerTransition: Flow<TransitionStep> = + repository.transition(LOCKSCREEN, PRIMARY_BOUNCER) /** LOCKSCREEN->DREAMING transition information. */ val lockscreenToDreamingTransition: Flow<TransitionStep> = diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt index a59c407182e2..833eda77108d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt @@ -86,7 +86,8 @@ constructor( KeyguardState.DOZING -> false KeyguardState.AOD -> false KeyguardState.DREAMING -> true - KeyguardState.BOUNCER -> true + KeyguardState.ALTERNATE_BOUNCER -> true + KeyguardState.PRIMARY_BOUNCER -> true KeyguardState.LOCKSCREEN -> true KeyguardState.GONE -> true KeyguardState.OCCLUDED -> true diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt index 96bf815b28d8..6610983a6ff6 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt @@ -164,7 +164,7 @@ constructor( } else { DejankUtils.postAfterTraversal(showRunnable) } - keyguardStateController.notifyBouncerShowing(true) + keyguardStateController.notifyPrimaryBouncerShowing(true) primaryBouncerCallbackInteractor.dispatchStartingToShow() Trace.endSection() } @@ -181,7 +181,7 @@ constructor( } falsingCollector.onBouncerHidden() - keyguardStateController.notifyBouncerShowing(false /* showing */) + keyguardStateController.notifyPrimaryBouncerShowing(false /* showing */) cancelShowRunnable() repository.setPrimaryShowingSoon(false) repository.setPrimaryVisible(false) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt index 81fa2336d40d..d9690b7e3b38 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt @@ -32,7 +32,9 @@ abstract class StartKeyguardTransitionModule { @Binds @IntoSet - abstract fun fromBouncer(impl: FromBouncerTransitionInteractor): TransitionInteractor + abstract fun fromPrimaryBouncer( + impl: FromPrimaryBouncerTransitionInteractor + ): TransitionInteractor @Binds @IntoSet @@ -53,4 +55,10 @@ abstract class StartKeyguardTransitionModule { @Binds @IntoSet abstract fun fromDozing(impl: FromDozingTransitionInteractor): TransitionInteractor + + @Binds + @IntoSet + abstract fun fromAlternateBouncer( + impl: FromAlternateBouncerTransitionInteractor + ): TransitionInteractor } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt index 4d24c14501aa..e3e3527e851f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt @@ -30,7 +30,26 @@ sealed class TransitionInteractor(val name: String) { abstract fun start() + fun <A, B, C> toTriple(a: A, b: B, c: C) = Triple(a, b, c) + fun <A, B, C> toTriple(a: A, bc: Pair<B, C>) = Triple(a, bc.first, bc.second) fun <A, B, C> toTriple(ab: Pair<A, B>, c: C) = Triple(ab.first, ab.second, c) + + fun <A, B, C, D> toQuad(a: A, b: B, c: C, d: D) = Quad(a, b, c, d) + + fun <A, B, C, D> toQuad(a: A, bcd: Triple<B, C, D>) = Quad(a, bcd.first, bcd.second, bcd.third) + + fun <A, B, C, D, E> toQuint(a: A, bcde: Quad<B, C, D, E>) = + Quint(a, bcde.first, bcde.second, bcde.third, bcde.fourth) } + +data class Quad<A, B, C, D>(val first: A, val second: B, val third: C, val fourth: D) + +data class Quint<A, B, C, D, E>( + val first: A, + val second: B, + val third: C, + val fourth: D, + val fifth: E +) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt index c7579862a717..87b4321769b5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt @@ -42,10 +42,15 @@ enum class KeyguardState { */ AOD, /* - * The security screen prompt UI, containing PIN, Password, Pattern, and all FPS - * (Fingerprint Sensor) variations, for the user to verify their credentials + * The security screen prompt containing UI to prompt the user to use a biometric credential + * (ie: fingerprint). When supported, this may show before showing the primary bouncer. */ - BOUNCER, + ALTERNATE_BOUNCER, + /* + * The security screen prompt UI, containing PIN, Password, Pattern for the user to verify their + * credentials. + */ + PRIMARY_BOUNCER, /* * Device is actively displaying keyguard UI and is not in low-power mode. Device may be * unlocked if SWIPE security method is used, or if face lockscreen bypass is false. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt index 9f09d53c99f3..56f911f8b1da 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt @@ -22,11 +22,12 @@ import android.view.ViewGroup import android.window.OnBackAnimationCallback import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle -import com.android.internal.policy.SystemBarUtils -import com.android.keyguard.KeyguardHostViewController +import com.android.keyguard.KeyguardSecurityContainerController import com.android.keyguard.KeyguardSecurityModel +import com.android.keyguard.KeyguardSecurityView import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.dagger.KeyguardBouncerComponent +import com.android.settingslib.Utils import com.android.systemui.keyguard.data.BouncerViewDelegate import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel @@ -44,52 +45,54 @@ object KeyguardBouncerViewBinder { viewModel: KeyguardBouncerViewModel, componentFactory: KeyguardBouncerComponent.Factory ) { - // Builds the KeyguardHostViewController from bouncer view group. - val hostViewController: KeyguardHostViewController = - componentFactory.create(view).keyguardHostViewController - hostViewController.init() + // Builds the KeyguardSecurityContainerController from bouncer view group. + val securityContainerController: KeyguardSecurityContainerController = + componentFactory.create(view).securityContainerController + securityContainerController.init() val delegate = object : BouncerViewDelegate { override fun isFullScreenBouncer(): Boolean { - val mode = hostViewController.currentSecurityMode + val mode = securityContainerController.currentSecurityMode return mode == KeyguardSecurityModel.SecurityMode.SimPin || mode == KeyguardSecurityModel.SecurityMode.SimPuk } override fun getBackCallback(): OnBackAnimationCallback { - return hostViewController.backCallback + return securityContainerController.backCallback } override fun shouldDismissOnMenuPressed(): Boolean { - return hostViewController.shouldEnableMenuKey() + return securityContainerController.shouldEnableMenuKey() } override fun interceptMediaKey(event: KeyEvent?): Boolean { - return hostViewController.interceptMediaKey(event) + return securityContainerController.interceptMediaKey(event) } override fun dispatchBackKeyEventPreIme(): Boolean { - return hostViewController.dispatchBackKeyEventPreIme() + return securityContainerController.dispatchBackKeyEventPreIme() } override fun showNextSecurityScreenOrFinish(): Boolean { - return hostViewController.dismiss(KeyguardUpdateMonitor.getCurrentUser()) + return securityContainerController.dismiss( + KeyguardUpdateMonitor.getCurrentUser() + ) } override fun resume() { - hostViewController.showPrimarySecurityScreen() - hostViewController.onResume() + securityContainerController.showPrimarySecurityScreen(/* isTurningOff= */ false) + securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON) } override fun setDismissAction( onDismissAction: ActivityStarter.OnDismissAction?, cancelAction: Runnable? ) { - hostViewController.setOnDismissAction(onDismissAction, cancelAction) + securityContainerController.setOnDismissAction(onDismissAction, cancelAction) } override fun willDismissWithActions(): Boolean { - return hostViewController.hasDismissActions() + return securityContainerController.hasDismissActions() } } view.repeatWhenAttached { @@ -98,39 +101,46 @@ object KeyguardBouncerViewBinder { viewModel.setBouncerViewDelegate(delegate) launch { viewModel.show.collect { - hostViewController.showPromptReason(it.promptReason) + // Reset Security Container entirely. + securityContainerController.reinflateViewFlipper() + securityContainerController.showPromptReason(it.promptReason) it.errorMessage?.let { errorMessage -> - hostViewController.showErrorMessage(errorMessage) + securityContainerController.showMessage( + errorMessage, + Utils.getColorError(view.context) + ) } - hostViewController.showPrimarySecurityScreen() - hostViewController.appear( - SystemBarUtils.getStatusBarHeight(view.context) + securityContainerController.showPrimarySecurityScreen( + /* turningOff= */ false ) - hostViewController.onResume() + securityContainerController.appear() + securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON) } } launch { viewModel.hide.collect { - hostViewController.cancelDismissAction() - hostViewController.cleanUp() - hostViewController.resetSecurityContainer() + securityContainerController.cancelDismissAction() + securityContainerController.onPause() + securityContainerController.reset() } } launch { - viewModel.startingToHide.collect { hostViewController.onStartingToHide() } + viewModel.startingToHide.collect { + securityContainerController.onStartingToHide() + } } launch { viewModel.startDisappearAnimation.collect { - hostViewController.startDisappearAnimation(it) + securityContainerController.startDisappearAnimation(it) } } launch { viewModel.bouncerExpansionAmount.collect { expansion -> - hostViewController.setExpansion(expansion) + securityContainerController.setExpansion(expansion) } } @@ -138,10 +148,8 @@ object KeyguardBouncerViewBinder { viewModel.bouncerExpansionAmount .filter { it == EXPANSION_VISIBLE } .collect { - hostViewController.onResume() - view.announceForAccessibility( - hostViewController.accessibilityTitleForCurrentMode - ) + securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON) + view.announceForAccessibility(securityContainerController.title) } } @@ -149,48 +157,42 @@ object KeyguardBouncerViewBinder { viewModel.isBouncerVisible.collect { isVisible -> val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE view.visibility = visibility - hostViewController.onBouncerVisibilityChanged(visibility) + securityContainerController.onBouncerVisibilityChanged(visibility) } } launch { viewModel.isInteractable.collect { isInteractable -> - hostViewController.setInteractable(isInteractable) + securityContainerController.setInteractable(isInteractable) } } launch { - viewModel.isBouncerVisible - .filter { !it } - .collect { - // Remove existing input for security reasons. - hostViewController.resetSecurityContainer() - } - } - - launch { viewModel.keyguardPosition.collect { position -> - hostViewController.updateKeyguardPosition(position) + securityContainerController.updateKeyguardPosition(position) } } launch { viewModel.updateResources.collect { - hostViewController.updateResources() + securityContainerController.updateResources() viewModel.notifyUpdateResources() } } launch { viewModel.bouncerShowMessage.collect { - hostViewController.showMessage(it.message, it.colorStateList) + securityContainerController.showMessage(it.message, it.colorStateList) viewModel.onMessageShown() } } launch { viewModel.keyguardAuthenticated.collect { - hostViewController.finish(it, KeyguardUpdateMonitor.getCurrentUser()) + securityContainerController.finish( + it, + KeyguardUpdateMonitor.getCurrentUser() + ) viewModel.notifyKeyguardAuthenticated() } } @@ -204,7 +206,7 @@ object KeyguardBouncerViewBinder { launch { viewModel.screenTurnedOff.collect { if (view.visibility == View.VISIBLE) { - hostViewController.onPause() + securityContainerController.onPause() } } } 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 index 403576cd1ec0..72b317c6274c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt @@ -170,7 +170,12 @@ constructor( } private fun setUpClock(parentView: ViewGroup) { - val clockChangeListener = ClockRegistry.ClockChangeListener { onClockChanged(parentView) } + val clockChangeListener = + object : ClockRegistry.ClockChangeListener { + override fun onCurrentClockChanged() { + onClockChanged(parentView) + } + } clockRegistry.registerClockChangeListener(clockChangeListener) disposables.add( DisposableHandle { clockRegistry.unregisterClockChangeListener(clockChangeListener) } diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index 41774800c527..5341cd53b2a5 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -265,16 +265,6 @@ public class LogModule { return factory.create("MediaCarouselCtlrLog", 20); } - /** - * Provides a {@link LogBuffer} for use in the status bar connectivity pipeline - */ - @Provides - @SysUISingleton - @StatusBarConnectivityLog - public static LogBuffer provideStatusBarConnectivityBuffer(LogBufferFactory factory) { - return factory.create("SbConnectivity", 64); - } - /** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */ @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt index 520edef7d109..f5558a240a70 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt @@ -1343,9 +1343,9 @@ class MediaDataManager( if (keyguardUpdateMonitor.isUserInLockdown(removed.userId)) { logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId) } else if (useMediaResumption && removed.resumeAction != null && removed.isLocalSession()) { - convertToResumePlayer(removed) + convertToResumePlayer(key, removed) } else if (mediaFlags.isRetainingPlayersEnabled()) { - handlePossibleRemoval(removed, notificationRemoved = true) + handlePossibleRemoval(key, removed, notificationRemoved = true) } else { notifyMediaDataRemoved(key) logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId) @@ -1359,7 +1359,7 @@ class MediaDataManager( val entry = mediaEntries.remove(key) ?: return // Clear token since the session is no longer valid val updated = entry.copy(token = null) - handlePossibleRemoval(updated) + handlePossibleRemoval(key, updated) } /** @@ -1368,8 +1368,11 @@ class MediaDataManager( * if it was removed before becoming inactive. (Assumes that [removed] was removed from * [mediaEntries] before this function was called) */ - private fun handlePossibleRemoval(removed: MediaData, notificationRemoved: Boolean = false) { - val key = removed.notificationKey!! + private fun handlePossibleRemoval( + key: String, + removed: MediaData, + notificationRemoved: Boolean = false + ) { val hasSession = removed.token != null if (hasSession && removed.semanticActions != null) { // The app was using session actions, and the session is still valid: keep player @@ -1395,13 +1398,12 @@ class MediaDataManager( "($hasSession) gone for inactive player $key" ) } - convertToResumePlayer(removed) + convertToResumePlayer(key, removed) } } /** Set the given [MediaData] as a resume state player and notify listeners */ - private fun convertToResumePlayer(data: MediaData) { - val key = data.notificationKey!! + private fun convertToResumePlayer(key: String, data: MediaData) { if (DEBUG) Log.d(TAG, "Converting $key to resume") // Move to resume key (aka package name) if that key doesn't already exist. val resumeAction = data.resumeAction?.let { getResumeMediaAction(it) } diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java index 146633d0d9f0..95f14190537f 100644 --- a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java +++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java @@ -121,6 +121,6 @@ public abstract class PluginsModule { @Provides @Named(PLUGIN_PRIVILEGED) static List<String> providesPrivilegedPlugins(Context context) { - return Arrays.asList(context.getResources().getStringArray(R.array.config_pluginWhitelist)); + return Arrays.asList(context.getResources().getStringArray(R.array.config_pluginAllowlist)); } } diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt new file mode 100644 index 000000000000..62c99da5ed81 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qrcodescanner.dagger + +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.qs.tiles.QRCodeScannerTile +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface QRCodeScannerModule { + + /** + */ + @Binds + @IntoMap + @StringKey(QRCodeScannerTile.TILE_SPEC) + fun bindQRCodeScannerTile(qrCodeScannerTile: QRCodeScannerTile): QSTileImpl<*> +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java index 25a5c61a5f7d..27ae1710467b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java @@ -30,6 +30,7 @@ import com.android.systemui.qs.QSHost; import com.android.systemui.qs.QSTileHost; import com.android.systemui.qs.ReduceBrightColorsController; import com.android.systemui.qs.external.QSExternalModule; +import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.AutoTileManager; import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.policy.CastController; @@ -40,11 +41,14 @@ import com.android.systemui.statusbar.policy.SafetyController; import com.android.systemui.statusbar.policy.WalletController; import com.android.systemui.util.settings.SecureSettings; +import java.util.Map; + import javax.inject.Named; import dagger.Binds; import dagger.Module; import dagger.Provides; +import dagger.multibindings.Multibinds; /** * Module for QS dependencies @@ -53,6 +57,11 @@ import dagger.Provides; includes = {MediaModule.class, QSExternalModule.class, QSFlagsModule.class}) public interface QSModule { + /** A map of internal QS tiles. Ensures that this can be injected even if + * it is empty */ + @Multibinds + Map<String, QSTileImpl<?>> tileMap(); + @Provides @SysUISingleton static AutoTileManager provideAutoTileManager( diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java index dec6e7d93fa2..6b23f5d77145 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java @@ -27,76 +27,32 @@ import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.qs.QSTileView; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.external.CustomTile; -import com.android.systemui.qs.tiles.AirplaneModeTile; -import com.android.systemui.qs.tiles.AlarmTile; -import com.android.systemui.qs.tiles.BatterySaverTile; -import com.android.systemui.qs.tiles.BluetoothTile; -import com.android.systemui.qs.tiles.CameraToggleTile; -import com.android.systemui.qs.tiles.CastTile; -import com.android.systemui.qs.tiles.ColorCorrectionTile; -import com.android.systemui.qs.tiles.ColorInversionTile; -import com.android.systemui.qs.tiles.DataSaverTile; -import com.android.systemui.qs.tiles.DeviceControlsTile; -import com.android.systemui.qs.tiles.DndTile; -import com.android.systemui.qs.tiles.DreamTile; -import com.android.systemui.qs.tiles.FlashlightTile; -import com.android.systemui.qs.tiles.FontScalingTile; -import com.android.systemui.qs.tiles.HotspotTile; -import com.android.systemui.qs.tiles.InternetTile; -import com.android.systemui.qs.tiles.LocationTile; -import com.android.systemui.qs.tiles.MicrophoneToggleTile; -import com.android.systemui.qs.tiles.NfcTile; -import com.android.systemui.qs.tiles.NightDisplayTile; -import com.android.systemui.qs.tiles.OneHandedModeTile; -import com.android.systemui.qs.tiles.QRCodeScannerTile; -import com.android.systemui.qs.tiles.QuickAccessWalletTile; -import com.android.systemui.qs.tiles.ReduceBrightColorsTile; -import com.android.systemui.qs.tiles.RotationLockTile; -import com.android.systemui.qs.tiles.ScreenRecordTile; -import com.android.systemui.qs.tiles.UiModeNightTile; -import com.android.systemui.qs.tiles.WorkModeTile; import com.android.systemui.util.leak.GarbageMonitor; +import java.util.Map; + import javax.inject.Inject; import javax.inject.Provider; import dagger.Lazy; +/** + * A factory that creates Quick Settings tiles based on a tileSpec + * + * To create a new tile within SystemUI, the tile class should extend {@link QSTileImpl} and have + * a public static final TILE_SPEC field which serves as a unique key for this tile. (e.g. {@link + * com.android.systemui.qs.tiles.DreamTile#TILE_SPEC}) + * + * After, create or find an existing Module class to house the tile's binding method (e.g. {@link + * com.android.systemui.accessibility.AccessibilityModule}). If creating a new module, add your + * module to the SystemUI dagger graph by including it in an appropriate module. + */ @SysUISingleton public class QSFactoryImpl implements QSFactory { private static final String TAG = "QSFactory"; - private final Provider<InternetTile> mInternetTileProvider; - private final Provider<BluetoothTile> mBluetoothTileProvider; - private final Provider<DndTile> mDndTileProvider; - private final Provider<ColorCorrectionTile> mColorCorrectionTileProvider; - private final Provider<ColorInversionTile> mColorInversionTileProvider; - private final Provider<AirplaneModeTile> mAirplaneModeTileProvider; - private final Provider<WorkModeTile> mWorkModeTileProvider; - private final Provider<RotationLockTile> mRotationLockTileProvider; - private final Provider<FlashlightTile> mFlashlightTileProvider; - private final Provider<LocationTile> mLocationTileProvider; - private final Provider<CastTile> mCastTileProvider; - private final Provider<HotspotTile> mHotspotTileProvider; - private final Provider<BatterySaverTile> mBatterySaverTileProvider; - private final Provider<DataSaverTile> mDataSaverTileProvider; - private final Provider<NightDisplayTile> mNightDisplayTileProvider; - private final Provider<NfcTile> mNfcTileProvider; - private final Provider<GarbageMonitor.MemoryTile> mMemoryTileProvider; - private final Provider<UiModeNightTile> mUiModeNightTileProvider; - private final Provider<ScreenRecordTile> mScreenRecordTileProvider; - private final Provider<ReduceBrightColorsTile> mReduceBrightColorsTileProvider; - private final Provider<CameraToggleTile> mCameraToggleTileProvider; - private final Provider<MicrophoneToggleTile> mMicrophoneToggleTileProvider; - private final Provider<DeviceControlsTile> mDeviceControlsTileProvider; - private final Provider<AlarmTile> mAlarmTileProvider; - private final Provider<QuickAccessWalletTile> mQuickAccessWalletTileProvider; - private final Provider<QRCodeScannerTile> mQRCodeScannerTileProvider; - private final Provider<OneHandedModeTile> mOneHandedModeTileProvider; - private final Provider<DreamTile> mDreamTileProvider; - private final Provider<FontScalingTile> mFontScalingTileProvider; - + protected final Map<String, Provider<QSTileImpl<?>>> mTileMap; private final Lazy<QSHost> mQsHostLazy; private final Provider<CustomTile.Builder> mCustomTileBuilderProvider; @@ -104,67 +60,10 @@ public class QSFactoryImpl implements QSFactory { public QSFactoryImpl( Lazy<QSHost> qsHostLazy, Provider<CustomTile.Builder> customTileBuilderProvider, - Provider<InternetTile> internetTileProvider, - Provider<BluetoothTile> bluetoothTileProvider, - Provider<DndTile> dndTileProvider, - Provider<ColorInversionTile> colorInversionTileProvider, - Provider<AirplaneModeTile> airplaneModeTileProvider, - Provider<WorkModeTile> workModeTileProvider, - Provider<RotationLockTile> rotationLockTileProvider, - Provider<FlashlightTile> flashlightTileProvider, - Provider<LocationTile> locationTileProvider, - Provider<CastTile> castTileProvider, - Provider<HotspotTile> hotspotTileProvider, - Provider<BatterySaverTile> batterySaverTileProvider, - Provider<DataSaverTile> dataSaverTileProvider, - Provider<NightDisplayTile> nightDisplayTileProvider, - Provider<NfcTile> nfcTileProvider, - Provider<GarbageMonitor.MemoryTile> memoryTileProvider, - Provider<UiModeNightTile> uiModeNightTileProvider, - Provider<ScreenRecordTile> screenRecordTileProvider, - Provider<ReduceBrightColorsTile> reduceBrightColorsTileProvider, - Provider<CameraToggleTile> cameraToggleTileProvider, - Provider<MicrophoneToggleTile> microphoneToggleTileProvider, - Provider<DeviceControlsTile> deviceControlsTileProvider, - Provider<AlarmTile> alarmTileProvider, - Provider<QuickAccessWalletTile> quickAccessWalletTileProvider, - Provider<QRCodeScannerTile> qrCodeScannerTileProvider, - Provider<OneHandedModeTile> oneHandedModeTileProvider, - Provider<ColorCorrectionTile> colorCorrectionTileProvider, - Provider<DreamTile> dreamTileProvider, - Provider<FontScalingTile> fontScalingTileProvider) { + Map<String, Provider<QSTileImpl<?>>> tileMap) { mQsHostLazy = qsHostLazy; mCustomTileBuilderProvider = customTileBuilderProvider; - - mInternetTileProvider = internetTileProvider; - mBluetoothTileProvider = bluetoothTileProvider; - mDndTileProvider = dndTileProvider; - mColorInversionTileProvider = colorInversionTileProvider; - mAirplaneModeTileProvider = airplaneModeTileProvider; - mWorkModeTileProvider = workModeTileProvider; - mRotationLockTileProvider = rotationLockTileProvider; - mFlashlightTileProvider = flashlightTileProvider; - mLocationTileProvider = locationTileProvider; - mCastTileProvider = castTileProvider; - mHotspotTileProvider = hotspotTileProvider; - mBatterySaverTileProvider = batterySaverTileProvider; - mDataSaverTileProvider = dataSaverTileProvider; - mNightDisplayTileProvider = nightDisplayTileProvider; - mNfcTileProvider = nfcTileProvider; - mMemoryTileProvider = memoryTileProvider; - mUiModeNightTileProvider = uiModeNightTileProvider; - mScreenRecordTileProvider = screenRecordTileProvider; - mReduceBrightColorsTileProvider = reduceBrightColorsTileProvider; - mCameraToggleTileProvider = cameraToggleTileProvider; - mMicrophoneToggleTileProvider = microphoneToggleTileProvider; - mDeviceControlsTileProvider = deviceControlsTileProvider; - mAlarmTileProvider = alarmTileProvider; - mQuickAccessWalletTileProvider = quickAccessWalletTileProvider; - mQRCodeScannerTileProvider = qrCodeScannerTileProvider; - mOneHandedModeTileProvider = oneHandedModeTileProvider; - mColorCorrectionTileProvider = colorCorrectionTileProvider; - mDreamTileProvider = dreamTileProvider; - mFontScalingTileProvider = fontScalingTileProvider; + mTileMap = tileMap; } /** Creates a tile with a type based on {@code tileSpec} */ @@ -181,63 +80,10 @@ public class QSFactoryImpl implements QSFactory { @Nullable protected QSTileImpl createTileInternal(String tileSpec) { // Stock tiles. - switch (tileSpec) { - case "internet": - return mInternetTileProvider.get(); - case "bt": - return mBluetoothTileProvider.get(); - case "dnd": - return mDndTileProvider.get(); - case "inversion": - return mColorInversionTileProvider.get(); - case "airplane": - return mAirplaneModeTileProvider.get(); - case "work": - return mWorkModeTileProvider.get(); - case "rotation": - return mRotationLockTileProvider.get(); - case "flashlight": - return mFlashlightTileProvider.get(); - case "location": - return mLocationTileProvider.get(); - case "cast": - return mCastTileProvider.get(); - case "hotspot": - return mHotspotTileProvider.get(); - case "battery": - return mBatterySaverTileProvider.get(); - case "saver": - return mDataSaverTileProvider.get(); - case "night": - return mNightDisplayTileProvider.get(); - case "nfc": - return mNfcTileProvider.get(); - case "dark": - return mUiModeNightTileProvider.get(); - case "screenrecord": - return mScreenRecordTileProvider.get(); - case "reduce_brightness": - return mReduceBrightColorsTileProvider.get(); - case "cameratoggle": - return mCameraToggleTileProvider.get(); - case "mictoggle": - return mMicrophoneToggleTileProvider.get(); - case "controls": - return mDeviceControlsTileProvider.get(); - case "alarm": - return mAlarmTileProvider.get(); - case "wallet": - return mQuickAccessWalletTileProvider.get(); - case "qr_code_scanner": - return mQRCodeScannerTileProvider.get(); - case "onehanded": - return mOneHandedModeTileProvider.get(); - case "color_correction": - return mColorCorrectionTileProvider.get(); - case "dream": - return mDreamTileProvider.get(); - case "font_scaling": - return mFontScalingTileProvider.get(); + if (mTileMap.containsKey(tileSpec) + // We should not return a Garbage Monitory Tile if the build is not Debuggable + && (!tileSpec.equals(GarbageMonitor.MemoryTile.TILE_SPEC) || Build.IS_DEBUGGABLE)) { + return mTileMap.get(tileSpec).get(); } // Custom tiles @@ -246,13 +92,6 @@ public class QSFactoryImpl implements QSFactory { mCustomTileBuilderProvider.get(), tileSpec, mQsHostLazy.get().getUserContext()); } - // Debug tiles. - if (Build.IS_DEBUGGABLE) { - if (tileSpec.equals(GarbageMonitor.MemoryTile.TILE_SPEC)) { - return mMemoryTileProvider.get(); - } - } - // Broken tiles. Log.w(TAG, "No stock tile spec: " + tileSpec); return null; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 2cffe8951b56..49ba5086f64d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -712,6 +712,10 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy return context.getDrawable(mResId); } + public int getResId() { + return mResId; + } + @Override public boolean equals(Object o) { return o instanceof ResourceIcon && ((ResourceIcon) o).mResId == mResId; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index d0b04c93bba0..de1137e48074 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -440,12 +440,11 @@ open class QSTileViewImpl @JvmOverloads constructor( // State handling and description val stateDescription = StringBuilder() - val stateText = getStateText(state) + val arrayResId = SubtitleArrayMapping.getSubtitleId(state.spec) + val stateText = state.getStateText(arrayResId, resources) + state.secondaryLabel = state.getSecondaryLabel(stateText) if (!TextUtils.isEmpty(stateText)) { stateDescription.append(stateText) - if (TextUtils.isEmpty(state.secondaryLabel)) { - state.secondaryLabel = stateText - } } if (state.disabledByPolicy && state.state != Tile.STATE_UNAVAILABLE) { stateDescription.append(", ") @@ -591,16 +590,6 @@ open class QSTileViewImpl @JvmOverloads constructor( return resources.getStringArray(arrayResId)[Tile.STATE_UNAVAILABLE] } - private fun getStateText(state: QSTile.State): String { - return if (state.state == Tile.STATE_UNAVAILABLE || state is BooleanState) { - val arrayResId = SubtitleArrayMapping.getSubtitleId(state.spec) - val array = resources.getStringArray(arrayResId) - array[state.state] - } else { - "" - } - } - /* * The view should not be animated if it's not on screen and no part of it is visible. */ @@ -663,46 +652,6 @@ open class QSTileViewImpl @JvmOverloads constructor( ) } -@VisibleForTesting -internal object SubtitleArrayMapping { - private val subtitleIdsMap = mapOf<String?, Int>( - "internet" to R.array.tile_states_internet, - "wifi" to R.array.tile_states_wifi, - "cell" to R.array.tile_states_cell, - "battery" to R.array.tile_states_battery, - "dnd" to R.array.tile_states_dnd, - "flashlight" to R.array.tile_states_flashlight, - "rotation" to R.array.tile_states_rotation, - "bt" to R.array.tile_states_bt, - "airplane" to R.array.tile_states_airplane, - "location" to R.array.tile_states_location, - "hotspot" to R.array.tile_states_hotspot, - "inversion" to R.array.tile_states_inversion, - "saver" to R.array.tile_states_saver, - "dark" to R.array.tile_states_dark, - "work" to R.array.tile_states_work, - "cast" to R.array.tile_states_cast, - "night" to R.array.tile_states_night, - "screenrecord" to R.array.tile_states_screenrecord, - "reverse" to R.array.tile_states_reverse, - "reduce_brightness" to R.array.tile_states_reduce_brightness, - "cameratoggle" to R.array.tile_states_cameratoggle, - "mictoggle" to R.array.tile_states_mictoggle, - "controls" to R.array.tile_states_controls, - "wallet" to R.array.tile_states_wallet, - "qr_code_scanner" to R.array.tile_states_qr_code_scanner, - "alarm" to R.array.tile_states_alarm, - "onehanded" to R.array.tile_states_onehanded, - "color_correction" to R.array.tile_states_color_correction, - "dream" to R.array.tile_states_dream, - "font_scaling" to R.array.tile_states_font_scaling - ) - - fun getSubtitleId(spec: String?): Int { - return subtitleIdsMap.getOrDefault(spec, R.array.tile_states_default) - } -} - fun constrainSquishiness(squish: Float): Float { return 0.1f + squish * 0.9f } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt new file mode 100644 index 000000000000..f672e518f0b3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.qs.tileimpl + +import com.android.systemui.R + +/** Return the subtitle resource Id of the given tile. */ +object SubtitleArrayMapping { + private val subtitleIdsMap: HashMap<String, Int> = HashMap() + init { + subtitleIdsMap["internet"] = R.array.tile_states_internet + subtitleIdsMap["wifi"] = R.array.tile_states_wifi + subtitleIdsMap["cell"] = R.array.tile_states_cell + subtitleIdsMap["battery"] = R.array.tile_states_battery + subtitleIdsMap["dnd"] = R.array.tile_states_dnd + subtitleIdsMap["flashlight"] = R.array.tile_states_flashlight + subtitleIdsMap["rotation"] = R.array.tile_states_rotation + subtitleIdsMap["bt"] = R.array.tile_states_bt + subtitleIdsMap["airplane"] = R.array.tile_states_airplane + subtitleIdsMap["location"] = R.array.tile_states_location + subtitleIdsMap["hotspot"] = R.array.tile_states_hotspot + subtitleIdsMap["inversion"] = R.array.tile_states_inversion + subtitleIdsMap["saver"] = R.array.tile_states_saver + subtitleIdsMap["dark"] = R.array.tile_states_dark + subtitleIdsMap["work"] = R.array.tile_states_work + subtitleIdsMap["cast"] = R.array.tile_states_cast + subtitleIdsMap["night"] = R.array.tile_states_night + subtitleIdsMap["screenrecord"] = R.array.tile_states_screenrecord + subtitleIdsMap["reverse"] = R.array.tile_states_reverse + subtitleIdsMap["reduce_brightness"] = R.array.tile_states_reduce_brightness + subtitleIdsMap["cameratoggle"] = R.array.tile_states_cameratoggle + subtitleIdsMap["mictoggle"] = R.array.tile_states_mictoggle + subtitleIdsMap["controls"] = R.array.tile_states_controls + subtitleIdsMap["wallet"] = R.array.tile_states_wallet + subtitleIdsMap["qr_code_scanner"] = R.array.tile_states_qr_code_scanner + subtitleIdsMap["alarm"] = R.array.tile_states_alarm + subtitleIdsMap["onehanded"] = R.array.tile_states_onehanded + subtitleIdsMap["color_correction"] = R.array.tile_states_color_correction + subtitleIdsMap["dream"] = R.array.tile_states_dream + subtitleIdsMap["font_scaling"] = R.array.tile_states_font_scaling + } + + /** Get the subtitle resource id of the given tile */ + fun getSubtitleId(spec: String?): Int { + return if (spec == null) { + R.array.tile_states_default + } else subtitleIdsMap[spec] ?: R.array.tile_states_default + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java index 033dbe0f82ee..92a83bba8a68 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java @@ -57,6 +57,9 @@ import dagger.Lazy; /** Quick settings tile: Airplane mode **/ public class AirplaneModeTile extends QSTileImpl<BooleanState> { + + public static final String TILE_SPEC = "airplane"; + private final SettingObserver mSetting; private final BroadcastDispatcher mBroadcastDispatcher; private final Lazy<ConnectivityManager> mLazyConnectivityManager; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt index 14e0f707d3b5..2ca452e45ecf 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt @@ -118,4 +118,8 @@ class AlarmTile @Inject constructor( override fun getLongClickIntent(): Intent? { return null } -}
\ No newline at end of file + + companion object { + const val TILE_SPEC = "alarm" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java index ee49b294dfcd..027a464251c9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java @@ -48,6 +48,8 @@ import javax.inject.Inject; public class BatterySaverTile extends QSTileImpl<BooleanState> implements BatteryController.BatteryStateChangeCallback { + public static final String TILE_SPEC = "battery"; + private final BatteryController mBatteryController; @VisibleForTesting protected final SettingObserver mSetting; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 9a0d0d9656ca..df1c8dfdde96 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -55,6 +55,9 @@ import javax.inject.Inject; /** Quick settings tile: Bluetooth **/ public class BluetoothTile extends QSTileImpl<BooleanState> { + + public static final String TILE_SPEC = "bt"; + private static final Intent BLUETOOTH_SETTINGS = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS); private final BluetoothController mController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java index ee41f1d1077d..93e5f1efbdc8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java @@ -45,6 +45,8 @@ import javax.inject.Inject; public class CameraToggleTile extends SensorPrivacyToggleTile { + public static final String TILE_SPEC = "cameratoggle"; + @Inject protected CameraToggleTile(QSHost host, @Background Looper backgroundLooper, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index dce137f5b9f3..8d984817ba77 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -66,7 +66,9 @@ import javax.inject.Inject; /** Quick settings tile: Cast **/ public class CastTile extends QSTileImpl<BooleanState> { - private static final String INTERACTION_JANK_TAG = "cast"; + public static final String TILE_SPEC = "cast"; + + private static final String INTERACTION_JANK_TAG = TILE_SPEC; private static final Intent CAST_SETTINGS = new Intent(Settings.ACTION_CAST_SETTINGS); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java index 6dfcf5ccc258..b6205d5df63d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java @@ -48,6 +48,8 @@ import javax.inject.Inject; /** Quick settings tile: Color correction **/ public class ColorCorrectionTile extends QSTileImpl<BooleanState> { + public static final String TILE_SPEC = "color_correction"; + private final Icon mIcon = ResourceIcon.get(drawable.ic_qs_color_correction); private final SettingObserver mSetting; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index a31500c6bb18..9a44e83ad9a1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -49,6 +49,7 @@ import javax.inject.Inject; /** Quick settings tile: Invert colors **/ public class ColorInversionTile extends QSTileImpl<BooleanState> { + public static final String TILE_SPEC = "inversion"; private final SettingObserver mSetting; @Inject diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java index 2fc99f323611..add517e18516 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java @@ -48,6 +48,8 @@ import javax.inject.Inject; public class DataSaverTile extends QSTileImpl<BooleanState> implements DataSaverController.Listener{ + public static final String TILE_SPEC = "saver"; + private static final String INTERACTION_JANK_TAG = "start_data_saver"; private final DataSaverController mDataSaverController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt index 41d854969e20..01164fb0a009 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt @@ -159,4 +159,8 @@ class DeviceControlsTile @Inject constructor( override fun getTileLabel(): CharSequence { return mContext.getText(controlsComponent.getTileTitleId()) } + + companion object { + const val TILE_SPEC = "controls" + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 8b7f53fa5a3f..434fe45f47c0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -67,6 +67,8 @@ import javax.inject.Inject; /** Quick settings tile: Do not disturb **/ public class DndTile extends QSTileImpl<BooleanState> { + public static final String TILE_SPEC = "dnd"; + private static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java index 5bc209a840cb..53774e82602b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java @@ -60,6 +60,8 @@ import javax.inject.Named; /** Quick settings tile: Screensaver (dream) **/ public class DreamTile extends QSTileImpl<QSTile.BooleanState> { + public static final String TILE_SPEC = "dream"; + private static final String LOG_TAG = "QSDream"; // TODO: consider 1 animated icon instead private final Icon mIconDocked = ResourceIcon.get(R.drawable.ic_qs_screen_saver); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index a74792687289..e091a750fbec 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -49,6 +49,7 @@ import javax.inject.Inject; public class FlashlightTile extends QSTileImpl<BooleanState> implements FlashlightController.FlashlightListener { + public static final String TILE_SPEC = "flashlight"; private final FlashlightController mFlashlightController; @Inject diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt index b9cd535b9765..721046d217c9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt @@ -103,6 +103,7 @@ constructor( } companion object { + const val TILE_SPEC = "font_scaling" private const val INTERACTION_JANK_TAG = "font_scaling" } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index 624def60276b..6bf8b7666054 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -51,6 +51,7 @@ import javax.inject.Inject; /** Quick settings tile: Hotspot **/ public class HotspotTile extends QSTileImpl<BooleanState> { + public static final String TILE_SPEC = "hotspot"; private final HotspotController mHotspotController; private final DataSaverController mDataSaverController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java index 1c60486a6909..12e9aebc58f7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java @@ -67,6 +67,9 @@ import javax.inject.Inject; /** Quick settings tile: Internet **/ public class InternetTile extends QSTileImpl<SignalState> { + + public static final String TILE_SPEC = "internet"; + private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS); protected final NetworkController mController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index 9466a694ea1b..89d402a3af5a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -48,6 +48,8 @@ import javax.inject.Inject; /** Quick settings tile: Location **/ public class LocationTile extends QSTileImpl<BooleanState> { + public static final String TILE_SPEC = "location"; + private final LocationController mController; private final KeyguardStateController mKeyguard; private final Callback mCallback = new Callback(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java index e54709562c10..2e475d40d55f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java @@ -45,6 +45,8 @@ import javax.inject.Inject; public class MicrophoneToggleTile extends SensorPrivacyToggleTile { + public static final String TILE_SPEC = "mictoggle"; + @Inject protected MicrophoneToggleTile(QSHost host, @Background Looper backgroundLooper, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java index a61f0ce0c864..e189f80a7c23 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java @@ -51,7 +51,9 @@ import javax.inject.Inject; /** Quick settings tile: Enable/Disable NFC **/ public class NfcTile extends QSTileImpl<BooleanState> { - private static final String NFC = "nfc"; + public static final String TILE_SPEC = "nfc"; + + private static final String NFC = TILE_SPEC; private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_nfc); @Nullable diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java index 0e9f6599522f..aacd53bde51c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java @@ -61,6 +61,8 @@ import javax.inject.Inject; public class NightDisplayTile extends QSTileImpl<BooleanState> implements NightDisplayListener.Callback { + public static final String TILE_SPEC = "night"; + /** * Pattern for {@link java.time.format.DateTimeFormatter} used to approximate the time to the * nearest hour and add on the AM/PM indicator. diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java index 7e1712455e72..ae67d99ea2fb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java @@ -47,6 +47,9 @@ import javax.inject.Inject; /** Quick settings tile: One-handed mode **/ public class OneHandedModeTile extends QSTileImpl<BooleanState> { + + public static final String TILE_SPEC = "onehanded"; + private final Icon mIcon = ResourceIcon.get( com.android.internal.R.drawable.ic_qs_one_handed_mode); private final SettingObserver mSetting; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java index 6d50b562cd02..92f52724ca0c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java @@ -44,6 +44,9 @@ import javax.inject.Inject; /** Quick settings tile: QR Code Scanner **/ public class QRCodeScannerTile extends QSTileImpl<QSTile.State> { + + public static final String TILE_SPEC = "qr_code_scanner"; + private static final String TAG = "QRCodeScanner"; private final CharSequence mLabel = mContext.getString(R.string.qr_code_scanner_title); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java index 248c78e557cc..4a3c56328006 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java @@ -62,6 +62,8 @@ import javax.inject.Inject; /** Quick settings tile: Quick access wallet **/ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> { + public static final String TILE_SPEC = "wallet"; + private static final String TAG = "QuickAccessWalletTile"; private static final String FEATURE_CHROME_OS = "org.chromium.arc"; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java index 1dac33909ba7..10f1ce4946c8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java @@ -49,6 +49,7 @@ import javax.inject.Named; public class ReduceBrightColorsTile extends QSTileImpl<QSTile.BooleanState> implements ReduceBrightColorsController.Listener{ + public static final String TILE_SPEC = "reduce_brightness"; private final boolean mIsAvailable; private final ReduceBrightColorsController mReduceBrightColorsController; private boolean mIsListening; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index 600874f0d01a..8888c733c3c1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -57,6 +57,9 @@ import javax.inject.Inject; /** Quick settings tile: Rotation **/ public class RotationLockTile extends QSTileImpl<BooleanState> implements BatteryController.BatteryStateChangeCallback { + + public static final String TILE_SPEC = "rotation"; + private static final String EMPTY_SECONDARY_STRING = ""; private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_auto_rotate); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java index ad000690a354..07b50c9a66f6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java @@ -54,6 +54,9 @@ import javax.inject.Inject; */ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> implements RecordingController.RecordingStateChangeCallback { + + public static final String TILE_SPEC = "screenrecord"; + private static final String TAG = "ScreenRecordTile"; private static final String INTERACTION_JANK_TAG = "screen_record"; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java index 92f6690a13e7..809689cb806d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java @@ -17,7 +17,6 @@ package com.android.systemui.qs.tiles; import android.app.UiModeManager; -import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.os.Handler; @@ -60,6 +59,9 @@ import javax.inject.Inject; public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements ConfigurationController.ConfigurationListener, BatteryController.BatteryStateChangeCallback { + + public static final String TILE_SPEC = "dark"; + public static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a"); private final UiModeManager mUiModeManager; private final BatteryController mBatteryController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index 72c6bfe371ce..6a5c99032457 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -49,6 +49,9 @@ import javax.inject.Inject; /** Quick settings tile: Work profile on/off */ public class WorkModeTile extends QSTileImpl<BooleanState> implements ManagedProfileController.Callback { + + public static final String TILE_SPEC = "work"; + private final Icon mIcon = ResourceIcon.get(R.drawable.stat_sys_managed_profile_status); private final ManagedProfileController mProfileController; diff --git a/packages/SystemUI/src/com/android/systemui/rotationlock/RotationLockModule.kt b/packages/SystemUI/src/com/android/systemui/rotationlock/RotationLockModule.kt new file mode 100644 index 000000000000..9abe90fb05d4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/rotationlock/RotationLockModule.kt @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.rotationlock + +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.qs.tiles.RotationLockTile +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface RotationLockModule { + + /** Inject RotationLockTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(RotationLockTile.TILE_SPEC) + fun bindRotationLockTile(rotationLockTile: RotationLockTile): QSTileImpl<*> +} diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordModule.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordModule.kt new file mode 100644 index 000000000000..7467805d73ec --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordModule.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.screenrecord + +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.qs.tiles.ScreenRecordTile +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface ScreenRecordModule { + /** Inject ScreenRecordTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(ScreenRecordTile.TILE_SPEC) + fun bindScreenRecordTile(screenRecordTile: ScreenRecordTile): QSTileImpl<*> +} diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java index 7a62bae5b5ae..fc94aed5336a 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java @@ -93,7 +93,13 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum { @UiEvent(doc = "User has discarded the result of a long screenshot") SCREENSHOT_LONG_SCREENSHOT_EXIT(911), @UiEvent(doc = "A screenshot has been taken and saved to work profile") - SCREENSHOT_SAVED_TO_WORK_PROFILE(1240); + SCREENSHOT_SAVED_TO_WORK_PROFILE(1240), + @UiEvent(doc = "Notes application triggered the screenshot for notes") + SCREENSHOT_FOR_NOTE_TRIGGERED(1308), + @UiEvent(doc = "User accepted the screenshot to be sent to the notes app") + SCREENSHOT_FOR_NOTE_ACCEPTED(1309), + @UiEvent(doc = "User cancelled the screenshot for notes app flow") + SCREENSHOT_FOR_NOTE_CANCELLED(1310); private final int mId; diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt index bfba6dfddfac..bb637dcd860e 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt @@ -32,74 +32,62 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.util.concurrency.DelayableExecutor import java.io.File +import java.io.FilenameFilter import javax.inject.Inject /** - * Implementation for retrieving file paths for file storage of system and secondary users. Files - * lie in {File Directory}/UserFileManager/{User Id} for secondary user. For system user, we use the - * conventional {File Directory} + * Implementation for retrieving file paths for file storage of system and secondary users. For + * non-system users, files will be prepended by a special prefix containing the user id. */ @SysUISingleton class UserFileManagerImpl @Inject constructor( - // Context of system process and system user. private val context: Context, val userManager: UserManager, val broadcastDispatcher: BroadcastDispatcher, @Background val backgroundExecutor: DelayableExecutor ) : UserFileManager, CoreStartable { companion object { - private const val FILES = "files" + private const val PREFIX = "__USER_" + private const val TAG = "UserFileManagerImpl" + const val ROOT_DIR = "UserFileManager" + const val FILES = "files" const val SHARED_PREFS = "shared_prefs" - @VisibleForTesting internal const val ID = "UserFileManager" - - /** Returns `true` if the given user ID is that for the primary/system user. */ - fun isPrimaryUser(userId: Int): Boolean { - return UserHandle(userId).isSystem - } /** - * Returns a [File] pointing to the correct path for a secondary user ID. - * - * Note that there is no check for the type of user. This should only be called for - * secondary users, never for the system user. For that, make sure to call [isPrimaryUser]. - * - * Note also that there is no guarantee that the parent directory structure for the file - * exists on disk. For that, call [ensureParentDirExists]. - * - * @param context The context - * @param fileName The name of the file - * @param directoryName The name of the directory that would contain the file - * @param userId The ID of the user to build a file path for + * Returns a File object with a relative path, built from the userId for non-system users */ - fun secondaryUserFile( - context: Context, - fileName: String, - directoryName: String, - userId: Int, - ): File { - return Environment.buildPath( - context.filesDir, - ID, - userId.toString(), - directoryName, - fileName, - ) + fun createFile(fileName: String, userId: Int): File { + return if (isSystemUser(userId)) { + File(fileName) + } else { + File(getFilePrefix(userId) + fileName) + } } - /** - * Checks to see if parent dir of the file exists. If it does not, we create the parent dirs - * recursively. - */ - fun ensureParentDirExists(file: File) { - val parent = file.parentFile - if (!parent.exists()) { - if (!parent.mkdirs()) { - Log.e(ID, "Could not create parent directory for file: ${file.absolutePath}") - } + fun createLegacyFile(context: Context, dir: String, fileName: String, userId: Int): File? { + return if (isSystemUser(userId)) { + null + } else { + return Environment.buildPath( + context.filesDir, + ROOT_DIR, + userId.toString(), + dir, + fileName + ) } } + + fun getFilePrefix(userId: Int): String { + return PREFIX + userId.toString() + "_" + } + + /** Returns `true` if the given user ID is that for the system user. */ + private fun isSystemUser(userId: Int): Boolean { + return UserHandle(userId).isSystem + } } private val broadcastReceiver = @@ -119,64 +107,87 @@ constructor( broadcastDispatcher.registerReceiver(broadcastReceiver, filter, backgroundExecutor) } - /** Return the file based on current user. */ + /** + * Return the file based on current user. Files for all users will exist in [context.filesDir], + * but non system user files will be prepended with [getFilePrefix]. + */ override fun getFile(fileName: String, userId: Int): File { - return if (isPrimaryUser(userId)) { - Environment.buildPath(context.filesDir, fileName) - } else { - val secondaryFile = - secondaryUserFile( - context = context, - userId = userId, - directoryName = FILES, - fileName = fileName, - ) - ensureParentDirExists(secondaryFile) - secondaryFile - } + val file = File(context.filesDir, createFile(fileName, userId).path) + createLegacyFile(context, FILES, fileName, userId)?.run { migrate(file, this) } + return file } - /** Get shared preferences from user. */ + /** + * Get shared preferences from user. Files for all users will exist in the shared_prefs dir, but + * non system user files will be prepended with [getFilePrefix]. + */ override fun getSharedPreferences( fileName: String, @Context.PreferencesMode mode: Int, userId: Int ): SharedPreferences { - if (isPrimaryUser(userId)) { - return context.getSharedPreferences(fileName, mode) + val file = createFile(fileName, userId) + createLegacyFile(context, SHARED_PREFS, "$fileName.xml", userId)?.run { + val path = Environment.buildPath(context.dataDir, SHARED_PREFS, "${file.path}.xml") + migrate(path, this) } - - val secondaryUserDir = - secondaryUserFile( - context = context, - fileName = fileName, - directoryName = SHARED_PREFS, - userId = userId, - ) - - ensureParentDirExists(secondaryUserDir) - return context.getSharedPreferences(secondaryUserDir, mode) + return context.getSharedPreferences(file.path, mode) } - /** Remove dirs for deleted users. */ + /** Remove files for deleted users. */ @VisibleForTesting internal fun clearDeletedUserData() { backgroundExecutor.execute { - val file = Environment.buildPath(context.filesDir, ID) - if (!file.exists()) return@execute - val aliveUsers = userManager.aliveUsers.map { it.id.toString() } - val dirsToDelete = file.list().filter { !aliveUsers.contains(it) } + deleteFiles(context.filesDir) + deleteFiles(File(context.dataDir, SHARED_PREFS)) + } + } + + private fun migrate(dest: File, source: File) { + if (source.exists()) { + try { + val parent = source.getParentFile() + source.renameTo(dest) + + deleteParentDirsIfEmpty(parent) + } catch (e: Exception) { + Log.e(TAG, "Failed to rename and delete ${source.path}", e) + } + } + } - dirsToDelete.forEach { dir -> + private fun deleteParentDirsIfEmpty(dir: File?) { + if (dir != null && dir.listFiles().size == 0) { + val priorParent = dir.parentFile + val isRoot = dir.name == ROOT_DIR + dir.delete() + + if (!isRoot) { + deleteParentDirsIfEmpty(priorParent) + } + } + } + + private fun deleteFiles(parent: File) { + val aliveUserFilePrefix = userManager.aliveUsers.map { getFilePrefix(it.id) } + val filesToDelete = + parent.listFiles( + FilenameFilter { _, name -> + name.startsWith(PREFIX) && + aliveUserFilePrefix.filter { name.startsWith(it) }.isEmpty() + } + ) + + // This can happen in test environments + if (filesToDelete == null) { + Log.i(TAG, "Empty directory: ${parent.path}") + } else { + filesToDelete.forEach { file -> + Log.i(TAG, "Deleting file: ${file.path}") try { - val dirToDelete = - Environment.buildPath( - file, - dir, - ) - dirToDelete.deleteRecursively() + file.delete() } catch (e: Exception) { - Log.e(ID, "Deletion failed.", e) + Log.e(TAG, "Deletion failed.", e) } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index f565f3daf2ee..afa60fbe70ab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -262,7 +262,6 @@ class LockscreenShadeTransitionController @Inject constructor( fun setStackScroller(nsslController: NotificationStackScrollLayoutController) { this.nsslController = nsslController - touchHelper.host = nsslController.view touchHelper.expandCallback = nsslController.expandHelperCallback } @@ -736,14 +735,12 @@ class DragDownHelper( private var dragDownAmountOnStart = 0.0f lateinit var expandCallback: ExpandHelper.Callback - lateinit var host: View private var minDragDistance = 0 private var initialTouchX = 0f private var initialTouchY = 0f private var touchSlop = 0f private var slopMultiplier = 0f - private val temp2 = IntArray(2) private var draggedFarEnough = false private var startingChild: ExpandableView? = null private var lastHeight = 0f @@ -923,7 +920,6 @@ class DragDownHelper( } private fun findView(x: Float, y: Float): ExpandableView? { - host.getLocationOnScreen(temp2) - return expandCallback.getChildAtRawPosition(x + temp2[0], y + temp2[1]) + return expandCallback.getChildAtRawPosition(x, y) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt new file mode 100644 index 000000000000..1099810f972f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.connectivity + +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.qs.tiles.AirplaneModeTile +import com.android.systemui.qs.tiles.BluetoothTile +import com.android.systemui.qs.tiles.CastTile +import com.android.systemui.qs.tiles.DataSaverTile +import com.android.systemui.qs.tiles.HotspotTile +import com.android.systemui.qs.tiles.InternetTile +import com.android.systemui.qs.tiles.NfcTile +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface ConnectivityModule { + + /** Inject InternetTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(InternetTile.TILE_SPEC) + fun bindInternetTile(internetTile: InternetTile): QSTileImpl<*> + + /** Inject BluetoothTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(BluetoothTile.TILE_SPEC) + fun bindBluetoothTile(bluetoothTile: BluetoothTile): QSTileImpl<*> + + /** Inject CastTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(CastTile.TILE_SPEC) + fun bindCastTile(castTile: CastTile): QSTileImpl<*> + + /** Inject HotspotTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(HotspotTile.TILE_SPEC) + fun bindHotspotTile(hotspotTile: HotspotTile): QSTileImpl<*> + + /** Inject AirplaneModeTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(AirplaneModeTile.TILE_SPEC) + fun bindAirplaneModeTile(airplaneModeTile: AirplaneModeTile): QSTileImpl<*> + + /** Inject DataSaverTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(DataSaverTile.TILE_SPEC) + fun bindDataSaverTile(dataSaverTile: DataSaverTile): QSTileImpl<*> + + /** Inject NfcTile into tileMap in QSModule */ + @Binds @IntoMap @StringKey(NfcTile.TILE_SPEC) fun bindNfcTile(nfcTile: NfcTile): QSTileImpl<*> +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt index 6bf7668f080c..82bd45ce2279 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package com.android.systemui.statusbar.notification.collection.coordinator import android.os.UserHandle @@ -39,14 +41,20 @@ import com.android.systemui.statusbar.policy.headsUpEvents import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import javax.inject.Inject +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.launch /** @@ -93,14 +101,39 @@ constructor( private suspend fun trackUnseenNotificationsWhileUnlocked() { // Use collectLatest so that trackUnseenNotifications() is cancelled when the keyguard is // showing again + var clearUnseenOnUnlock = false keyguardRepository.isKeyguardShowing.collectLatest { isKeyguardShowing -> - if (!isKeyguardShowing) { + if (isKeyguardShowing) { + // Wait for the user to spend enough time on the lock screen before clearing unseen + // set when unlocked + awaitTimeSpentNotDozing(SEEN_TIMEOUT) + clearUnseenOnUnlock = true + } else { unseenNotifFilter.invalidateList("keyguard no longer showing") + if (clearUnseenOnUnlock) { + clearUnseenOnUnlock = false + unseenNotifications.clear() + } trackUnseenNotifications() } } } + private suspend fun awaitTimeSpentNotDozing(duration: Duration) { + keyguardRepository.isDozing + // Use transformLatest so that the timeout delay is cancelled if the device enters doze, + // and is restarted when doze ends. + .transformLatest { isDozing -> + if (!isDozing) { + delay(duration) + // Signal timeout has completed + emit(Unit) + } + } + // Suspend until the first emission + .first() + } + private suspend fun trackUnseenNotifications() { coroutineScope { launch { clearUnseenNotificationsWhenShadeIsExpanded() } @@ -240,5 +273,6 @@ constructor( companion object { private const val TAG = "KeyguardCoordinator" + private val SEEN_TIMEOUT = 5.seconds } } 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 9275e2b603c3..64c1a595483e 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 @@ -1196,6 +1196,22 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return getShowingLayout().getVisibleWrapper(); } + /** + * @return whether the notification row is long clickable or not. + */ + public boolean isNotificationRowLongClickable() { + if (mLongPressListener == null) { + return false; + } + + if (!areGutsExposed()) { // guts is not opened + return true; + } + + // if it is leave behind, it shouldn't be long clickable. + return !isGutsLeaveBehind(); + } + public void setLongPressListener(LongPressListener longPressListener) { mLongPressListener = longPressListener; } @@ -2947,6 +2963,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return (mGuts != null && mGuts.isExposed()); } + private boolean isGutsLeaveBehind() { + return (mGuts != null && mGuts.isLeavebehind()); + } + @Override public boolean isContentExpandable() { if (mIsSummaryWithChildren && !shouldShowPublic()) { @@ -3394,7 +3414,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfoInternal(info); - info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK); + final boolean isLongClickable = isNotificationRowLongClickable(); + if (isLongClickable) { + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK); + } + info.setLongClickable(isLongClickable); + if (canViewBeDismissed() && !mIsSnoozed) { info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index 37ff11db81e3..06d40803052e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -586,7 +586,9 @@ public class NotificationGutsManager implements NotifGutsViewManager { } final ExpandableNotificationRow row = (ExpandableNotificationRow) view; - view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + if (row.isNotificationRowLongClickable()) { + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } if (row.areGutsExposed()) { closeAndSaveGuts(false /* removeLeavebehind */, false /* force */, true /* removeControls */, -1 /* x */, -1 /* y */, 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 6e6396047361..3170f34bcebd 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 @@ -870,7 +870,8 @@ public class StackScrollAlgorithm { } for (int i = childCount - 1; i >= 0; i--) { - updateChildZValue(i, algorithmState, ambientState, i == topHunIndex); + childrenOnTop = updateChildZValue(i, childrenOnTop, + algorithmState, ambientState, i == topHunIndex); } } @@ -880,11 +881,15 @@ 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 void updateChildZValue(int i, - StackScrollAlgorithmState algorithmState, - AmbientState ambientState, - boolean isTopHun) { + protected float updateChildZValue(int i, float childrenOnTop, + StackScrollAlgorithmState algorithmState, + AmbientState ambientState, + boolean isTopHun) { ExpandableView child = algorithmState.visibleChildren.get(i); ExpandableViewState childViewState = child.getViewState(); float baseZ = ambientState.getBaseZHeight(); @@ -898,16 +903,22 @@ 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 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); + // 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); } + 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 @@ -935,14 +946,15 @@ public class StackScrollAlgorithm { } // Handles HUN shadow when shade is closed. - // 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. + // While HUN is showing and Shade is closed: 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/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt index 4a5342e0f765..5d5d562a22fc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt @@ -18,9 +18,10 @@ package com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.log.table.TableLogBuffer +import com.android.systemui.log.table.logDiffsForTable import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange +import com.android.systemui.statusbar.pipeline.dagger.AirplaneTableLog import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted @@ -46,7 +47,7 @@ class AirplaneModeViewModelImpl @Inject constructor( interactor: AirplaneModeInteractor, - logger: ConnectivityPipelineLogger, + @AirplaneTableLog logger: TableLogBuffer, @Application private val scope: CoroutineScope, ) : AirplaneModeViewModel { override val isAirplaneModeIconVisible: StateFlow<Boolean> = @@ -56,6 +57,11 @@ constructor( isAirplaneMode && !isAirplaneIconForceHidden } .distinctUntilChanged() - .logOutputChange(logger, "isAirplaneModeIconVisible") + .logDiffsForTable( + logger, + columnPrefix = "", + columnName = "isAirplaneModeIconVisible", + initialValue = false, + ) .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false) } diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarConnectivityLog.java b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileInputLog.kt index 67cdb722055b..d1aa79e2233a 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarConnectivityLog.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileInputLog.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,22 +14,12 @@ * limitations under the License. */ -package com.android.systemui.log.dagger; +package com.android.systemui.statusbar.pipeline.dagger -import static java.lang.annotation.RetentionPolicy.RUNTIME; +import javax.inject.Qualifier -import com.android.systemui.plugins.log.LogBuffer; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; - -import javax.inject.Qualifier; - -/** - * A {@link LogBuffer} for status bar connectivity events. - */ +/** Logs for inputs into the mobile pipeline. */ @Qualifier -@Documented -@Retention(RUNTIME) -public @interface StatusBarConnectivityLog { -} +@MustBeDocumented +@kotlin.annotation.Retention(AnnotationRetention.RUNTIME) +annotation class MobileInputLog diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/SharedConnectivityInputLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/SharedConnectivityInputLog.kt new file mode 100644 index 000000000000..5face22e505f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/SharedConnectivityInputLog.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.dagger + +import javax.inject.Qualifier + +/** Logs for connectivity-related inputs that are shared across wifi, mobile, etc. */ +@Qualifier +@MustBeDocumented +@kotlin.annotation.Retention(AnnotationRetention.RUNTIME) +annotation class SharedConnectivityInputLog diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt index 60de1a38dd95..44647515a6e5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt @@ -19,8 +19,10 @@ package com.android.systemui.statusbar.pipeline.dagger import android.net.wifi.WifiManager import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.log.LogBufferFactory import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBufferFactory +import com.android.systemui.plugins.log.LogBuffer import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepositoryImpl import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel @@ -107,6 +109,13 @@ abstract class StatusBarPipelineModule { @Provides @SysUISingleton + @WifiInputLog + fun provideWifiInputLogBuffer(factory: LogBufferFactory): LogBuffer { + return factory.create("WifiInputLog", 50) + } + + @Provides + @SysUISingleton @WifiTableLog fun provideWifiTableLogBuffer(factory: TableLogBufferFactory): TableLogBuffer { return factory.create("WifiTableLog", 100) @@ -121,9 +130,23 @@ abstract class StatusBarPipelineModule { @Provides @SysUISingleton + @SharedConnectivityInputLog + fun provideSharedConnectivityTableLogBuffer(factory: LogBufferFactory): LogBuffer { + return factory.create("SharedConnectivityInputLog", 30) + } + + @Provides + @SysUISingleton @MobileSummaryLog fun provideMobileSummaryLogBuffer(factory: TableLogBufferFactory): TableLogBuffer { return factory.create("MobileSummaryLog", 100) } + + @Provides + @SysUISingleton + @MobileInputLog + fun provideMobileInputLogBuffer(factory: LogBufferFactory): LogBuffer { + return factory.create("MobileInputLog", 100) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt new file mode 100644 index 000000000000..6db694474f5f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.dagger + +import javax.inject.Qualifier + +/** Wifi logs for inputs into the wifi pipeline. */ +@Qualifier +@MustBeDocumented +@kotlin.annotation.Retention(AnnotationRetention.RUNTIME) +annotation class WifiInputLog diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt index 5769f90ab6c7..bb3b9b2166c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt @@ -31,7 +31,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dump.DumpManager import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger +import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger import java.io.PrintWriter import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -57,7 +57,7 @@ constructor( broadcastDispatcher: BroadcastDispatcher, private val carrierConfigManager: CarrierConfigManager, dumpManager: DumpManager, - logger: ConnectivityPipelineLogger, + logger: MobileInputLogger, @Application scope: CoroutineScope, ) : Dumpable { private var isListening = false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt index 938c7346f702..8f6a87b089f2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt @@ -28,8 +28,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetwork import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt index dcce0ea58512..96b96f14d6aa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt @@ -47,8 +47,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameMo import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS +import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher @@ -85,7 +85,7 @@ class MobileConnectionRepositoryImpl( broadcastDispatcher: BroadcastDispatcher, private val mobileMappingsProxy: MobileMappingsProxy, bgDispatcher: CoroutineDispatcher, - logger: ConnectivityPipelineLogger, + logger: MobileInputLogger, override val tableLogBuffer: TableLogBuffer, scope: CoroutineScope, ) : MobileConnectionRepository { @@ -291,7 +291,7 @@ class MobileConnectionRepositoryImpl( private val broadcastDispatcher: BroadcastDispatcher, private val context: Context, private val telephonyManager: TelephonyManager, - private val logger: ConnectivityPipelineLogger, + private val logger: MobileInputLogger, private val carrierConfigRepository: CarrierConfigRepository, private val mobileMappingsProxy: MobileMappingsProxy, @Background private val bgDispatcher: CoroutineDispatcher, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt index e77266fc6d8a..b3d5b1e7e450 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt @@ -49,11 +49,10 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectiv import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository +import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.util.kotlin.pairwise import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher @@ -84,7 +83,7 @@ constructor( private val connectivityManager: ConnectivityManager, private val subscriptionManager: SubscriptionManager, private val telephonyManager: TelephonyManager, - private val logger: ConnectivityPipelineLogger, + private val logger: MobileInputLogger, @MobileSummaryLog private val tableLogger: TableLogBuffer, mobileMappingsProxy: MobileMappingsProxy, broadcastDispatcher: BroadcastDispatcher, @@ -222,13 +221,13 @@ constructor( private val carrierConfigChangedEvent = broadcastDispatcher .broadcastFlow(IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) - .logInputChange(logger, "ACTION_CARRIER_CONFIG_CHANGED") + .onEach { logger.logActionCarrierConfigChanged() } override val defaultDataSubRatConfig: StateFlow<Config> = merge(defaultDataSubIdChangeEvent, carrierConfigChangedEvent) .mapLatest { Config.readConfig(context) } .distinctUntilChanged() - .logInputChange(logger, "defaultDataSubRatConfig") + .onEach { logger.logDefaultDataSubRatConfig(it) } .stateIn( scope, SharingStarted.WhileSubscribed(), @@ -239,13 +238,13 @@ constructor( defaultDataSubRatConfig .map { mobileMappingsProxy.mapIconSets(it) } .distinctUntilChanged() - .logInputChange(logger, "defaultMobileIconMapping") + .onEach { logger.logDefaultMobileIconMapping(it) } override val defaultMobileIconGroup: Flow<MobileIconGroup> = defaultDataSubRatConfig .map { mobileMappingsProxy.getDefaultIcons(it) } .distinctUntilChanged() - .logInputChange(logger, "defaultMobileIconGroup") + .onEach { logger.logDefaultMobileIconGroup(it) } override fun getRepoForSubId(subId: Int): FullMobileConnectionRepository { if (!isValidSubId(subId)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt index 5a2e11e8de88..142c372d4c07 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt @@ -30,7 +30,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionMod import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository import com.android.systemui.util.CarrierConfigTracker @@ -111,7 +110,6 @@ class MobileIconsInteractorImpl constructor( private val mobileConnectionsRepo: MobileConnectionsRepository, private val carrierConfigTracker: CarrierConfigTracker, - private val logger: ConnectivityPipelineLogger, @MobileSummaryLog private val tableLogger: TableLogBuffer, connectivityRepository: ConnectivityRepository, userSetupRepo: UserSetupRepository, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt new file mode 100644 index 000000000000..3cbd2b76c248 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.mobile.shared + +import android.net.Network +import android.net.NetworkCapabilities +import android.telephony.ServiceState +import android.telephony.SignalStrength +import android.telephony.TelephonyDisplayInfo +import com.android.settingslib.SignalIcon +import com.android.settingslib.mobile.MobileMappings +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.plugins.log.LogBuffer +import com.android.systemui.plugins.log.LogLevel +import com.android.systemui.statusbar.pipeline.dagger.MobileInputLog +import com.android.systemui.statusbar.pipeline.shared.LoggerHelper +import javax.inject.Inject + +/** Logs for inputs into the mobile pipeline. */ +@SysUISingleton +class MobileInputLogger +@Inject +constructor( + @MobileInputLog private val buffer: LogBuffer, +) { + fun logOnCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities, + isDefaultNetworkCallback: Boolean, + ) { + LoggerHelper.logOnCapabilitiesChanged( + buffer, + TAG, + network, + networkCapabilities, + isDefaultNetworkCallback, + ) + } + + fun logOnLost(network: Network) { + LoggerHelper.logOnLost(buffer, TAG, network) + } + + fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { + int1 = subId + bool1 = serviceState.isEmergencyOnly + bool2 = serviceState.roaming + str1 = serviceState.operatorAlphaShort + }, + { + "onServiceStateChanged: subId=$int1 emergencyOnly=$bool1 roaming=$bool2" + + " operator=$str1" + } + ) + } + + fun logOnSignalStrengthsChanged(signalStrength: SignalStrength, subId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { + int1 = subId + str1 = signalStrength.toString() + }, + { "onSignalStrengthsChanged: subId=$int1 strengths=$str1" } + ) + } + + fun logOnDataConnectionStateChanged(dataState: Int, networkType: Int, subId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { + int1 = subId + int2 = dataState + str1 = networkType.toString() + }, + { "onDataConnectionStateChanged: subId=$int1 dataState=$int2 networkType=$str1" }, + ) + } + + fun logOnDataActivity(direction: Int, subId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { + int1 = subId + int2 = direction + }, + { "onDataActivity: subId=$int1 direction=$int2" }, + ) + } + + fun logOnCarrierNetworkChange(active: Boolean, subId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { + int1 = subId + bool1 = active + }, + { "onCarrierNetworkChange: subId=$int1 active=$bool1" }, + ) + } + + fun logOnDisplayInfoChanged(displayInfo: TelephonyDisplayInfo, subId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { + int1 = subId + str1 = displayInfo.toString() + }, + { "onDisplayInfoChanged: subId=$int1 displayInfo=$str1" }, + ) + } + + fun logUiAdapterSubIdsUpdated(subs: List<Int>) { + buffer.log( + TAG, + LogLevel.INFO, + { str1 = subs.toString() }, + { "Sub IDs in MobileUiAdapter updated internally: $str1" }, + ) + } + + fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) { + buffer.log( + TAG, + LogLevel.INFO, + { str1 = subs.toString() }, + { "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" }, + ) + } + + fun logCarrierConfigChanged(subId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { int1 = subId }, + { "onCarrierConfigChanged: subId=$int1" }, + ) + } + + fun logOnDataEnabledChanged(enabled: Boolean, subId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { + int1 = subId + bool1 = enabled + }, + { "onDataEnabledChanged: subId=$int1 enabled=$bool1" }, + ) + } + + fun logActionCarrierConfigChanged() { + buffer.log(TAG, LogLevel.INFO, {}, { "Intent received: ACTION_CARRIER_CONFIG_CHANGED" }) + } + + fun logDefaultDataSubRatConfig(config: MobileMappings.Config) { + buffer.log( + TAG, + LogLevel.INFO, + { str1 = config.toString() }, + { "defaultDataSubRatConfig: $str1" } + ) + } + + fun logDefaultMobileIconMapping(mapping: Map<String, SignalIcon.MobileIconGroup>) { + buffer.log( + TAG, + LogLevel.INFO, + { str1 = mapping.toString() }, + { "defaultMobileIconMapping: $str1" } + ) + } + + fun logDefaultMobileIconGroup(group: SignalIcon.MobileIconGroup) { + buffer.log(TAG, LogLevel.INFO, { str1 = group.name }, { "defaultMobileIconGroup: $str1" }) + } +} + +private const val TAG = "MobileInputLog" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt index ef75713cd2f2..da63ab10f733 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt @@ -22,8 +22,8 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.statusbar.phone.StatusBarIconController import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor +import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import java.io.PrintWriter import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -55,7 +55,7 @@ constructor( interactor: MobileIconsInteractor, private val iconController: StatusBarIconController, private val iconsViewModelFactory: MobileIconsViewModel.Factory, - private val logger: ConnectivityPipelineLogger, + private val logger: MobileInputLogger, @Application private val scope: CoroutineScope, private val statusBarPipelineFlags: StatusBarPipelineFlags, ) : CoreStartable { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt index 185b6685ba0e..8cb52af336da 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt @@ -25,7 +25,6 @@ import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.Airpla import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.StateFlow @@ -42,7 +41,6 @@ constructor( val subscriptionIdsFlow: StateFlow<List<Int>>, private val interactor: MobileIconsInteractor, private val airplaneModeInteractor: AirplaneModeInteractor, - private val logger: ConnectivityPipelineLogger, private val constants: ConnectivityConstants, @Application private val scope: CoroutineScope, private val statusBarPipelineFlags: StatusBarPipelineFlags, @@ -83,7 +81,6 @@ constructor( constructor( private val interactor: MobileIconsInteractor, private val airplaneModeInteractor: AirplaneModeInteractor, - private val logger: ConnectivityPipelineLogger, private val constants: ConnectivityConstants, @Application private val scope: CoroutineScope, private val statusBarPipelineFlags: StatusBarPipelineFlags, @@ -93,7 +90,6 @@ constructor( subscriptionIdsFlow, interactor, airplaneModeInteractor, - logger, constants, scope, statusBarPipelineFlags, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt index 0c9b86cb2b11..0fe53294fa7d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt @@ -22,7 +22,6 @@ import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG import java.io.PrintWriter import javax.inject.Inject @@ -40,7 +39,7 @@ constructor( telephonyManager: TelephonyManager, ) : Dumpable { init { - dumpManager.registerNormalDumpable("${SB_LOGGING_TAG}Constants", this) + dumpManager.registerNormalDumpable("ConnectivityConstants", this) } /** True if this device has the capability for data connections and false otherwise. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt new file mode 100644 index 000000000000..95548b84f769 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.shared + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.plugins.log.LogBuffer +import com.android.systemui.plugins.log.LogLevel +import com.android.systemui.statusbar.pipeline.dagger.SharedConnectivityInputLog +import javax.inject.Inject + +/** Logs for connectivity-related inputs that are shared across wifi, mobile, etc. */ +@SysUISingleton +class ConnectivityInputLogger +@Inject +constructor( + @SharedConnectivityInputLog private val buffer: LogBuffer, +) { + fun logTuningChanged(tuningList: String?) { + buffer.log(TAG, LogLevel.DEBUG, { str1 = tuningList }, { "onTuningChanged: $str1" }) + } +} + +private const val TAG = "ConnectivityInputLogger" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt deleted file mode 100644 index 45036969aefe..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.statusbar.pipeline.shared - -import android.net.Network -import android.net.NetworkCapabilities -import android.telephony.ServiceState -import android.telephony.SignalStrength -import android.telephony.TelephonyDisplayInfo -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.log.dagger.StatusBarConnectivityLog -import com.android.systemui.plugins.log.LogBuffer -import com.android.systemui.plugins.log.LogLevel -import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.toString -import javax.inject.Inject -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.onEach - -@SysUISingleton -class ConnectivityPipelineLogger -@Inject -constructor( - @StatusBarConnectivityLog private val buffer: LogBuffer, -) { - /** - * Logs a change in one of the **raw inputs** to the connectivity pipeline. - * - * Use this method for inputs that don't have any extra information besides their callback name. - */ - fun logInputChange(callbackName: String) { - buffer.log(SB_LOGGING_TAG, LogLevel.INFO, { str1 = callbackName }, { "Input: $str1" }) - } - - /** Logs a change in one of the **raw inputs** to the connectivity pipeline. */ - fun logInputChange(callbackName: String, changeInfo: String?) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - str1 = callbackName - str2 = changeInfo - }, - { "Input: $str1: $str2" } - ) - } - - /** Logs a **data transformation** that we performed within the connectivity pipeline. */ - fun logTransformation(transformationName: String, oldValue: Any?, newValue: Any?) { - if (oldValue == newValue) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - str1 = transformationName - str2 = oldValue.toString() - }, - { "Transform: $str1: $str2 (transformation didn't change it)" } - ) - } else { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - str1 = transformationName - str2 = oldValue.toString() - str3 = newValue.toString() - }, - { "Transform: $str1: $str2 -> $str3" } - ) - } - } - - /** Logs a change in one of the **outputs** to the connectivity pipeline. */ - fun logOutputChange(outputParamName: String, changeInfo: String) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - str1 = outputParamName - str2 = changeInfo - }, - { "Output: $str1: $str2" } - ) - } - - fun logOnCapabilitiesChanged( - network: Network, - networkCapabilities: NetworkCapabilities, - isDefaultNetworkCallback: Boolean, - ) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - bool1 = isDefaultNetworkCallback - int1 = network.getNetId() - str1 = networkCapabilities.toString() - }, - { "onCapabilitiesChanged[default=$bool1]: net=$int1 capabilities=$str1" } - ) - } - - fun logOnLost(network: Network) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { int1 = network.getNetId() }, - { "onLost: net=$int1" } - ) - } - - fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - int1 = subId - bool1 = serviceState.isEmergencyOnly - bool2 = serviceState.roaming - str1 = serviceState.operatorAlphaShort - }, - { - "onServiceStateChanged: subId=$int1 emergencyOnly=$bool1 roaming=$bool2" + - " operator=$str1" - } - ) - } - - fun logOnSignalStrengthsChanged(signalStrength: SignalStrength, subId: Int) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - int1 = subId - str1 = signalStrength.toString() - }, - { "onSignalStrengthsChanged: subId=$int1 strengths=$str1" } - ) - } - - fun logOnDataConnectionStateChanged(dataState: Int, networkType: Int, subId: Int) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - int1 = subId - int2 = dataState - str1 = networkType.toString() - }, - { "onDataConnectionStateChanged: subId=$int1 dataState=$int2 networkType=$str1" }, - ) - } - - fun logOnDataActivity(direction: Int, subId: Int) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - int1 = subId - int2 = direction - }, - { "onDataActivity: subId=$int1 direction=$int2" }, - ) - } - - fun logOnCarrierNetworkChange(active: Boolean, subId: Int) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - int1 = subId - bool1 = active - }, - { "onCarrierNetworkChange: subId=$int1 active=$bool1" }, - ) - } - - fun logOnDisplayInfoChanged(displayInfo: TelephonyDisplayInfo, subId: Int) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - int1 = subId - str1 = displayInfo.toString() - }, - { "onDisplayInfoChanged: subId=$int1 displayInfo=$str1" }, - ) - } - - // TODO(b/238425913): We should split this class into mobile-specific and wifi-specific loggers. - - fun logUiAdapterSubIdsUpdated(subs: List<Int>) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { str1 = subs.toString() }, - { "Sub IDs in MobileUiAdapter updated internally: $str1" }, - ) - } - - fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { str1 = subs.toString() }, - { "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" }, - ) - } - - fun logCarrierConfigChanged(subId: Int) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { int1 = subId }, - { "onCarrierConfigChanged: subId=$int1" }, - ) - } - - fun logOnDataEnabledChanged(enabled: Boolean, subId: Int) { - buffer.log( - SB_LOGGING_TAG, - LogLevel.INFO, - { - int1 = subId - bool1 = enabled - }, - { "onDataEnabledChanged: subId=$int1 enabled=$bool1" }, - ) - } - - companion object { - const val SB_LOGGING_TAG = "SbConnectivity" - - /** Log a change in one of the **inputs** to the connectivity pipeline. */ - fun Flow<Unit>.logInputChange( - logger: ConnectivityPipelineLogger, - inputParamName: String, - ): Flow<Unit> { - return this.onEach { logger.logInputChange(inputParamName) } - } - - /** - * Log a change in one of the **inputs** to the connectivity pipeline. - * - * @param prettyPrint an optional function to transform the value into a readable string. - * [toString] is used if no custom function is provided. - */ - fun <T> Flow<T>.logInputChange( - logger: ConnectivityPipelineLogger, - inputParamName: String, - prettyPrint: (T) -> String = { it.toString() } - ): Flow<T> { - return this.onEach { logger.logInputChange(inputParamName, prettyPrint(it)) } - } - - /** - * Log a change in one of the **outputs** to the connectivity pipeline. - * - * @param prettyPrint an optional function to transform the value into a readable string. - * [toString] is used if no custom function is provided. - */ - fun <T> Flow<T>.logOutputChange( - logger: ConnectivityPipelineLogger, - outputParamName: String, - prettyPrint: (T) -> String = { it.toString() } - ): Flow<T> { - return this.onEach { logger.logOutputChange(outputParamName, prettyPrint(it)) } - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt new file mode 100644 index 000000000000..6f29e33b5a17 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.shared + +import android.net.Network +import android.net.NetworkCapabilities +import com.android.systemui.plugins.log.LogBuffer +import com.android.systemui.plugins.log.LogLevel + +/** Helper object for logs that are shared between wifi and mobile. */ +object LoggerHelper { + fun logOnCapabilitiesChanged( + buffer: LogBuffer, + tag: String, + network: Network, + networkCapabilities: NetworkCapabilities, + isDefaultNetworkCallback: Boolean, + ) { + buffer.log( + tag, + LogLevel.INFO, + { + bool1 = isDefaultNetworkCallback + int1 = network.getNetId() + str1 = networkCapabilities.toString() + }, + { "onCapabilitiesChanged[default=$bool1]: net=$int1 capabilities=$str1" } + ) + } + + fun logOnLost(buffer: LogBuffer, tag: String, network: Network) { + buffer.log(tag, LogLevel.INFO, { int1 = network.getNetId() }, { "onLost: net=$int1" }) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt index 45c6d466f7e0..5d9ba018822d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt @@ -26,8 +26,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dump.DumpManager import com.android.systemui.statusbar.phone.StatusBarIconController -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG +import com.android.systemui.statusbar.pipeline.shared.ConnectivityInputLogger import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots import com.android.systemui.tuner.TunerService @@ -45,59 +44,61 @@ import kotlinx.coroutines.flow.stateIn * types of connectivity (wifi, mobile, ethernet, etc.) */ interface ConnectivityRepository { - /** - * Observable for the current set of connectivity icons that should be force-hidden. - */ + /** Observable for the current set of connectivity icons that should be force-hidden. */ val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> } @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton -class ConnectivityRepositoryImpl @Inject constructor( +class ConnectivityRepositoryImpl +@Inject +constructor( private val connectivitySlots: ConnectivitySlots, context: Context, dumpManager: DumpManager, - logger: ConnectivityPipelineLogger, + logger: ConnectivityInputLogger, @Application scope: CoroutineScope, tunerService: TunerService, ) : ConnectivityRepository, Dumpable { init { - dumpManager.registerDumpable("${SB_LOGGING_TAG}Repository", this) + dumpManager.registerDumpable("ConnectivityRepository", this) } // The default set of hidden icons to use if we don't get any from [TunerService]. private val defaultHiddenIcons: Set<ConnectivitySlot> = - context.resources.getStringArray(DEFAULT_HIDDEN_ICONS_RESOURCE) - .asList() - .toSlotSet(connectivitySlots) + context.resources + .getStringArray(DEFAULT_HIDDEN_ICONS_RESOURCE) + .asList() + .toSlotSet(connectivitySlots) - override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> = conflatedCallbackFlow { - val callback = object : TunerService.Tunable { - override fun onTuningChanged(key: String, newHideList: String?) { - if (key != HIDDEN_ICONS_TUNABLE_KEY) { - return - } - logger.logInputChange("onTuningChanged", newHideList) + override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> = + conflatedCallbackFlow { + val callback = + object : TunerService.Tunable { + override fun onTuningChanged(key: String, newHideList: String?) { + if (key != HIDDEN_ICONS_TUNABLE_KEY) { + return + } + logger.logTuningChanged(newHideList) - val outputList = newHideList?.split(",")?.toSlotSet(connectivitySlots) - ?: defaultHiddenIcons - trySend(outputList) - } - } - tunerService.addTunable(callback, HIDDEN_ICONS_TUNABLE_KEY) + val outputList = + newHideList?.split(",")?.toSlotSet(connectivitySlots) + ?: defaultHiddenIcons + trySend(outputList) + } + } + tunerService.addTunable(callback, HIDDEN_ICONS_TUNABLE_KEY) - awaitClose { tunerService.removeTunable(callback) } - } - .stateIn( - scope, - started = SharingStarted.WhileSubscribed(), - initialValue = defaultHiddenIcons - ) + awaitClose { tunerService.removeTunable(callback) } + } + .stateIn( + scope, + started = SharingStarted.WhileSubscribed(), + initialValue = defaultHiddenIcons + ) override fun dump(pw: PrintWriter, args: Array<out String>) { - pw.apply { - println("defaultHiddenIcons=$defaultHiddenIcons") - } + pw.apply { println("defaultHiddenIcons=$defaultHiddenIcons") } } companion object { @@ -111,8 +112,7 @@ class ConnectivityRepositoryImpl @Inject constructor( private fun List<String>.toSlotSet( connectivitySlots: ConnectivitySlots ): Set<ConnectivitySlot> { - return this - .filter { it.isNotBlank() } + return this.filter { it.isNotBlank() } .mapNotNull { connectivitySlots.getSlotFromName(it) } .toSet() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt index ac4d55c3a29c..08c14e743bb6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.pipeline.wifi.data.repository import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import kotlinx.coroutines.flow.StateFlow /** Provides data related to the wifi state. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt index 2cb81c809716..e0e0ed795e4a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt @@ -23,9 +23,9 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.demomode.DemoMode import com.android.systemui.demomode.DemoModeController import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt index a19c3c3e86a6..a4fbc2c93647 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt @@ -19,9 +19,9 @@ package com.android.systemui.statusbar.pipeline.wifi.data.repository.demo import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepository.kt index 5d4a6664a19a..86a668a2e842 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepository.kt @@ -18,8 +18,8 @@ package com.android.systemui.statusbar.pipeline.wifi.data.repository.prod import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt index c45b420780b9..ee58160a7d3b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt @@ -39,13 +39,12 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.logDiffsForTable import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository +import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import java.util.concurrent.Executor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -58,6 +57,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.merge +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn /** Real implementation of [WifiRepository]. */ @@ -70,7 +70,7 @@ class WifiRepositoryImpl constructor( broadcastDispatcher: BroadcastDispatcher, connectivityManager: ConnectivityManager, - logger: ConnectivityPipelineLogger, + logger: WifiInputLogger, @WifiTableLog wifiTableLogBuffer: TableLogBuffer, @Main mainExecutor: Executor, @Application scope: CoroutineScope, @@ -80,7 +80,7 @@ constructor( private val wifiStateChangeEvents: Flow<Unit> = broadcastDispatcher .broadcastFlow(IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)) - .logInputChange(logger, "WIFI_STATE_CHANGED_ACTION intent") + .onEach { logger.logIntent("WIFI_STATE_CHANGED_ACTION") } private val wifiNetworkChangeEvents: MutableSharedFlow<Unit> = MutableSharedFlow(extraBufferCapacity = 1) @@ -173,11 +173,6 @@ constructor( networkCapabilities, wifiManager, ) - logger.logTransformation( - WIFI_NETWORK_CALLBACK_NAME, - oldValue = currentWifi, - newValue = wifiNetworkModel, - ) currentWifi = wifiNetworkModel trySend(wifiNetworkModel) } @@ -194,11 +189,6 @@ constructor( wifi.networkId == network.getNetId() ) { val newNetworkModel = WifiNetworkModel.Inactive - logger.logTransformation( - WIFI_NETWORK_CALLBACK_NAME, - oldValue = wifi, - newValue = newNetworkModel, - ) currentWifi = newNetworkModel trySend(newNetworkModel) } @@ -228,7 +218,7 @@ constructor( override val wifiActivity: StateFlow<DataActivityModel> = conflatedCallbackFlow { val callback = TrafficStateCallback { state -> - logger.logInputChange("onTrafficStateChange", prettyPrintActivity(state)) + logger.logActivity(prettyPrintActivity(state)) trySend(state.toWifiDataActivityModel()) } wifiManager.registerTrafficStateCallback(mainExecutor, callback) @@ -336,8 +326,6 @@ constructor( .addTransportType(TRANSPORT_CELLULAR) .build() - private const val WIFI_NETWORK_CALLBACK_NAME = "wifiNetworkModel" - private const val CARRIER_MERGED_INVALID_SUB_ID_REASON = "Wifi network was carrier merged but had invalid sub ID" } @@ -348,7 +336,7 @@ constructor( constructor( private val broadcastDispatcher: BroadcastDispatcher, private val connectivityManager: ConnectivityManager, - private val logger: ConnectivityPipelineLogger, + private val logger: WifiInputLogger, @WifiTableLog private val wifiTableLogBuffer: TableLogBuffer, @Main private val mainExecutor: Executor, @Application private val scope: CoroutineScope, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt index 86dcd18c643c..96ab074c6e56 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt @@ -21,8 +21,8 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow @@ -58,25 +58,29 @@ interface WifiInteractor { } @SysUISingleton -class WifiInteractorImpl @Inject constructor( +class WifiInteractorImpl +@Inject +constructor( connectivityRepository: ConnectivityRepository, wifiRepository: WifiRepository, ) : WifiInteractor { - override val ssid: Flow<String?> = wifiRepository.wifiNetwork.map { info -> - when (info) { - is WifiNetworkModel.Unavailable -> null - is WifiNetworkModel.Invalid -> null - is WifiNetworkModel.Inactive -> null - is WifiNetworkModel.CarrierMerged -> null - is WifiNetworkModel.Active -> when { - info.isPasspointAccessPoint || info.isOnlineSignUpForPasspointAccessPoint -> - info.passpointProviderFriendlyName - info.ssid != WifiManager.UNKNOWN_SSID -> info.ssid - else -> null + override val ssid: Flow<String?> = + wifiRepository.wifiNetwork.map { info -> + when (info) { + is WifiNetworkModel.Unavailable -> null + is WifiNetworkModel.Invalid -> null + is WifiNetworkModel.Inactive -> null + is WifiNetworkModel.CarrierMerged -> null + is WifiNetworkModel.Active -> + when { + info.isPasspointAccessPoint || info.isOnlineSignUpForPasspointAccessPoint -> + info.passpointProviderFriendlyName + info.ssid != WifiManager.UNKNOWN_SSID -> info.ssid + else -> null + } } } - } override val isEnabled: Flow<Boolean> = wifiRepository.isWifiEnabled @@ -86,7 +90,6 @@ class WifiInteractorImpl @Inject constructor( override val activity: StateFlow<DataActivityModel> = wifiRepository.wifiActivity - override val isForceHidden: Flow<Boolean> = connectivityRepository.forceHiddenSlots.map { - it.contains(ConnectivitySlot.WIFI) - } + override val isForceHidden: Flow<Boolean> = + connectivityRepository.forceHiddenSlots.map { it.contains(ConnectivitySlot.WIFI) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt index 4f7fe28c1e7c..8bea7728170f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt @@ -21,7 +21,6 @@ import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG import java.io.PrintWriter import javax.inject.Inject @@ -30,12 +29,14 @@ import javax.inject.Inject * logging purposes. */ @SysUISingleton -class WifiConstants @Inject constructor( - context: Context, - dumpManager: DumpManager, +class WifiConstants +@Inject +constructor( + context: Context, + dumpManager: DumpManager, ) : Dumpable { init { - dumpManager.registerDumpable("${SB_LOGGING_TAG}WifiConstants", this) + dumpManager.registerNormalDumpable("WifiConstants", this) } /** True if we should always show the wifi icon when wifi is enabled and false otherwise. */ @@ -43,8 +44,6 @@ class WifiConstants @Inject constructor( context.resources.getBoolean(R.bool.config_showWifiIndicatorWhenEnabled) override fun dump(pw: PrintWriter, args: Array<out String>) { - pw.apply { - println("alwaysShowIconIfEnabled=$alwaysShowIconIfEnabled") - } + pw.apply { println("alwaysShowIconIfEnabled=$alwaysShowIconIfEnabled") } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt new file mode 100644 index 000000000000..a32e47592355 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.wifi.shared + +import android.net.Network +import android.net.NetworkCapabilities +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.plugins.log.LogBuffer +import com.android.systemui.plugins.log.LogLevel +import com.android.systemui.statusbar.pipeline.dagger.WifiInputLog +import com.android.systemui.statusbar.pipeline.shared.LoggerHelper +import javax.inject.Inject + +/** + * Logger for all the wifi-related inputs (intents, callbacks, etc.) that the wifi repo receives. + */ +@SysUISingleton +class WifiInputLogger +@Inject +constructor( + @WifiInputLog val buffer: LogBuffer, +) { + fun logOnCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities, + isDefaultNetworkCallback: Boolean, + ) { + LoggerHelper.logOnCapabilitiesChanged( + buffer, + TAG, + network, + networkCapabilities, + isDefaultNetworkCallback, + ) + } + + fun logOnLost(network: Network) { + LoggerHelper.logOnLost(buffer, TAG, network) + } + + fun logIntent(intentName: String) { + buffer.log(TAG, LogLevel.DEBUG, { str1 = intentName }, { "Intent received: $str1" }) + } + + fun logActivity(activity: String) { + buffer.log(TAG, LogLevel.DEBUG, { str1 = activity }, { "Activity: $str1" }) + } +} + +private const val TAG = "WifiInputLog" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt index da2daf2c55ea..0923d7848d8c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.android.systemui.statusbar.pipeline.wifi.data.model +package com.android.systemui.statusbar.pipeline.wifi.shared.model -import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID +import android.telephony.SubscriptionManager import androidx.annotation.VisibleForTesting -import com.android.systemui.log.table.TableRowLogger import com.android.systemui.log.table.Diffable -import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS +import com.android.systemui.log.table.TableRowLogger +import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository /** Provides information about the current wifi network. */ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { @@ -57,9 +57,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { } } - /** - * A model representing that the wifi information we received was invalid in some way. - */ + /** A model representing that the wifi information we received was invalid in some way. */ data class Invalid( /** A description of why the wifi information was invalid. */ val invalidReason: String, @@ -142,21 +140,17 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { */ val subscriptionId: Int, - /** - * The signal level, guaranteed to be 0 <= level <= numberOfLevels. - */ + /** The signal level, guaranteed to be 0 <= level <= numberOfLevels. */ val level: Int, - /** - * The maximum possible level. - */ - val numberOfLevels: Int = DEFAULT_NUM_LEVELS, + /** The maximum possible level. */ + val numberOfLevels: Int = MobileConnectionRepository.DEFAULT_NUM_LEVELS, ) : WifiNetworkModel() { init { require(level in MIN_VALID_LEVEL..numberOfLevels) { "0 <= wifi level <= $numberOfLevels required; level was $level" } - require(subscriptionId != INVALID_SUBSCRIPTION_ID) { + require(subscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { "subscription ID cannot be invalid" } } @@ -208,9 +202,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { /** See [android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED]. */ val isValidated: Boolean = false, - /** - * The wifi signal level, guaranteed to be 0 <= level <= 4. - */ + /** The wifi signal level, guaranteed to be 0 <= level <= 4. */ val level: Int, /** See [android.net.wifi.WifiInfo.ssid]. */ @@ -255,8 +247,10 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { if (prevVal.isPasspointAccessPoint != isPasspointAccessPoint) { row.logChange(COL_PASSPOINT_ACCESS_POINT, isPasspointAccessPoint) } - if (prevVal.isOnlineSignUpForPasspointAccessPoint != - isOnlineSignUpForPasspointAccessPoint) { + if ( + prevVal.isOnlineSignUpForPasspointAccessPoint != + isOnlineSignUpForPasspointAccessPoint + ) { row.logChange(COL_ONLINE_SIGN_UP, isOnlineSignUpForPasspointAccessPoint) } if (prevVal.passpointProviderFriendlyName != passpointProviderFriendlyName) { @@ -281,29 +275,29 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { // Only include the passpoint-related values in the string if we have them. (Most // networks won't have them so they'll be mostly clutter.) val passpointString = - if (isPasspointAccessPoint || - isOnlineSignUpForPasspointAccessPoint || - passpointProviderFriendlyName != null) { + if ( + isPasspointAccessPoint || + isOnlineSignUpForPasspointAccessPoint || + passpointProviderFriendlyName != null + ) { ", isPasspointAp=$isPasspointAccessPoint, " + "isOnlineSignUpForPasspointAp=$isOnlineSignUpForPasspointAccessPoint, " + "passpointName=$passpointProviderFriendlyName" - } else { - "" - } + } else { + "" + } return "WifiNetworkModel.Active(networkId=$networkId, isValidated=$isValidated, " + "level=$level, ssid=$ssid$passpointString)" } companion object { - @VisibleForTesting - internal const val MAX_VALID_LEVEL = 4 + @VisibleForTesting internal const val MAX_VALID_LEVEL = 4 } } companion object { - @VisibleForTesting - internal const val MIN_VALID_LEVEL = 0 + @VisibleForTesting internal const val MIN_VALID_LEVEL = 0 } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt index 95431afb71bb..105723156b50 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt @@ -25,8 +25,6 @@ import com.android.systemui.R import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog -import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.logDiffsForTable import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS @@ -34,13 +32,13 @@ import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_IC import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel +import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel +import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow @@ -55,15 +53,12 @@ import kotlinx.coroutines.flow.stateIn /** * Models the UI state for the status bar wifi icon. * - * This class exposes three view models, one per status bar location: - * - [home] - * - [keyguard] - * - [qs] - * In order to get the UI state for the wifi icon, you must use one of those view models (whichever - * is correct for your location). + * This class exposes three view models, one per status bar location: [home], [keyguard], and [qs]. + * In order to get the UI state for the wifi icon, you must use one of those view models (whichever + * is correct for your location). * - * Internally, this class maintains the current state of the wifi icon and notifies those three - * view models of any changes. + * Internally, this class maintains the current state of the wifi icon and notifies those three view + * models of any changes. */ @SysUISingleton class WifiViewModel @@ -72,7 +67,6 @@ constructor( airplaneModeViewModel: AirplaneModeViewModel, connectivityConstants: ConnectivityConstants, private val context: Context, - logger: ConnectivityPipelineLogger, @WifiTableLog wifiTableLogBuffer: TableLogBuffer, interactor: WifiInteractor, @Application private val scope: CoroutineScope, @@ -85,12 +79,13 @@ constructor( is WifiNetworkModel.Unavailable -> WifiIcon.Hidden is WifiNetworkModel.Invalid -> WifiIcon.Hidden is WifiNetworkModel.CarrierMerged -> WifiIcon.Hidden - is WifiNetworkModel.Inactive -> WifiIcon.Visible( - res = WIFI_NO_NETWORK, - ContentDescription.Loaded( - "${context.getString(WIFI_NO_CONNECTION)},${context.getString(NO_INTERNET)}" + is WifiNetworkModel.Inactive -> + WifiIcon.Visible( + res = WIFI_NO_NETWORK, + ContentDescription.Loaded( + "${context.getString(WIFI_NO_CONNECTION)},${context.getString(NO_INTERNET)}" + ) ) - ) is WifiNetworkModel.Active -> { val levelDesc = context.getString(WIFI_CONNECTION_STRENGTH[this.level]) when { @@ -114,25 +109,25 @@ constructor( /** The wifi icon that should be displayed. */ private val wifiIcon: StateFlow<WifiIcon> = combine( - interactor.isEnabled, - interactor.isDefault, - interactor.isForceHidden, - interactor.wifiNetwork, - ) { isEnabled, isDefault, isForceHidden, wifiNetwork -> - if (!isEnabled || isForceHidden || wifiNetwork is WifiNetworkModel.CarrierMerged) { - return@combine WifiIcon.Hidden - } + interactor.isEnabled, + interactor.isDefault, + interactor.isForceHidden, + interactor.wifiNetwork, + ) { isEnabled, isDefault, isForceHidden, wifiNetwork -> + if (!isEnabled || isForceHidden || wifiNetwork is WifiNetworkModel.CarrierMerged) { + return@combine WifiIcon.Hidden + } - val icon = wifiNetwork.icon() + val icon = wifiNetwork.icon() - return@combine when { - isDefault -> icon - wifiConstants.alwaysShowIconIfEnabled -> icon - !connectivityConstants.hasDataCapabilities -> icon - wifiNetwork is WifiNetworkModel.Active && wifiNetwork.isValidated -> icon - else -> WifiIcon.Hidden + return@combine when { + isDefault -> icon + wifiConstants.alwaysShowIconIfEnabled -> icon + !connectivityConstants.hasDataCapabilities -> icon + wifiNetwork is WifiNetworkModel.Active && wifiNetwork.isValidated -> icon + else -> WifiIcon.Hidden + } } - } .logDiffsForTable( wifiTableLogBuffer, columnPrefix = "", @@ -145,36 +140,42 @@ constructor( ) /** The wifi activity status. Null if we shouldn't display the activity status. */ - private val activity: Flow<DataActivityModel?> = + private val activity: Flow<DataActivityModel> = run { + val default = DataActivityModel(hasActivityIn = false, hasActivityOut = false) if (!connectivityConstants.shouldShowActivityConfig) { - flowOf(null) - } else { - combine(interactor.activity, interactor.ssid) { activity, ssid -> - when (ssid) { - null -> null - else -> activity + flowOf(default) + } else { + combine(interactor.activity, interactor.ssid) { activity, ssid -> + when (ssid) { + null -> default + else -> activity + } } } - } - .distinctUntilChanged() - .logOutputChange(logger, "activity") - .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = null) + .distinctUntilChanged() + .logDiffsForTable( + wifiTableLogBuffer, + columnPrefix = "VM.activity", + initialValue = default, + ) + .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = default) + } private val isActivityInViewVisible: Flow<Boolean> = - activity - .map { it?.hasActivityIn == true } - .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false) + activity + .map { it.hasActivityIn } + .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false) private val isActivityOutViewVisible: Flow<Boolean> = - activity - .map { it?.hasActivityOut == true } - .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false) + activity + .map { it.hasActivityOut } + .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false) private val isActivityContainerVisible: Flow<Boolean> = - combine(isActivityInViewVisible, isActivityOutViewVisible) { activityIn, activityOut -> - activityIn || activityOut - } - .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false) + combine(isActivityInViewVisible, isActivityOutViewVisible) { activityIn, activityOut -> + activityIn || activityOut + } + .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false) // TODO(b/238425913): It isn't ideal for the wifi icon to need to know about whether the // airplane icon is visible. Instead, we should have a parent StatusBarSystemIconsViewModel diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java index 1ae1eae00651..8929e024c00d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java @@ -56,7 +56,7 @@ public interface KeyguardStateController extends CallbackController<Callback> { /** * Whether the bouncer (PIN/password entry) is currently visible. */ - boolean isBouncerShowing(); + boolean isPrimaryBouncerShowing(); /** * If swiping up will unlock without asking for a password. @@ -196,7 +196,7 @@ public interface KeyguardStateController extends CallbackController<Callback> { /** **/ default void notifyKeyguardState(boolean showing, boolean occluded) {} /** **/ - default void notifyBouncerShowing(boolean showing) {} + default void notifyPrimaryBouncerShowing(boolean showing) {} /** * Updates the keyguard state to reflect that it's in the process of being dismissed, either by @@ -244,7 +244,7 @@ public interface KeyguardStateController extends CallbackController<Callback> { /** * Called when the bouncer (PIN/password entry) is shown or hidden. */ - default void onBouncerShowingChanged() {} + default void onPrimaryBouncerShowingChanged() {} /** * Triggered when the device was just unlocked and the lock screen is being dismissed. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java index 9ad36fd58fe1..805368cc1f0a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java @@ -65,7 +65,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum private boolean mCanDismissLockScreen; private boolean mShowing; - private boolean mBouncerShowing; + private boolean mPrimaryBouncerShowing; private boolean mSecure; private boolean mOccluded; @@ -157,8 +157,8 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum } @Override - public boolean isBouncerShowing() { - return mBouncerShowing; + public boolean isPrimaryBouncerShowing() { + return mPrimaryBouncerShowing; } @Override @@ -339,11 +339,11 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum } @Override - public void notifyBouncerShowing(boolean showing) { - if (mBouncerShowing != showing) { - mBouncerShowing = showing; + public void notifyPrimaryBouncerShowing(boolean showing) { + if (mPrimaryBouncerShowing != showing) { + mPrimaryBouncerShowing = showing; - new ArrayList<>(mCallbacks).forEach(Callback::onBouncerShowingChanged); + new ArrayList<>(mCallbacks).forEach(Callback::onPrimaryBouncerShowingChanged); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt new file mode 100644 index 000000000000..2a18b8149637 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use mHost file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.systemui.statusbar.policy + +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.qs.tiles.AlarmTile +import com.android.systemui.qs.tiles.CameraToggleTile +import com.android.systemui.qs.tiles.DndTile +import com.android.systemui.qs.tiles.FlashlightTile +import com.android.systemui.qs.tiles.LocationTile +import com.android.systemui.qs.tiles.MicrophoneToggleTile +import com.android.systemui.qs.tiles.UiModeNightTile +import com.android.systemui.qs.tiles.WorkModeTile +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface PolicyModule { + + /** Inject DndTile into tileMap in QSModule */ + @Binds @IntoMap @StringKey(DndTile.TILE_SPEC) fun bindDndTile(dndTile: DndTile): QSTileImpl<*> + + /** Inject WorkModeTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(WorkModeTile.TILE_SPEC) + fun bindWorkModeTile(workModeTile: WorkModeTile): QSTileImpl<*> + + /** Inject FlashlightTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(FlashlightTile.TILE_SPEC) + fun bindFlashlightTile(flashlightTile: FlashlightTile): QSTileImpl<*> + + /** Inject LocationTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(LocationTile.TILE_SPEC) + fun bindLocationTile(locationTile: LocationTile): QSTileImpl<*> + + /** Inject CameraToggleTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(CameraToggleTile.TILE_SPEC) + fun bindCameraToggleTile(cameraToggleTile: CameraToggleTile): QSTileImpl<*> + + /** Inject MicrophoneToggleTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(MicrophoneToggleTile.TILE_SPEC) + fun bindMicrophoneToggleTile(microphoneToggleTile: MicrophoneToggleTile): QSTileImpl<*> + + /** Inject AlarmTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(AlarmTile.TILE_SPEC) + fun bindAlarmTile(alarmTile: AlarmTile): QSTileImpl<*> + + @Binds + @IntoMap + @StringKey(UiModeNightTile.TILE_SPEC) + fun bindUiModeNightTile(uiModeNightTile: UiModeNightTile): QSTileImpl<*> +} diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitorModule.kt b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitorModule.kt new file mode 100644 index 000000000000..c74e71f668f8 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitorModule.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util.leak + +import com.android.systemui.CoreStartable +import com.android.systemui.qs.tileimpl.QSTileImpl +import dagger.Binds +import dagger.Module +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface GarbageMonitorModule { + /** Inject into GarbageMonitor.Service. */ + @Binds + @IntoMap + @ClassKey(GarbageMonitor::class) + fun bindGarbageMonitorService(sysui: GarbageMonitor.Service): CoreStartable + + @Binds + @IntoMap + @StringKey(GarbageMonitor.MemoryTile.TILE_SPEC) + fun bindMemoryTile(memoryTile: GarbageMonitor.MemoryTile): QSTileImpl<*> +} diff --git a/packages/SystemUI/src/com/android/systemui/wallet/dagger/WalletModule.java b/packages/SystemUI/src/com/android/systemui/wallet/dagger/WalletModule.java index 2c901d285939..9429d8991090 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/dagger/WalletModule.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/dagger/WalletModule.java @@ -22,6 +22,8 @@ import android.service.quickaccesswallet.QuickAccessWalletClient; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.qs.tiles.QuickAccessWalletTile; import com.android.systemui.wallet.ui.WalletActivity; import java.util.concurrent.Executor; @@ -31,6 +33,7 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.ClassKey; import dagger.multibindings.IntoMap; +import dagger.multibindings.StringKey; /** @@ -52,4 +55,11 @@ public abstract class WalletModule { @Background Executor bgExecutor) { return QuickAccessWalletClient.create(context, bgExecutor); } + + /** */ + @Binds + @IntoMap + @StringKey(QuickAccessWalletTile.TILE_SPEC) + public abstract QSTileImpl<?> bindQuickAccessWalletTile( + QuickAccessWalletTile quickAccessWalletTile); } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt index e8d50ca4bc76..e84a975d84e2 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt @@ -24,13 +24,20 @@ import android.os.Handler import android.os.PowerManager import android.os.PowerManager.WAKE_REASON_BIOMETRIC import android.os.UserHandle -import android.provider.Settings +import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL +import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO +import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ERRORS +import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT +import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED +import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_WAKE +import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS +import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq -import com.android.systemui.util.settings.SecureSettings +import com.android.systemui.util.settings.FakeSettings import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before @@ -41,20 +48,12 @@ import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +import java.io.PrintWriter @SmallTest class ActiveUnlockConfigTest : SysuiTestCase() { - private val fakeWakeUri = Uri.Builder().appendPath("wake").build() - private val fakeUnlockIntentUri = Uri.Builder().appendPath("unlock-intent").build() - private val fakeBioFailUri = Uri.Builder().appendPath("bio-fail").build() - private val fakeFaceErrorsUri = Uri.Builder().appendPath("face-errors").build() - private val fakeFaceAcquiredUri = Uri.Builder().appendPath("face-acquired").build() - private val fakeUnlockIntentBioEnroll = Uri.Builder().appendPath("unlock-intent-bio").build() - private val fakeWakeupsConsideredUnlockIntents = - Uri.Builder().appendPath("wakeups-considered-unlock-intent").build() - @Mock - private lateinit var secureSettings: SecureSettings + private lateinit var secureSettings: FakeSettings @Mock private lateinit var contentResolver: ContentResolver @Mock @@ -63,33 +62,19 @@ class ActiveUnlockConfigTest : SysuiTestCase() { private lateinit var dumpManager: DumpManager @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor + @Mock private lateinit var mockPrintWriter: PrintWriter @Captor private lateinit var settingsObserverCaptor: ArgumentCaptor<ContentObserver> private lateinit var activeUnlockConfig: ActiveUnlockConfig + private var currentUser: Int = 0 @Before fun setUp() { MockitoAnnotations.initMocks(this) - - `when`(secureSettings.getUriFor(Settings.Secure.ACTIVE_UNLOCK_ON_WAKE)) - .thenReturn(fakeWakeUri) - `when`(secureSettings.getUriFor(Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT)) - .thenReturn(fakeUnlockIntentUri) - `when`(secureSettings.getUriFor(Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL)) - .thenReturn(fakeBioFailUri) - `when`(secureSettings.getUriFor(Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ERRORS)) - .thenReturn(fakeFaceErrorsUri) - `when`(secureSettings.getUriFor(Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO)) - .thenReturn(fakeFaceAcquiredUri) - `when`(secureSettings.getUriFor( - Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED)) - .thenReturn(fakeUnlockIntentBioEnroll) - `when`(secureSettings.getUriFor( - Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS)) - .thenReturn(fakeWakeupsConsideredUnlockIntents) - + currentUser = KeyguardUpdateMonitor.getCurrentUser() + secureSettings = FakeSettings() activeUnlockConfig = ActiveUnlockConfig( handler, secureSettings, @@ -105,8 +90,6 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Test fun onWakeupSettingChanged() { - verifyRegisterSettingObserver() - // GIVEN no active unlock settings enabled assertFalse( activeUnlockConfig.shouldAllowActiveUnlockFromOrigin( @@ -114,9 +97,8 @@ class ActiveUnlockConfigTest : SysuiTestCase() { ) // WHEN unlock on wake is allowed - `when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_WAKE, - 0, 0)).thenReturn(1) - updateSetting(fakeWakeUri) + secureSettings.putIntForUser(ACTIVE_UNLOCK_ON_WAKE, 1, currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_WAKE)) // THEN active unlock triggers allowed on: wake, unlock-intent, and biometric failure assertTrue( @@ -135,8 +117,6 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Test fun onUnlockIntentSettingChanged() { - verifyRegisterSettingObserver() - // GIVEN no active unlock settings enabled assertFalse( activeUnlockConfig.shouldAllowActiveUnlockFromOrigin( @@ -144,9 +124,8 @@ class ActiveUnlockConfigTest : SysuiTestCase() { ) // WHEN unlock on biometric failed is allowed - `when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT, - 0, 0)).thenReturn(1) - updateSetting(fakeUnlockIntentUri) + secureSettings.putIntForUser(ACTIVE_UNLOCK_ON_UNLOCK_INTENT, 1, currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_UNLOCK_INTENT)) // THEN active unlock triggers allowed on: biometric failure ONLY assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin( @@ -159,21 +138,19 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Test fun onBioFailSettingChanged() { - verifyRegisterSettingObserver() - // GIVEN no active unlock settings enabled and triggering unlock intent on biometric // enrollment setting is disabled (empty string is disabled, null would use the default) - `when`(secureSettings.getStringForUser( - Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED, - 0)).thenReturn("") - updateSetting(fakeUnlockIntentBioEnroll) + secureSettings.putStringForUser( + ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED, "", currentUser) + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED + )) assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin( ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL)) // WHEN unlock on biometric failed is allowed - `when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, - 0, 0)).thenReturn(1) - updateSetting(fakeBioFailUri) + secureSettings.putIntForUser(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, 1, currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL)) // THEN active unlock triggers allowed on: biometric failure ONLY assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin( @@ -186,17 +163,14 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Test fun faceErrorSettingsChanged() { - verifyRegisterSettingObserver() - // GIVEN unlock on biometric fail - `when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, - 0, 0)).thenReturn(1) - updateSetting(fakeBioFailUri) + secureSettings.putIntForUser(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, 1, currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL)) // WHEN face error timeout (3), allow trigger active unlock - `when`(secureSettings.getStringForUser(Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ERRORS, - 0)).thenReturn("3") - updateSetting(fakeFaceAcquiredUri) + secureSettings.putStringForUser( + ACTIVE_UNLOCK_ON_FACE_ERRORS, "3", currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_FACE_ERRORS)) // THEN active unlock triggers allowed on error TIMEOUT assertTrue(activeUnlockConfig.shouldRequestActiveUnlockOnFaceError( @@ -208,19 +182,17 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Test fun faceAcquiredSettingsChanged() { - verifyRegisterSettingObserver() - // GIVEN unlock on biometric fail - `when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, - 0, 0)).thenReturn(1) - updateSetting(fakeBioFailUri) + secureSettings.putStringForUser(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, "1", currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL)) // WHEN face acquiredMsg DARK_GLASSESand MOUTH_COVERING are allowed to trigger - `when`(secureSettings.getStringForUser(Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO, - 0)).thenReturn( + secureSettings.putStringForUser( + ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO, "${BiometricFaceConstants.FACE_ACQUIRED_MOUTH_COVERING_DETECTED}" + - "|${BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED}") - updateSetting(fakeFaceAcquiredUri) + "|${BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED}", + currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO)) // THEN active unlock triggers allowed on acquired messages DARK_GLASSES & MOUTH_COVERING assertTrue(activeUnlockConfig.shouldRequestActiveUnlockOnFaceAcquireInfo( @@ -236,23 +208,23 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Test fun triggerOnUnlockIntentWhenBiometricEnrolledNone() { - verifyRegisterSettingObserver() - // GIVEN unlock on biometric fail - `when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, - 0, 0)).thenReturn(1) - updateSetting(fakeBioFailUri) + secureSettings.putIntForUser(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, 1, currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL)) // GIVEN fingerprint and face are NOT enrolled activeUnlockConfig.keyguardUpdateMonitor = keyguardUpdateMonitor - `when`(keyguardUpdateMonitor.isFaceEnrolled()).thenReturn(false) + `when`(keyguardUpdateMonitor.isFaceEnrolled).thenReturn(false) `when`(keyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(0)).thenReturn(false) // WHEN unlock intent is allowed when NO biometrics are enrolled (0) - `when`(secureSettings.getStringForUser( - Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED, - 0)).thenReturn("${ActiveUnlockConfig.BiometricType.NONE.intValue}") - updateSetting(fakeUnlockIntentBioEnroll) + + secureSettings.putStringForUser( + ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED, + "${ActiveUnlockConfig.BiometricType.NONE.intValue}", currentUser) + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED + )) // THEN active unlock triggers allowed on unlock intent assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin( @@ -261,12 +233,9 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Test fun triggerOnUnlockIntentWhenBiometricEnrolledFingerprintOrFaceOnly() { - verifyRegisterSettingObserver() - // GIVEN unlock on biometric fail - `when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, - 0, 0)).thenReturn(1) - updateSetting(fakeBioFailUri) + secureSettings.putIntForUser(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL, 1, currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL)) // GIVEN fingerprint and face are both enrolled activeUnlockConfig.keyguardUpdateMonitor = keyguardUpdateMonitor @@ -275,12 +244,14 @@ class ActiveUnlockConfigTest : SysuiTestCase() { // WHEN unlock intent is allowed when ONLY fingerprint is enrolled or NO biometircs // are enrolled - `when`(secureSettings.getStringForUser( - Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED, - 0)).thenReturn( + secureSettings.putStringForUser( + ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED, "${ActiveUnlockConfig.BiometricType.ANY_FACE.intValue}" + - "|${ActiveUnlockConfig.BiometricType.ANY_FINGERPRINT.intValue}") - updateSetting(fakeUnlockIntentBioEnroll) + "|${ActiveUnlockConfig.BiometricType.ANY_FINGERPRINT.intValue}", + currentUser) + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED + )) // THEN active unlock triggers NOT allowed on unlock intent assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin( @@ -305,13 +276,12 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Test fun isWakeupConsideredUnlockIntent_singleValue() { - verifyRegisterSettingObserver() - // GIVEN lift is considered an unlock intent - `when`(secureSettings.getStringForUser( - Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, - 0)).thenReturn(PowerManager.WAKE_REASON_LIFT.toString()) - updateSetting(fakeWakeupsConsideredUnlockIntents) + secureSettings.putIntForUser( + ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, + PowerManager.WAKE_REASON_LIFT, + currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS)) // THEN only WAKE_REASON_LIFT is considered an unlock intent for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { @@ -325,17 +295,15 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Test fun isWakeupConsideredUnlockIntent_multiValue() { - verifyRegisterSettingObserver() - // GIVEN lift and tap are considered an unlock intent - `when`(secureSettings.getStringForUser( - Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, - 0)).thenReturn( + secureSettings.putStringForUser( + ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, PowerManager.WAKE_REASON_LIFT.toString() + "|" + - PowerManager.WAKE_REASON_TAP.toString() + PowerManager.WAKE_REASON_TAP.toString(), + currentUser ) - updateSetting(fakeWakeupsConsideredUnlockIntents) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS)) // THEN WAKE_REASON_LIFT and WAKE_REASON TAP are considered an unlock intent for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { @@ -346,34 +314,102 @@ class ActiveUnlockConfigTest : SysuiTestCase() { assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason)) } } - assertTrue(activeUnlockConfig.isWakeupConsideredUnlockIntent(PowerManager.WAKE_REASON_LIFT)) - assertTrue(activeUnlockConfig.isWakeupConsideredUnlockIntent(PowerManager.WAKE_REASON_TAP)) - assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent( - PowerManager.WAKE_REASON_UNFOLD_DEVICE)) } @Test fun isWakeupConsideredUnlockIntent_emptyValues() { + // GIVEN lift and tap are considered an unlock intent + secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, " ", + currentUser) + updateSetting(secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS)) + + // THEN no wake up gestures are considered an unlock intent + for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { + assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason)) + } + } + + @Test + fun isWakeupForceDismissKeyguard_singleValue() { + verifyRegisterSettingObserver() + + // GIVEN lift is considered an unlock intent + secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + PowerManager.WAKE_REASON_LIFT.toString(), currentUser) + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD + )) + + // THEN only WAKE_REASON_LIFT is considered an unlock intent + for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { + if (wakeReason == PowerManager.WAKE_REASON_LIFT) { + assertTrue(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) + } else { + assertFalse(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) + } + } + } + + @Test + fun isWakeupForceDismissKeyguard_emptyValues() { verifyRegisterSettingObserver() // GIVEN lift and tap are considered an unlock intent - `when`(secureSettings.getStringForUser( - Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, - 0)).thenReturn(" ") - updateSetting(fakeWakeupsConsideredUnlockIntents) + secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + " ", currentUser) + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD + )) // THEN no wake up gestures are considered an unlock intent for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { - assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason)) + assertFalse(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) } - assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent( - PowerManager.WAKE_REASON_LIFT)) - assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(PowerManager.WAKE_REASON_TAP)) - assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent( - PowerManager.WAKE_REASON_UNFOLD_DEVICE)) + } + + @Test + fun isWakeupForceDismissKeyguard_multiValue() { + verifyRegisterSettingObserver() + + // GIVEN lift and tap are considered an unlock intent + secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + PowerManager.WAKE_REASON_LIFT.toString() + + "|" + + PowerManager.WAKE_REASON_TAP.toString(), + currentUser + ) + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD + )) + + // THEN WAKE_REASON_LIFT and WAKE_REASON TAP are considered an unlock intent + for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { + if (wakeReason == PowerManager.WAKE_REASON_LIFT || + wakeReason == PowerManager.WAKE_REASON_TAP) { + assertTrue(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) + } else { + assertFalse(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) + } + } + } + + @Test + fun dump_onUnlockIntentWhenBiometricEnrolled_invalidNum_noArrayOutOfBoundsException() { + // GIVEN an invalid input (-1) + secureSettings.putStringForUser(ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED, + "-1", currentUser) + + // WHEN the setting updates + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED + )) + + // THEN no exception thrown + activeUnlockConfig.dump(mockPrintWriter, emptyArray()) } private fun updateSetting(uri: Uri) { + verifyRegisterSettingObserver() settingsObserverCaptor.value.onChange( false, listOf(uri), @@ -383,13 +419,17 @@ class ActiveUnlockConfigTest : SysuiTestCase() { } private fun verifyRegisterSettingObserver() { - verifyRegisterSettingObserver(fakeWakeUri) - verifyRegisterSettingObserver(fakeUnlockIntentUri) - verifyRegisterSettingObserver(fakeBioFailUri) - verifyRegisterSettingObserver(fakeFaceErrorsUri) - verifyRegisterSettingObserver(fakeFaceAcquiredUri) - verifyRegisterSettingObserver(fakeUnlockIntentBioEnroll) - verifyRegisterSettingObserver(fakeWakeupsConsideredUnlockIntents) + verifyRegisterSettingObserver(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_WAKE)) + verifyRegisterSettingObserver(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_UNLOCK_INTENT)) + verifyRegisterSettingObserver(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL)) + verifyRegisterSettingObserver(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_FACE_ERRORS)) + verifyRegisterSettingObserver(secureSettings.getUriFor(ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO)) + verifyRegisterSettingObserver(secureSettings.getUriFor( + ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED + )) + verifyRegisterSettingObserver(secureSettings.getUriFor( + ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS + )) } private fun verifyRegisterSettingObserver(uri: Uri) { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt index f7fec80ded98..480b8f972b4a 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt @@ -23,6 +23,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.flags.FeatureFlags +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor @@ -85,6 +86,7 @@ class ClockEventControllerTest : SysuiTestCase() { @Mock private lateinit var transitionRepository: KeyguardTransitionRepository @Mock private lateinit var commandQueue: CommandQueue private lateinit var repository: FakeKeyguardRepository + private lateinit var bouncerRepository: FakeKeyguardBouncerRepository @Mock private lateinit var smallLogBuffer: LogBuffer @Mock private lateinit var largeLogBuffer: LogBuffer private lateinit var underTest: ClockEventController @@ -103,11 +105,15 @@ class ClockEventControllerTest : SysuiTestCase() { whenever(largeClockEvents.tickRate).thenReturn(ClockTickRate.PER_MINUTE) repository = FakeKeyguardRepository() + bouncerRepository = FakeKeyguardBouncerRepository() underTest = ClockEventController( - KeyguardInteractor(repository = repository, - commandQueue = commandQueue, - featureFlags = featureFlags), + KeyguardInteractor( + repository = repository, + commandQueue = commandQueue, + featureFlags = featureFlags, + bouncerRepository = bouncerRepository, + ), KeyguardTransitionInteractor(repository = transitionRepository), broadcastDispatcher, batteryController, diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index ccc4e4af4ac8..a5f90f8441b2 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java @@ -241,7 +241,7 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { mController.init(); verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture()); - listenerArgumentCaptor.getValue().onClockChanged(); + listenerArgumentCaptor.getValue().onCurrentClockChanged(); verify(mView, times(2)).setClock(mClockController, StatusBarState.SHADE); verify(mClockEventController, times(2)).setClock(mClockController); } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java deleted file mode 100644 index 4021652295c1..000000000000 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2018 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.keyguard; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.media.AudioManager; -import android.telephony.TelephonyManager; -import android.test.suitebuilder.annotation.SmallTest; -import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper; -import android.testing.TestableResources; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import com.android.systemui.R; -import com.android.systemui.SysuiTestCase; -import com.android.systemui.plugins.ActivityStarter.OnDismissAction; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper -public class KeyguardHostViewControllerTest extends SysuiTestCase { - @Mock - private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - - private KeyguardHostView mKeyguardHostView; - @Mock - private AudioManager mAudioManager; - @Mock - private TelephonyManager mTelephonyManager; - @Mock - private ViewMediatorCallback mViewMediatorCallback; - @Mock - KeyguardSecurityContainerController.Factory mKeyguardSecurityContainerControllerFactory; - @Mock - private KeyguardSecurityContainerController mKeyguardSecurityContainerController; - - @Rule - public MockitoRule mMockitoRule = MockitoJUnit.rule(); - - private TestableResources mTestableResources; - private KeyguardHostViewController mKeyguardHostViewController; - - @Before - public void setup() { - mTestableResources = mContext.getOrCreateTestableResources(); - - mKeyguardHostView = new KeyguardHostView(mContext); - - // Explicitly disable one handed keyguard. - mTestableResources.addOverride( - R.bool.can_use_one_handed_bouncer, false); - - when(mKeyguardSecurityContainerControllerFactory.create(any( - KeyguardSecurityContainer.SecurityCallback.class))) - .thenReturn(mKeyguardSecurityContainerController); - mKeyguardHostViewController = new KeyguardHostViewController( - mKeyguardHostView, mKeyguardUpdateMonitor, mAudioManager, mTelephonyManager, - mViewMediatorCallback, mKeyguardSecurityContainerControllerFactory); - } - - @Test - public void testHasDismissActions() { - assertFalse("Action not set yet", mKeyguardHostViewController.hasDismissActions()); - mKeyguardHostViewController.setOnDismissAction(mock(OnDismissAction.class), - null /* cancelAction */); - assertTrue("Action should exist", mKeyguardHostViewController.hasDismissActions()); - } - - @Test - public void testOnStartingToHide() { - mKeyguardHostViewController.onStartingToHide(); - verify(mKeyguardSecurityContainerController).onStartingToHide(); - } - - @Test - public void onBouncerVisible_propagatesToKeyguardSecurityContainerController() { - mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.VISIBLE); - mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.INVISIBLE); - - InOrder order = inOrder(mKeyguardSecurityContainerController); - order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(View.VISIBLE); - order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged( - View.INVISIBLE); - } - - @Test - public void testGravityReappliedOnConfigurationChange() { - FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); - mKeyguardHostView.setLayoutParams(lp); - - // Set initial gravity - mTestableResources.addOverride(R.integer.keyguard_host_view_gravity, - Gravity.CENTER); - - // Kick off the initial pass... - mKeyguardHostViewController.init(); - assertEquals( - ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity, - Gravity.CENTER); - - // Now simulate a config change - mTestableResources.addOverride(R.integer.keyguard_host_view_gravity, - Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); - - mKeyguardHostViewController.updateResources(); - assertEquals( - ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity, - Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); - } - - @Test - public void testGravityUsesOneHandGravityWhenApplicable() { - FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); - mKeyguardHostView.setLayoutParams(lp); - - mTestableResources.addOverride( - R.integer.keyguard_host_view_gravity, - Gravity.CENTER); - mTestableResources.addOverride( - R.integer.keyguard_host_view_one_handed_gravity, - Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); - - // Start disabled. - mTestableResources.addOverride( - R.bool.can_use_one_handed_bouncer, false); - - mKeyguardHostViewController.init(); - assertEquals( - ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity, - Gravity.CENTER); - - // And enable - mTestableResources.addOverride( - R.bool.can_use_one_handed_bouncer, true); - - mKeyguardHostViewController.updateResources(); - assertEquals( - ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity, - Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); - } - - @Test - public void testUpdateKeyguardPositionDelegatesToSecurityContainer() { - mKeyguardHostViewController.updateKeyguardPosition(1.0f); - - verify(mKeyguardSecurityContainerController).updateKeyguardPosition(1.0f); - } -} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java index 075ef9df9664..bffbe17fb2eb 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java @@ -23,12 +23,17 @@ import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED; import static com.google.common.truth.Truth.assertThat; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -38,13 +43,19 @@ import static org.mockito.Mockito.when; import android.content.res.Configuration; import android.content.res.Resources; +import android.hardware.biometrics.BiometricOverlayConstants; import android.hardware.biometrics.BiometricSourceType; +import android.media.AudioManager; +import android.telephony.TelephonyManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.testing.TestableResources; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.WindowInsetsController; +import android.widget.FrameLayout; import androidx.test.filters.SmallTest; @@ -60,6 +71,7 @@ import com.android.systemui.classifier.FalsingA11yDelegate; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.log.SessionTracker; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -71,6 +83,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatcher; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; @@ -108,8 +121,6 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Mock private KeyguardInputViewController mInputViewController; @Mock - private KeyguardSecurityContainer.SecurityCallback mSecurityCallback; - @Mock private WindowInsetsController mWindowInsetsController; @Mock private KeyguardSecurityViewFlipper mSecurityViewFlipper; @@ -126,8 +137,6 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Mock private EmergencyButtonController mEmergencyButtonController; @Mock - private Resources mResources; - @Mock private FalsingCollector mFalsingCollector; @Mock private FalsingManager mFalsingManager; @@ -147,6 +156,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock; @Mock private FalsingA11yDelegate mFalsingA11yDelegate; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private ViewMediatorCallback mViewMediatorCallback; + @Mock + private AudioManager mAudioManager; @Captor private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback; @@ -158,18 +173,25 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { private KeyguardSecurityContainerController mKeyguardSecurityContainerController; private KeyguardPasswordViewController mKeyguardPasswordViewController; private KeyguardPasswordView mKeyguardPasswordView; + private TestableResources mTestableResources; @Before public void setup() { mConfiguration = new Configuration(); mConfiguration.setToDefaults(); // Defaults to ORIENTATION_UNDEFINED. + mTestableResources = mContext.getOrCreateTestableResources(); - when(mResources.getConfiguration()).thenReturn(mConfiguration); when(mView.getContext()).thenReturn(mContext); - when(mView.getResources()).thenReturn(mResources); + when(mView.getResources()).thenReturn(mContext.getResources()); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(/* width= */ 0, /* height= */ + 0); + lp.gravity = 0; + when(mView.getLayoutParams()).thenReturn(lp); when(mAdminSecondaryLockScreenControllerFactory.create(any(KeyguardSecurityCallback.class))) .thenReturn(mAdminSecondaryLockScreenController); when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController); + when(mKeyguardSecurityViewFlipperController.getSecurityView(any(SecurityMode.class), + any(KeyguardSecurityCallback.class))).thenReturn(mInputViewController); mKeyguardPasswordView = spy((KeyguardPasswordView) LayoutInflater.from(mContext).inflate( R.layout.keyguard_password_view, null)); when(mKeyguardPasswordView.getRootView()).thenReturn(mSecurityViewFlipper); @@ -178,20 +200,21 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class))) .thenReturn(mKeyguardMessageAreaController); when(mKeyguardPasswordView.getWindowInsetsController()).thenReturn(mWindowInsetsController); + when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(SecurityMode.PIN); mKeyguardPasswordViewController = new KeyguardPasswordViewController( (KeyguardPasswordView) mKeyguardPasswordView, mKeyguardUpdateMonitor, SecurityMode.Password, mLockPatternUtils, null, mKeyguardMessageAreaControllerFactory, null, null, mEmergencyButtonController, null, mock(Resources.class), null, mKeyguardViewController); - mKeyguardSecurityContainerController = new KeyguardSecurityContainerController.Factory( + mKeyguardSecurityContainerController = new KeyguardSecurityContainerController( mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils, mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger, mKeyguardStateController, mKeyguardSecurityViewFlipperController, mConfigurationController, mFalsingCollector, mFalsingManager, mUserSwitcherController, mFeatureFlags, mGlobalSettings, - mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate).create( - mSecurityCallback); + mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate, + mTelephonyManager, mViewMediatorCallback, mAudioManager); } @Test @@ -243,7 +266,8 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { eq(mFalsingA11yDelegate)); // Update rotation. Should trigger update - mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE; + mTestableResources.getResources().getConfiguration().orientation = + Configuration.ORIENTATION_LANDSCAPE; mKeyguardSecurityContainerController.updateResources(); verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager), @@ -277,7 +301,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Test public void showSecurityScreen_oneHandedMode_flagDisabled_noOneHandedMode() { - when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(false); + mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, false); when(mKeyguardSecurityViewFlipperController.getSecurityView( eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class))) .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController); @@ -291,7 +315,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Test public void showSecurityScreen_oneHandedMode_flagEnabled_oneHandedMode() { - when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true); + mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true); when(mKeyguardSecurityViewFlipperController.getSecurityView( eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class))) .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController); @@ -305,7 +329,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Test public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() { - when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true); + mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true); setupGetSecurityView(); mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password); @@ -350,7 +374,8 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER); + verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD); verify(mSideFpsController, never()).hide(any()); } @@ -363,7 +388,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any()); + verify(mSideFpsController, never()).show(any(), anyInt()); } @Test @@ -375,7 +400,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any()); + verify(mSideFpsController, never()).show(any(), anyInt()); } @Test @@ -387,7 +412,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any()); + verify(mSideFpsController, never()).show(any(), anyInt()); } @Test @@ -395,13 +420,14 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { setupGetSecurityView(); setupConditionsToEnableSideFpsHint(); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER); + verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD); reset(mSideFpsController); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any()); + verify(mSideFpsController, never()).show(any(), anyInt()); } @Test @@ -416,13 +442,14 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { setupGetSecurityView(); setupConditionsToEnableSideFpsHint(); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER); + verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD); reset(mSideFpsController); mKeyguardSecurityContainerController.onStartingToHide(); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any()); + verify(mSideFpsController, never()).show(any(), anyInt()); } @Test @@ -430,13 +457,14 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { setupGetSecurityView(); setupConditionsToEnableSideFpsHint(); mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER); + verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD); reset(mSideFpsController); mKeyguardSecurityContainerController.onPause(); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any()); + verify(mSideFpsController, never()).show(any(), anyInt()); } @Test @@ -448,7 +476,8 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { mKeyguardSecurityContainerController.onResume(0); - verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER); + verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD); verify(mSideFpsController, never()).hide(any()); } @@ -463,7 +492,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { mKeyguardSecurityContainerController.onResume(0); verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any()); + verify(mSideFpsController, never()).show(any(), anyInt()); } @Test @@ -482,7 +511,9 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { SecurityMode.SimPin); // THEN the next security method of PIN is set, and the keyguard is not marked as done - verify(mSecurityCallback, never()).finish(anyBoolean(), anyInt()); + + verify(mViewMediatorCallback, never()).keyguardDonePending(anyBoolean(), anyInt()); + verify(mViewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt()); assertThat(mKeyguardSecurityContainerController.getCurrentSecurityMode()) .isEqualTo(SecurityMode.PIN); } @@ -556,17 +587,19 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { } @Test - public void onDensityorFontScaleChanged() { + public void onDensityOrFontScaleChanged() { ArgumentCaptor<ConfigurationController.ConfigurationListener> configurationListenerArgumentCaptor = ArgumentCaptor.forClass( ConfigurationController.ConfigurationListener.class); mKeyguardSecurityContainerController.onViewAttached(); verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture()); + clearInvocations(mKeyguardSecurityViewFlipperController); + configurationListenerArgumentCaptor.getValue().onDensityOrFontScaleChanged(); verify(mView).onDensityOrFontScaleChanged(); verify(mKeyguardSecurityViewFlipperController).clearViews(); - verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class), + verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN), any(KeyguardSecurityCallback.class)); } @@ -577,11 +610,13 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { ConfigurationController.ConfigurationListener.class); mKeyguardSecurityContainerController.onViewAttached(); verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture()); + clearInvocations(mKeyguardSecurityViewFlipperController); + configurationListenerArgumentCaptor.getValue().onThemeChanged(); verify(mView).reloadColors(); verify(mKeyguardSecurityViewFlipperController).clearViews(); - verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class), + verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN), any(KeyguardSecurityCallback.class)); } @@ -592,10 +627,94 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { ConfigurationController.ConfigurationListener.class); mKeyguardSecurityContainerController.onViewAttached(); verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture()); + clearInvocations(mKeyguardSecurityViewFlipperController); + configurationListenerArgumentCaptor.getValue().onUiModeChanged(); verify(mView).reloadColors(); verify(mKeyguardSecurityViewFlipperController).clearViews(); + verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN), + any(KeyguardSecurityCallback.class)); + } + + @Test + public void testHasDismissActions() { + assertFalse("Action not set yet", mKeyguardSecurityContainerController.hasDismissActions()); + mKeyguardSecurityContainerController.setOnDismissAction(mock( + ActivityStarter.OnDismissAction.class), + null /* cancelAction */); + assertTrue("Action should exist", mKeyguardSecurityContainerController.hasDismissActions()); + } + + @Test + public void testOnStartingToHide() { + mKeyguardSecurityContainerController.onStartingToHide(); + verify(mInputViewController).onStartingToHide(); + } + + @Test + public void testGravityReappliedOnConfigurationChange() { + // Set initial gravity + mTestableResources.addOverride(R.integer.keyguard_host_view_gravity, + Gravity.CENTER); + + // Kick off the initial pass... + mKeyguardSecurityContainerController.onInit(); + verify(mView).setLayoutParams(argThat( + (ArgumentMatcher<FrameLayout.LayoutParams>) argument -> + argument.gravity == Gravity.CENTER)); + clearInvocations(mView); + + // Now simulate a config change + mTestableResources.addOverride(R.integer.keyguard_host_view_gravity, + Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); + + mKeyguardSecurityContainerController.updateResources(); + verify(mView).setLayoutParams(argThat( + (ArgumentMatcher<FrameLayout.LayoutParams>) argument -> + argument.gravity == (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM))); + } + + @Test + public void testGravityUsesOneHandGravityWhenApplicable() { + mTestableResources.addOverride( + R.integer.keyguard_host_view_gravity, + Gravity.CENTER); + mTestableResources.addOverride( + R.integer.keyguard_host_view_one_handed_gravity, + Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); + + // Start disabled. + mTestableResources.addOverride( + R.bool.can_use_one_handed_bouncer, false); + + mKeyguardSecurityContainerController.onInit(); + verify(mView).setLayoutParams(argThat( + (ArgumentMatcher<FrameLayout.LayoutParams>) argument -> + argument.gravity == Gravity.CENTER)); + clearInvocations(mView); + + // And enable + mTestableResources.addOverride( + R.bool.can_use_one_handed_bouncer, true); + + mKeyguardSecurityContainerController.updateResources(); + verify(mView).setLayoutParams(argThat( + (ArgumentMatcher<FrameLayout.LayoutParams>) argument -> + argument.gravity == (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM))); + } + + @Test + public void testUpdateKeyguardPositionDelegatesToSecurityContainer() { + mKeyguardSecurityContainerController.updateKeyguardPosition(1.0f); + verify(mView).updatePositionByTouchX(1.0f); + } + + + @Test + public void testReinflateViewFlipper() { + mKeyguardSecurityContainerController.reinflateViewFlipper(); + verify(mKeyguardSecurityViewFlipperController).clearViews(); verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class), any(KeyguardSecurityCallback.class)); } @@ -625,7 +744,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { } private void setSideFpsHintEnabledFromResources(boolean enabled) { - when(mResources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)).thenReturn( + mTestableResources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, enabled); } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 853d8ed251c9..6b80494a0c30 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -900,6 +900,25 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test + public void noFpListeningWhenKeyguardIsOccluded_unlessAlternateBouncerShowing() { + // GIVEN device is awake but occluded + mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON); + mKeyguardUpdateMonitor.setKeyguardShowing(false, true); + + // THEN fingerprint shouldn't listen + assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isFalse(); + verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(), + anyInt(), anyInt()); + + // WHEN alternate bouncer is shown + mKeyguardUpdateMonitor.setAlternateBouncerShowing(true); + + // THEN make sure FP listening begins + verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(), + anyInt()); + } + + @Test public void testTriesToAuthenticate_whenTrustOnAgentKeyguard_ifBypass() { mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON); mTestableLooper.processAllMessages(); @@ -2374,6 +2393,56 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); } + @Test + public void unfoldWakeup_requestActiveUnlock_forceDismissKeyguard() + throws RemoteException { + // GIVEN shouldTriggerActiveUnlock + keyguardIsVisible(); + when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true); + + // GIVEN active unlock triggers on wakeup + when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin( + ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE)) + .thenReturn(true); + + // GIVEN an unfold should force dismiss the keyguard + when(mActiveUnlockConfig.shouldWakeupForceDismissKeyguard( + PowerManager.WAKE_REASON_UNFOLD_DEVICE)).thenReturn(true); + + // WHEN device wakes up from an unfold + mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNFOLD_DEVICE); + mTestableLooper.processAllMessages(); + + // THEN request unlock with a keyguard dismissal + verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()), + eq(true)); + } + + @Test + public void unfoldWakeup_requestActiveUnlock_noDismissKeyguard() + throws RemoteException { + // GIVEN shouldTriggerActiveUnlock on wake from UNFOLD_DEVICE + keyguardIsVisible(); + when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true); + + // GIVEN active unlock triggers on wakeup + when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin( + ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE)) + .thenReturn(true); + + // GIVEN an unfold should NOT force dismiss the keyguard + when(mActiveUnlockConfig.shouldWakeupForceDismissKeyguard( + PowerManager.WAKE_REASON_UNFOLD_DEVICE)).thenReturn(false); + + // WHEN device wakes up from an unfold + mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNFOLD_DEVICE); + mTestableLooper.processAllMessages(); + + // THEN request unlock WITHOUT a keyguard dismissal + verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()), + eq(false)); + } + private void userDeviceLockDown() { when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false); when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId)) diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java index 3d0d0367a4c7..456702b65091 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java @@ -43,6 +43,7 @@ import com.android.systemui.biometrics.AuthRippleController; import com.android.systemui.doze.util.BurnInHelperKt; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository; import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository; import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; @@ -159,9 +160,12 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase { mAuthRippleController, mResources, new KeyguardTransitionInteractor(mTransitionRepository), - new KeyguardInteractor(new FakeKeyguardRepository(), + new KeyguardInteractor( + new FakeKeyguardRepository(), mCommandQueue, - mFeatureFlags), + mFeatureFlags, + new FakeKeyguardBouncerRepository() + ), mFeatureFlags ); } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java index b69491ed1096..b7d005957700 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java @@ -284,4 +284,26 @@ public class LockIconViewControllerTest extends LockIconViewControllerBaseTest { // THEN the lock icon is shown verify(mLockIconView).setContentDescription(LOCKED_LABEL); } + + @Test + public void lockIconShows_afterUnlockStateChanges() { + // GIVEN lock icon controller is initialized and view is attached + init(/* useMigrationFlag= */false); + captureKeyguardStateCallback(); + captureKeyguardUpdateMonitorCallback(); + + // GIVEN user has unlocked with a biometric auth (ie: face auth) + // and biometric running state changes + when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(true); + mKeyguardUpdateMonitorCallback.onBiometricRunningStateChanged(false, + BiometricSourceType.FACE); + reset(mLockIconView); + + // WHEN the unlocked state changes + when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(false); + mKeyguardStateCallback.onUnlockedChanged(); + + // THEN the lock icon is shown + verify(mLockIconView).setContentDescription(LOCKED_LABEL); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt index 41beada11fa9..612e55732bc1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt @@ -267,6 +267,17 @@ class SideFpsControllerTest : SysuiTestCase() { } @Test + fun testShowOverlayReasonWhenDisplayChanged() = testWithDisplay { + sideFpsController.show(SideFpsUiRequestSource.AUTO_SHOW, REASON_AUTH_KEYGUARD) + executor.runAllReady() + sideFpsController.orientationListener.onDisplayChanged(1 /* displayId */) + executor.runAllReady() + + assertThat(sideFpsController.orientationReasonListener.reason) + .isEqualTo(REASON_AUTH_KEYGUARD) + } + + @Test fun testShowsAndHides() = testWithDisplay { overlayController.show(SENSOR_ID, REASON_UNKNOWN) executor.runAllReady() diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java index 7177919909f9..fd6e31ba3bee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java @@ -51,6 +51,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import java.util.ArrayList; + import javax.inject.Provider; @SmallTest @@ -195,6 +197,33 @@ public class ClipboardListenerTest extends SysuiTestCase { } @Test + public void test_nullClipData_showsNothing() { + when(mClipboardManager.getPrimaryClip()).thenReturn(null); + + mClipboardListener.start(); + mClipboardListener.onPrimaryClipChanged(); + + verifyZeroInteractions(mUiEventLogger); + verifyZeroInteractions(mClipboardToast); + verifyZeroInteractions(mOverlayControllerProvider); + } + + @Test + public void test_emptyClipData_showsToast() { + ClipDescription description = new ClipDescription("Test", new String[0]); + ClipData noItems = new ClipData(description, new ArrayList<>()); + when(mClipboardManager.getPrimaryClip()).thenReturn(noItems); + + mClipboardListener.start(); + mClipboardListener.onPrimaryClipChanged(); + + verify(mUiEventLogger, times(1)).log( + ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN, 0, mSampleSource); + verify(mClipboardToast, times(1)).showCopiedToast(); + verifyZeroInteractions(mOverlayControllerProvider); + } + + @Test public void test_minimizedLayoutFlagOff_usesLegacy() { mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardModelTest.kt index faef35e7bfcb..c0dada4725b8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardModelTest.kt @@ -53,25 +53,15 @@ class ClipboardModelTest : SysuiTestCase() { } @Test - fun test_nullClipData() { - val model = ClipboardModel.fromClipData(mContext, mClipboardUtils, null, "test source") - assertNull(model.clipData) - assertEquals("test source", model.source) - assertEquals(ClipboardModel.Type.OTHER, model.type) - assertNull(model.item) - assertFalse(model.isSensitive) - assertFalse(model.isRemote) - assertNull(model.loadThumbnail(mContext)) - } - - @Test fun test_textClipData() { val source = "test source" val model = ClipboardModel.fromClipData(mContext, mClipboardUtils, mSampleClipData, source) assertEquals(mSampleClipData, model.clipData) assertEquals(source, model.source) assertEquals(ClipboardModel.Type.TEXT, model.type) - assertEquals(mSampleClipData.getItemAt(0), model.item) + assertEquals(mSampleClipData.getItemAt(0).text, model.text) + assertEquals(mSampleClipData.getItemAt(0).textLinks, model.textLinks) + assertEquals(mSampleClipData.getItemAt(0).uri, model.uri) assertFalse(model.isSensitive) assertFalse(model.isRemote) assertNull(model.loadThumbnail(mContext)) @@ -84,7 +74,7 @@ class ClipboardModelTest : SysuiTestCase() { b.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true) description.extras = b val data = ClipData(description, mSampleClipData.getItemAt(0)) - val (_, _, _, _, sensitive) = + val (_, _, _, _, _, _, sensitive) = ClipboardModel.fromClipData(mContext, mClipboardUtils, data, "") assertTrue(sensitive) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java index 0ac26676a9c7..2099281d694a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java @@ -139,29 +139,35 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { } @Test - public void test_setClipData_nullData_legacy() { - ClipData clipData = null; + public void test_setClipData_invalidImageData_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); + ClipData clipData = new ClipData("", new String[]{"image/png"}, + new ClipData.Item(Uri.parse(""))); + mOverlayController.setClipDataLegacy(clipData, ""); verify(mClipboardOverlayView, times(1)).showDefaultTextPreview(); - verify(mClipboardOverlayView, times(0)).showShareChip(); + verify(mClipboardOverlayView, times(1)).showShareChip(); verify(mClipboardOverlayView, times(1)).getEnterAnimation(); } @Test - public void test_setClipData_invalidImageData_legacy() { - ClipData clipData = new ClipData("", new String[]{"image/png"}, + public void test_setClipData_nonImageUri_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); + ClipData clipData = new ClipData("", new String[]{"resource/png"}, new ClipData.Item(Uri.parse(""))); mOverlayController.setClipDataLegacy(clipData, ""); verify(mClipboardOverlayView, times(1)).showDefaultTextPreview(); - verify(mClipboardOverlayView, times(0)).showShareChip(); + verify(mClipboardOverlayView, times(1)).showShareChip(); verify(mClipboardOverlayView, times(1)).getEnterAnimation(); } @Test public void test_setClipData_textData_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); + mOverlayController.setClipDataLegacy(mSampleClipData, ""); verify(mClipboardOverlayView, times(1)).showTextPreview("Test Item", false); @@ -171,6 +177,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_setClipData_sensitiveTextData_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); + ClipDescription description = mSampleClipData.getDescription(); PersistableBundle b = new PersistableBundle(); b.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true); @@ -185,6 +193,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_setClipData_repeatedCalls_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); when(mAnimator.isRunning()).thenReturn(true); mOverlayController.setClipDataLegacy(mSampleClipData, ""); @@ -195,6 +204,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_viewCallbacks_onShareTapped_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); mOverlayController.setClipDataLegacy(mSampleClipData, ""); mCallbacks.onShareButtonTapped(); @@ -205,6 +215,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_viewCallbacks_onDismissTapped_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); mOverlayController.setClipDataLegacy(mSampleClipData, ""); mCallbacks.onDismissButtonTapped(); @@ -215,6 +226,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_multipleDismissals_dismissesOnce_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); + mCallbacks.onSwipeDismissInitiated(mAnimator); mCallbacks.onDismissButtonTapped(); mCallbacks.onSwipeDismissInitiated(mAnimator); @@ -226,6 +239,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_remoteCopy_withFlagOn_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true); when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(true); @@ -236,6 +250,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_remoteCopy_withFlagOff_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(true); mOverlayController.setClipDataLegacy(mSampleClipData, ""); @@ -245,6 +260,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_nonRemoteCopy_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true); when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(false); @@ -255,6 +271,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_logsUseLastClipSource_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); + mOverlayController.setClipDataLegacy(mSampleClipData, "first.package"); mCallbacks.onDismissButtonTapped(); mOverlayController.setClipDataLegacy(mSampleClipData, "second.package"); @@ -267,6 +285,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { @Test public void test_logOnClipboardActionsShown_legacy() { + mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false); ClipData.Item item = mSampleClipData.getItemAt(0); item.setTextLinks(Mockito.mock(TextLinks.class)); mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true); @@ -292,24 +311,26 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { // start of refactored setClipData tests @Test - public void test_setClipData_nullData() { - ClipData clipData = null; + public void test_setClipData_invalidImageData() { + ClipData clipData = new ClipData("", new String[]{"image/png"}, + new ClipData.Item(Uri.parse(""))); + mOverlayController.setClipData(clipData, ""); verify(mClipboardOverlayView, times(1)).showDefaultTextPreview(); - verify(mClipboardOverlayView, times(0)).showShareChip(); + verify(mClipboardOverlayView, times(1)).showShareChip(); verify(mClipboardOverlayView, times(1)).getEnterAnimation(); } @Test - public void test_setClipData_invalidImageData() { - ClipData clipData = new ClipData("", new String[]{"image/png"}, + public void test_setClipData_nonImageUri() { + ClipData clipData = new ClipData("", new String[]{"resource/png"}, new ClipData.Item(Uri.parse(""))); mOverlayController.setClipData(clipData, ""); verify(mClipboardOverlayView, times(1)).showDefaultTextPreview(); - verify(mClipboardOverlayView, times(0)).showShareChip(); + verify(mClipboardOverlayView, times(1)).showShareChip(); verify(mClipboardOverlayView, times(1)).getEnterAnimation(); } @@ -425,7 +446,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true); when(mClipboardUtils.isRemoteCopy(any(Context.class), any(ClipData.class), anyString())) .thenReturn(true); - when(mClipboardUtils.getAction(any(ClipData.Item.class), anyString())) + when(mClipboardUtils.getAction(any(CharSequence.class), any(TextLinks.class), anyString())) .thenReturn(Optional.of(Mockito.mock(RemoteAction.class))); when(mClipboardOverlayView.post(any(Runnable.class))).thenAnswer(new Answer<Object>() { @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt index 4439586497ff..228374671ad4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt @@ -18,9 +18,13 @@ package com.android.systemui.controls.controller import android.app.job.JobParameters import android.content.Context +import android.os.PersistableBundle import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapper.DeletionJobService.Companion.USER +import com.android.systemui.util.mockito.whenever +import java.util.concurrent.TimeUnit import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -28,18 +32,15 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -import java.util.concurrent.TimeUnit @SmallTest @RunWith(AndroidTestingRunner::class) class DeletionJobServiceTest : SysuiTestCase() { - @Mock - private lateinit var context: Context + @Mock private lateinit var context: Context private lateinit var service: AuxiliaryPersistenceWrapper.DeletionJobService @@ -53,6 +54,10 @@ class DeletionJobServiceTest : SysuiTestCase() { @Test fun testOnStartJob() { + val bundle = PersistableBundle().also { it.putInt(USER, 0) } + val params = mock(JobParameters::class.java) + whenever(params.getExtras()).thenReturn(bundle) + // false means job is terminated assertFalse(service.onStartJob(mock(JobParameters::class.java))) verify(context).deleteFile(AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME) @@ -67,13 +72,17 @@ class DeletionJobServiceTest : SysuiTestCase() { @Test fun testJobHasRightParameters() { val userId = 10 - `when`(context.userId).thenReturn(userId) - `when`(context.packageName).thenReturn(mContext.packageName) + whenever(context.userId).thenReturn(userId) + whenever(context.packageName).thenReturn(mContext.packageName) - val jobInfo = AuxiliaryPersistenceWrapper.DeletionJobService.getJobForContext(context) + val jobInfo = + AuxiliaryPersistenceWrapper.DeletionJobService.getJobForContext(context, userId) assertEquals( - AuxiliaryPersistenceWrapper.DeletionJobService.DELETE_FILE_JOB_ID + userId, jobInfo.id) + AuxiliaryPersistenceWrapper.DeletionJobService.DELETE_FILE_JOB_ID + userId, + jobInfo.id + ) assertTrue(jobInfo.isPersisted) + assertEquals(userId, jobInfo.getExtras().getInt(USER)) assertEquals(TimeUnit.DAYS.toMillis(7), jobInfo.minLatencyMillis) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt new file mode 100644 index 000000000000..de0e5113571f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.flags + +import android.os.PowerManager +import android.test.suitebuilder.annotation.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.util.settings.FakeSettings +import com.android.systemui.util.time.FakeSystemClock +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.mockito.ArgumentCaptor +import org.mockito.Mock +import org.mockito.Mockito.anyLong +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +class RestartDozeListenerTest : SysuiTestCase() { + + lateinit var restartDozeListener: RestartDozeListener + + val settings = FakeSettings() + @Mock lateinit var statusBarStateController: StatusBarStateController + @Mock lateinit var powerManager: PowerManager + val clock = FakeSystemClock() + lateinit var listener: StatusBarStateController.StateListener + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + restartDozeListener = + RestartDozeListener(settings, statusBarStateController, powerManager, clock) + + val captor = ArgumentCaptor.forClass(StatusBarStateController.StateListener::class.java) + restartDozeListener.init() + verify(statusBarStateController).addCallback(captor.capture()) + listener = captor.value + } + + @Test + fun testStoreDreamState_onDreamingStarted() { + listener.onDreamingChanged(true) + assertThat(settings.getBool(RestartDozeListener.RESTART_NAP_KEY)).isTrue() + } + + @Test + fun testStoreDreamState_onDreamingStopped() { + listener.onDreamingChanged(false) + assertThat(settings.getBool(RestartDozeListener.RESTART_NAP_KEY)).isFalse() + } + + @Test + fun testRestoreDreamState_dreamingShouldStart() { + settings.putBool(RestartDozeListener.RESTART_NAP_KEY, true) + restartDozeListener.maybeRestartSleep() + verify(powerManager).wakeUp(clock.uptimeMillis()) + verify(powerManager).goToSleep(clock.uptimeMillis()) + } + + @Test + fun testRestoreDreamState_dreamingShouldNot() { + settings.putBool(RestartDozeListener.RESTART_NAP_KEY, false) + restartDozeListener.maybeRestartSleep() + verify(powerManager, never()).wakeUp(anyLong()) + verify(powerManager, never()).goToSleep(anyLong()) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt index 4ebf9741ce22..a12315b63fa7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt @@ -50,10 +50,10 @@ class ServerFlagReaderImplTest : SysuiTestCase() { @Test fun testChange_alertsListener() { - val flag = ReleasedFlag(1, "1", "test") + val flag = ReleasedFlag(1, "flag_1", "test") serverFlagReader.listenForChanges(listOf(flag), changeListener) - deviceConfig.setProperty(NAMESPACE, "flag_override_1", "1", false) + deviceConfig.setProperty(NAMESPACE, "flag_1", "1", false) executor.runAllReady() verify(changeListener).onChange(flag) diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt index 4415033061d4..15a454b3a24e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt @@ -39,6 +39,7 @@ import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffor import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor @@ -172,6 +173,7 @@ class CustomizationProviderTest : SysuiTestCase() { repository = FakeKeyguardRepository(), commandQueue = commandQueue, featureFlags = featureFlags, + bouncerRepository = FakeKeyguardBouncerRepository(), ), registry = mock(), lockPatternUtils = lockPatternUtils, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt index db18ba61c578..5bb8367432fc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt @@ -18,15 +18,19 @@ package com.android.systemui.keyguard.data.quickaffordance import android.app.StatusBarManager +import android.app.admin.DevicePolicyManager import android.content.Context import android.content.pm.PackageManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.camera.CameraGestureHelper +import com.android.systemui.settings.UserTracker import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Before @@ -44,21 +48,28 @@ class CameraQuickAffordanceConfigTest : SysuiTestCase() { @Mock private lateinit var cameraGestureHelper: CameraGestureHelper @Mock private lateinit var context: Context @Mock private lateinit var packageManager: PackageManager + @Mock private lateinit var userTracker: UserTracker + @Mock private lateinit var devicePolicyManager: DevicePolicyManager private lateinit var underTest: CameraQuickAffordanceConfig + private lateinit var testScope: TestScope @Before fun setUp() { MockitoAnnotations.initMocks(this) - setLaunchable(true) + setLaunchable() + val testDispatcher = StandardTestDispatcher() + testScope = TestScope(testDispatcher) underTest = CameraQuickAffordanceConfig( context, packageManager, - ) { - cameraGestureHelper - } + { cameraGestureHelper }, + userTracker, + devicePolicyManager, + testDispatcher, + ) } @Test @@ -73,23 +84,57 @@ class CameraQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun `getPickerScreenState - default when launchable`() = runTest { - setLaunchable(true) + fun `getPickerScreenState - default when launchable`() = + testScope.runTest { + setLaunchable(true) - Truth.assertThat(underTest.getPickerScreenState()) - .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java) - } + Truth.assertThat(underTest.getPickerScreenState()) + .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java) + } @Test - fun `getPickerScreenState - unavailable when not launchable`() = runTest { - setLaunchable(false) + fun `getPickerScreenState - unavailable when camera app not installed`() = + testScope.runTest { + setLaunchable(isCameraAppInstalled = false) - Truth.assertThat(underTest.getPickerScreenState()) - .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice) - } + Truth.assertThat(underTest.getPickerScreenState()) + .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice) + } + + @Test + fun `getPickerScreenState - unavailable when camera disabled by admin`() = + testScope.runTest { + setLaunchable(isCameraDisabledByDeviceAdmin = true) + + Truth.assertThat(underTest.getPickerScreenState()) + .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice) + } + + @Test + fun `getPickerScreenState - unavailable when secure camera disabled by admin`() = + testScope.runTest { + setLaunchable(isSecureCameraDisabledByDeviceAdmin = true) + + Truth.assertThat(underTest.getPickerScreenState()) + .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice) + } - private fun setLaunchable(isLaunchable: Boolean) { + private fun setLaunchable( + isCameraAppInstalled: Boolean = true, + isCameraDisabledByDeviceAdmin: Boolean = false, + isSecureCameraDisabledByDeviceAdmin: Boolean = false, + ) { whenever(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) - .thenReturn(isLaunchable) + .thenReturn(isCameraAppInstalled) + whenever(devicePolicyManager.getCameraDisabled(null, userTracker.userId)) + .thenReturn(isCameraDisabledByDeviceAdmin) + whenever(devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId)) + .thenReturn( + if (isSecureCameraDisabledByDeviceAdmin) { + DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA + } else { + 0 + } + ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt index 5bd86bd0f49b..f1b9c5f0fff8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.keyguard.data.quickaffordance +import android.app.admin.DevicePolicyManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.ActivityIntentHelper @@ -24,11 +25,14 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.camera.CameraIntentsWrapper import com.android.systemui.coroutines.collectLastValue import com.android.systemui.settings.FakeUserTracker +import com.android.systemui.settings.UserTracker import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -44,59 +48,94 @@ import org.mockito.MockitoAnnotations class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() { @Mock private lateinit var activityIntentHelper: ActivityIntentHelper + @Mock private lateinit var devicePolicyManager: DevicePolicyManager private lateinit var underTest: VideoCameraQuickAffordanceConfig + private lateinit var userTracker: UserTracker + private lateinit var testScope: TestScope @Before fun setUp() { MockitoAnnotations.initMocks(this) + val testDispatcher = StandardTestDispatcher() + testScope = TestScope(testDispatcher) + userTracker = FakeUserTracker() underTest = VideoCameraQuickAffordanceConfig( context = context, cameraIntents = CameraIntentsWrapper(context), activityIntentHelper = activityIntentHelper, - userTracker = FakeUserTracker(), + userTracker = userTracker, + devicePolicyManager = devicePolicyManager, + backgroundDispatcher = testDispatcher, ) } @Test - fun `lockScreenState - visible when launchable`() = runTest { - setLaunchable(true) + fun `lockScreenState - visible when launchable`() = + testScope.runTest { + setLaunchable() - val lockScreenState = collectLastValue(underTest.lockScreenState) + val lockScreenState = collectLastValue(underTest.lockScreenState) - assertThat(lockScreenState()) - .isInstanceOf(KeyguardQuickAffordanceConfig.LockScreenState.Visible::class.java) - } + assertThat(lockScreenState()) + .isInstanceOf(KeyguardQuickAffordanceConfig.LockScreenState.Visible::class.java) + } @Test - fun `lockScreenState - hidden when not launchable`() = runTest { - setLaunchable(false) + fun `lockScreenState - hidden when app not installed on device`() = + testScope.runTest { + setLaunchable(isVideoCameraAppInstalled = false) - val lockScreenState = collectLastValue(underTest.lockScreenState) + val lockScreenState = collectLastValue(underTest.lockScreenState) - assertThat(lockScreenState()) - .isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) - } + assertThat(lockScreenState()) + .isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) + } @Test - fun `getPickerScreenState - default when launchable`() = runTest { - setLaunchable(true) + fun `lockScreenState - hidden when camera disabled by admin`() = + testScope.runTest { + setLaunchable(isCameraDisabledByAdmin = true) - assertThat(underTest.getPickerScreenState()) - .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java) - } + val lockScreenState = collectLastValue(underTest.lockScreenState) + + assertThat(lockScreenState()) + .isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) + } @Test - fun `getPickerScreenState - unavailable when not launchable`() = runTest { - setLaunchable(false) + fun `getPickerScreenState - default when launchable`() = + testScope.runTest { + setLaunchable() - assertThat(underTest.getPickerScreenState()) - .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice) - } + assertThat(underTest.getPickerScreenState()) + .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java) + } - private fun setLaunchable(isLaunchable: Boolean) { + @Test + fun `getPickerScreenState - unavailable when app not installed on device`() = + testScope.runTest { + setLaunchable(isVideoCameraAppInstalled = false) + + assertThat(underTest.getPickerScreenState()) + .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice) + } + + @Test + fun `getPickerScreenState - unavailable when camera disabled by admin`() = + testScope.runTest { + setLaunchable(isCameraDisabledByAdmin = true) + + assertThat(underTest.getPickerScreenState()) + .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice) + } + + private fun setLaunchable( + isVideoCameraAppInstalled: Boolean = true, + isCameraDisabledByAdmin: Boolean = false, + ) { whenever( activityIntentHelper.getTargetActivityInfo( any(), @@ -105,11 +144,13 @@ class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() { ) ) .thenReturn( - if (isLaunchable) { + if (isVideoCameraAppInstalled) { mock() } else { null } ) + whenever(devicePolicyManager.getCameraDisabled(null, userTracker.userId)) + .thenReturn(isCameraDisabledByAdmin) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt index 8bb6a85ff34b..0469e77ca991 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt @@ -324,29 +324,6 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { } @Test - fun isBouncerShowing() = - runTest(UnconfinedTestDispatcher()) { - whenever(keyguardStateController.isBouncerShowing).thenReturn(false) - var latest: Boolean? = null - val job = underTest.isBouncerShowing.onEach { latest = it }.launchIn(this) - - assertThat(latest).isFalse() - - val captor = argumentCaptor<KeyguardStateController.Callback>() - verify(keyguardStateController).addCallback(captor.capture()) - - whenever(keyguardStateController.isBouncerShowing).thenReturn(true) - captor.value.onBouncerShowingChanged() - assertThat(latest).isTrue() - - whenever(keyguardStateController.isBouncerShowing).thenReturn(false) - captor.value.onBouncerShowingChanged() - assertThat(latest).isFalse() - - job.cancel() - } - - @Test fun isKeyguardGoingAway() = runTest(UnconfinedTestDispatcher()) { whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(false) diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt index 7ded354c92cc..18e80ea40c5c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt @@ -130,7 +130,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() { givenCanShowAlternateBouncer() assertTrue(underTest.show()) - assertTrue(bouncerRepository.isAlternateBouncerVisible.value) + assertTrue(bouncerRepository.alternateBouncerVisible.value) } @Test @@ -138,7 +138,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() { givenCannotShowAlternateBouncer() assertFalse(underTest.show()) - assertFalse(bouncerRepository.isAlternateBouncerVisible.value) + assertFalse(bouncerRepository.alternateBouncerVisible.value) } @Test @@ -146,7 +146,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() { bouncerRepository.setAlternateVisible(true) assertTrue(underTest.hide()) - assertFalse(bouncerRepository.isAlternateBouncerVisible.value) + assertFalse(bouncerRepository.alternateBouncerVisible.value) } @Test @@ -154,7 +154,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() { bouncerRepository.setAlternateVisible(false) assertFalse(underTest.hide()) - assertFalse(bouncerRepository.isAlternateBouncerVisible.value) + assertFalse(bouncerRepository.alternateBouncerVisible.value) } private fun givenCanShowAlternateBouncer() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt index 7d4861bdcb98..153439e4fe07 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt @@ -25,6 +25,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel import com.android.systemui.settings.DisplayTracker @@ -38,7 +39,6 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.mock -import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest @@ -50,6 +50,7 @@ class KeyguardInteractorTest : SysuiTestCase() { private lateinit var underTest: KeyguardInteractor private lateinit var repository: FakeKeyguardRepository + private lateinit var bouncerRepository: FakeKeyguardBouncerRepository @Before fun setUp() { @@ -58,7 +59,14 @@ class KeyguardInteractorTest : SysuiTestCase() { commandQueue = FakeCommandQueue(mock(Context::class.java), mock(DisplayTracker::class.java)) testScope = TestScope() repository = FakeKeyguardRepository() - underTest = KeyguardInteractor(repository, commandQueue, featureFlags) + bouncerRepository = FakeKeyguardBouncerRepository() + underTest = + KeyguardInteractor( + repository, + commandQueue, + featureFlags, + bouncerRepository, + ) } @Test @@ -137,7 +145,7 @@ class KeyguardInteractorTest : SysuiTestCase() { repository.setKeyguardOccluded(true) assertThat(secureCameraActive()).isTrue() - repository.setBouncerShowing(true) + bouncerRepository.setPrimaryVisible(true) assertThat(secureCameraActive()).isFalse() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt index 240af7bcac02..23e06ec181c0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt @@ -36,6 +36,7 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceRegistry @@ -298,6 +299,7 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { repository = FakeKeyguardRepository(), commandQueue = commandQueue, featureFlags = featureFlags, + bouncerRepository = FakeKeyguardBouncerRepository(), ), registry = FakeKeyguardQuickAffordanceRegistry( 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 ec708578a990..1b8c6273e2d8 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 @@ -36,6 +36,7 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel @@ -159,7 +160,8 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { KeyguardInteractor( repository = repository, commandQueue = commandQueue, - featureFlags = featureFlags + featureFlags = featureFlags, + bouncerRepository = FakeKeyguardBouncerRepository(), ), registry = FakeKeyguardQuickAffordanceRegistry( diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index 46e4679893b8..ae7a928cdb2c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -22,7 +22,9 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.animation.Interpolators import com.android.systemui.flags.FakeFeatureFlags +import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositoryImpl @@ -65,6 +67,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { private lateinit var testScope: TestScope private lateinit var keyguardRepository: FakeKeyguardRepository + private lateinit var bouncerRepository: FakeKeyguardBouncerRepository private lateinit var shadeRepository: ShadeRepository // Used to issue real transition steps for test input @@ -81,6 +84,10 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { private lateinit var fromOccludedTransitionInteractor: FromOccludedTransitionInteractor private lateinit var fromGoneTransitionInteractor: FromGoneTransitionInteractor private lateinit var fromAodTransitionInteractor: FromAodTransitionInteractor + private lateinit var fromAlternateBouncerTransitionInteractor: + FromAlternateBouncerTransitionInteractor + private lateinit var fromPrimaryBouncerTransitionInteractor: + FromPrimaryBouncerTransitionInteractor @Before fun setUp() { @@ -88,6 +95,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { testScope = TestScope() keyguardRepository = FakeKeyguardRepository() + bouncerRepository = FakeKeyguardBouncerRepository() shadeRepository = FakeShadeRepository() /* Used to issue full transition steps, to better simulate a real device */ @@ -98,8 +106,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromLockscreenTransitionInteractor = FromLockscreenTransitionInteractor( scope = testScope, - keyguardInteractor = - KeyguardInteractor(keyguardRepository, commandQueue, featureFlags), + keyguardInteractor = createKeyguardInteractor(featureFlags), shadeRepository = shadeRepository, keyguardTransitionRepository = mockTransitionRepository, keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository), @@ -109,8 +116,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromDreamingTransitionInteractor = FromDreamingTransitionInteractor( scope = testScope, - keyguardInteractor = - KeyguardInteractor(keyguardRepository, commandQueue, featureFlags), + keyguardInteractor = createKeyguardInteractor(featureFlags), keyguardTransitionRepository = mockTransitionRepository, keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository), ) @@ -119,8 +125,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromAodTransitionInteractor = FromAodTransitionInteractor( scope = testScope, - keyguardInteractor = - KeyguardInteractor(keyguardRepository, commandQueue, featureFlags), + keyguardInteractor = createKeyguardInteractor(featureFlags), keyguardTransitionRepository = mockTransitionRepository, keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository), ) @@ -129,8 +134,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromGoneTransitionInteractor = FromGoneTransitionInteractor( scope = testScope, - keyguardInteractor = - KeyguardInteractor(keyguardRepository, commandQueue, featureFlags), + keyguardInteractor = createKeyguardInteractor(featureFlags), keyguardTransitionRepository = mockTransitionRepository, keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository), ) @@ -139,8 +143,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromDozingTransitionInteractor = FromDozingTransitionInteractor( scope = testScope, - keyguardInteractor = - KeyguardInteractor(keyguardRepository, commandQueue, featureFlags), + keyguardInteractor = createKeyguardInteractor(featureFlags), keyguardTransitionRepository = mockTransitionRepository, keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository), ) @@ -149,12 +152,29 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromOccludedTransitionInteractor = FromOccludedTransitionInteractor( scope = testScope, - keyguardInteractor = - KeyguardInteractor(keyguardRepository, commandQueue, featureFlags), + keyguardInteractor = createKeyguardInteractor(featureFlags), keyguardTransitionRepository = mockTransitionRepository, keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository), ) fromOccludedTransitionInteractor.start() + + fromAlternateBouncerTransitionInteractor = + FromAlternateBouncerTransitionInteractor( + scope = testScope, + keyguardInteractor = createKeyguardInteractor(featureFlags), + keyguardTransitionRepository = mockTransitionRepository, + keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository), + ) + fromAlternateBouncerTransitionInteractor.start() + + fromPrimaryBouncerTransitionInteractor = + FromPrimaryBouncerTransitionInteractor( + scope = testScope, + keyguardInteractor = createKeyguardInteractor(featureFlags), + keyguardTransitionRepository = mockTransitionRepository, + keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository), + ) + fromPrimaryBouncerTransitionInteractor.start() } @Test @@ -256,7 +276,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test - fun `LOCKSCREEN to BOUNCER via bouncer showing call`() = + fun `LOCKSCREEN to PRIMARY_BOUNCER via bouncer showing call`() = testScope.runTest { // GIVEN a device that has at least woken up keyguardRepository.setWakefulnessModel(startingToWake()) @@ -278,18 +298,18 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { ) runCurrent() - // WHEN the bouncer is set to show - keyguardRepository.setBouncerShowing(true) + // WHEN the primary bouncer is set to show + bouncerRepository.setPrimaryVisible(true) runCurrent() val info = withArgCaptor<TransitionInfo> { verify(mockTransitionRepository).startTransition(capture()) } - // THEN a transition to BOUNCER should occur + // THEN a transition to PRIMARY_BOUNCER should occur assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor") assertThat(info.from).isEqualTo(KeyguardState.LOCKSCREEN) - assertThat(info.to).isEqualTo(KeyguardState.BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.PRIMARY_BOUNCER) assertThat(info.animator).isNotNull() coroutineContext.cancelChildren() @@ -695,6 +715,297 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { coroutineContext.cancelChildren() } + @Test + fun `ALTERNATE_BOUNCER to PRIMARY_BOUNCER`() = + testScope.runTest { + // GIVEN a prior transition has run to ALTERNATE_BOUNCER + runner.startTransition( + testScope, + TransitionInfo( + ownerName = "", + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.ALTERNATE_BOUNCER, + animator = + ValueAnimator().apply { + duration = 10 + interpolator = Interpolators.LINEAR + }, + ) + ) + runCurrent() + reset(mockTransitionRepository) + + // WHEN the alternateBouncer stops showing and then the primary bouncer shows + bouncerRepository.setPrimaryVisible(true) + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(mockTransitionRepository).startTransition(capture()) + } + // THEN a transition to PRIMARY_BOUNCER should occur + assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.ALTERNATE_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.PRIMARY_BOUNCER) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun `ALTERNATE_BOUNCER to AOD`() = + testScope.runTest { + // GIVEN a prior transition has run to ALTERNATE_BOUNCER + bouncerRepository.setAlternateVisible(true) + runner.startTransition( + testScope, + TransitionInfo( + ownerName = "", + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.ALTERNATE_BOUNCER, + animator = + ValueAnimator().apply { + duration = 10 + interpolator = Interpolators.LINEAR + }, + ) + ) + runCurrent() + reset(mockTransitionRepository) + + // GIVEN the primary bouncer isn't showing, aod available and starting to sleep + bouncerRepository.setPrimaryVisible(false) + keyguardRepository.setAodAvailable(true) + keyguardRepository.setWakefulnessModel(startingToSleep()) + + // WHEN the alternateBouncer stops showing + bouncerRepository.setAlternateVisible(false) + advanceUntilIdle() + + val info = + withArgCaptor<TransitionInfo> { + verify(mockTransitionRepository).startTransition(capture()) + } + // THEN a transition to AOD should occur + assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.ALTERNATE_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.AOD) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun `ALTERNATE_BOUNCER to DOZING`() = + testScope.runTest { + // GIVEN a prior transition has run to ALTERNATE_BOUNCER + bouncerRepository.setAlternateVisible(true) + runner.startTransition( + testScope, + TransitionInfo( + ownerName = "", + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.ALTERNATE_BOUNCER, + animator = + ValueAnimator().apply { + duration = 10 + interpolator = Interpolators.LINEAR + }, + ) + ) + runCurrent() + reset(mockTransitionRepository) + + // GIVEN the primary bouncer isn't showing, aod not available and starting to sleep + // to sleep + bouncerRepository.setPrimaryVisible(false) + keyguardRepository.setAodAvailable(false) + keyguardRepository.setWakefulnessModel(startingToSleep()) + + // WHEN the alternateBouncer stops showing + bouncerRepository.setAlternateVisible(false) + advanceUntilIdle() + + val info = + withArgCaptor<TransitionInfo> { + verify(mockTransitionRepository).startTransition(capture()) + } + // THEN a transition to DOZING should occur + assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.ALTERNATE_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.DOZING) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun `ALTERNATE_BOUNCER to LOCKSCREEN`() = + testScope.runTest { + // GIVEN a prior transition has run to ALTERNATE_BOUNCER + bouncerRepository.setAlternateVisible(true) + runner.startTransition( + testScope, + TransitionInfo( + ownerName = "", + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.ALTERNATE_BOUNCER, + animator = + ValueAnimator().apply { + duration = 10 + interpolator = Interpolators.LINEAR + }, + ) + ) + runCurrent() + reset(mockTransitionRepository) + + // GIVEN the primary bouncer isn't showing and device not sleeping + bouncerRepository.setPrimaryVisible(false) + keyguardRepository.setWakefulnessModel(startingToWake()) + + // WHEN the alternateBouncer stops showing + bouncerRepository.setAlternateVisible(false) + advanceUntilIdle() + + val info = + withArgCaptor<TransitionInfo> { + verify(mockTransitionRepository).startTransition(capture()) + } + // THEN a transition to LOCKSCREEN should occur + assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.ALTERNATE_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun `PRIMARY_BOUNCER to AOD`() = + testScope.runTest { + // GIVEN a prior transition has run to PRIMARY_BOUNCER + bouncerRepository.setPrimaryVisible(true) + runner.startTransition( + testScope, + TransitionInfo( + ownerName = "", + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.PRIMARY_BOUNCER, + animator = + ValueAnimator().apply { + duration = 10 + interpolator = Interpolators.LINEAR + }, + ) + ) + runCurrent() + reset(mockTransitionRepository) + + // GIVEN aod available and starting to sleep + keyguardRepository.setAodAvailable(true) + keyguardRepository.setWakefulnessModel(startingToSleep()) + + // WHEN the primaryBouncer stops showing + bouncerRepository.setPrimaryVisible(false) + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(mockTransitionRepository).startTransition(capture()) + } + // THEN a transition to AOD should occur + assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.PRIMARY_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.AOD) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun `PRIMARY_BOUNCER to DOZING`() = + testScope.runTest { + // GIVEN a prior transition has run to PRIMARY_BOUNCER + bouncerRepository.setPrimaryVisible(true) + runner.startTransition( + testScope, + TransitionInfo( + ownerName = "", + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.PRIMARY_BOUNCER, + animator = + ValueAnimator().apply { + duration = 10 + interpolator = Interpolators.LINEAR + }, + ) + ) + runCurrent() + reset(mockTransitionRepository) + + // GIVEN aod not available and starting to sleep to sleep + keyguardRepository.setAodAvailable(false) + keyguardRepository.setWakefulnessModel(startingToSleep()) + + // WHEN the primaryBouncer stops showing + bouncerRepository.setPrimaryVisible(false) + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(mockTransitionRepository).startTransition(capture()) + } + // THEN a transition to DOZING should occur + assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.PRIMARY_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.DOZING) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun `PRIMARY_BOUNCER to LOCKSCREEN`() = + testScope.runTest { + // GIVEN a prior transition has run to PRIMARY_BOUNCER + bouncerRepository.setPrimaryVisible(true) + runner.startTransition( + testScope, + TransitionInfo( + ownerName = "", + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.PRIMARY_BOUNCER, + animator = + ValueAnimator().apply { + duration = 10 + interpolator = Interpolators.LINEAR + }, + ) + ) + runCurrent() + reset(mockTransitionRepository) + + // GIVEN device not sleeping + keyguardRepository.setWakefulnessModel(startingToWake()) + + // WHEN the alternateBouncer stops showing + bouncerRepository.setPrimaryVisible(false) + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(mockTransitionRepository).startTransition(capture()) + } + // THEN a transition to LOCKSCREEN should occur + assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor") + assertThat(info.from).isEqualTo(KeyguardState.PRIMARY_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + private fun startingToWake() = WakefulnessModel( WakefulnessState.STARTING_TO_WAKE, @@ -710,4 +1021,13 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { WakeSleepReason.OTHER, WakeSleepReason.OTHER ) + + private fun createKeyguardInteractor(featureFlags: FeatureFlags): KeyguardInteractor { + return KeyguardInteractor( + keyguardRepository, + commandQueue, + featureFlags, + bouncerRepository, + ) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt index c5e025285944..46ed829e0574 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt @@ -102,7 +102,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() { verify(repository).setPrimaryScrimmed(true) verify(repository).setPanelExpansion(EXPANSION_VISIBLE) verify(repository).setPrimaryShowingSoon(true) - verify(keyguardStateController).notifyBouncerShowing(true) + verify(keyguardStateController).notifyPrimaryBouncerShowing(true) verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToShow() verify(repository).setPrimaryVisible(true) verify(repository).setPrimaryShow(any(KeyguardBouncerModel::class.java)) @@ -118,7 +118,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() { @Test fun testShow_keyguardIsDone() { `when`(bouncerView.delegate?.showNextSecurityScreenOrFinish()).thenReturn(true) - verify(keyguardStateController, never()).notifyBouncerShowing(true) + verify(keyguardStateController, never()).notifyPrimaryBouncerShowing(true) verify(mPrimaryBouncerCallbackInteractor, never()).dispatchStartingToShow() } @@ -126,7 +126,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() { fun testHide() { underTest.hide() verify(falsingCollector).onBouncerHidden() - verify(keyguardStateController).notifyBouncerShowing(false) + verify(keyguardStateController).notifyPrimaryBouncerShowing(false) verify(repository).setPrimaryShowingSoon(false) verify(repository).setPrimaryVisible(false) verify(repository).setPrimaryHide(true) 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 03a347eb1562..6afeddda18ab 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 @@ -35,6 +35,7 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor @@ -136,6 +137,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { repository = repository, commandQueue = commandQueue, featureFlags = featureFlags, + bouncerRepository = FakeKeyguardBouncerRepository(), ) whenever(userTracker.userHandle).thenReturn(mock()) whenever(lockPatternUtils.getStrongAuthForUser(anyInt())) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt index 9f12329321e1..a07a714ebc77 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt @@ -1897,6 +1897,20 @@ class MediaDataManagerTest : SysuiTestCase() { .onMediaDataLoaded(eq(PACKAGE_NAME), any(), any(), anyBoolean(), anyInt(), anyBoolean()) } + @Test + fun testSessionDestroyed_noNotificationKey_stillRemoved() { + whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true) + whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true) + + // When a notiifcation is added and then removed before it is fully processed + mediaDataManager.onNotificationAdded(KEY, mediaNotification) + backgroundExecutor.runAllReady() + mediaDataManager.onNotificationRemoved(KEY) + + // We still make sure to remove it + verify(listener).onMediaDataRemoved(eq(KEY)) + } + /** Helper function to add a media notification and capture the resulting MediaData */ private fun addNotificationAndLoad() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt index 4635b4843a91..e222542e5c53 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt @@ -52,14 +52,15 @@ import com.android.systemui.qs.tiles.UiModeNightTile import com.android.systemui.qs.tiles.WorkModeTile import com.android.systemui.util.leak.GarbageMonitor import com.google.common.truth.Truth.assertThat +import javax.inject.Provider import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Answers import org.mockito.Mock import org.mockito.Mockito.inOrder -import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations private val specMap = mapOf( "internet" to InternetTile::class.java, @@ -140,40 +141,43 @@ class QSFactoryImplTest : SysuiTestCase() { whenever(qsHost.userContext).thenReturn(mContext) whenever(customTileBuilder.build()).thenReturn(customTile) + val tileMap = mutableMapOf<String, Provider<QSTileImpl<*>>>( + "internet" to Provider { internetTile }, + "bt" to Provider { bluetoothTile }, + "dnd" to Provider { dndTile }, + "inversion" to Provider { colorInversionTile }, + "airplane" to Provider { airplaneTile }, + "work" to Provider { workTile }, + "rotation" to Provider { rotationTile }, + "flashlight" to Provider { flashlightTile }, + "location" to Provider { locationTile }, + "cast" to Provider { castTile }, + "hotspot" to Provider { hotspotTile }, + "battery" to Provider { batterySaverTile }, + "saver" to Provider { dataSaverTile }, + "night" to Provider { nightDisplayTile }, + "nfc" to Provider { nfcTile }, + "dark" to Provider { darkModeTile }, + "screenrecord" to Provider { screenRecordTile }, + "reduce_brightness" to Provider { reduceBrightColorsTile }, + "cameratoggle" to Provider { cameraToggleTile }, + "mictoggle" to Provider { microphoneToggleTile }, + "controls" to Provider { deviceControlsTile }, + "alarm" to Provider { alarmTile }, + "wallet" to Provider { quickAccessWalletTile }, + "qr_code_scanner" to Provider { qrCodeScannerTile }, + "onehanded" to Provider { oneHandedModeTile }, + "color_correction" to Provider { colorCorrectionTile }, + "dream" to Provider { dreamTile }, + "font_scaling" to Provider { fontScalingTile } + ) + factory = QSFactoryImpl( { qsHost }, { customTileBuilder }, - { internetTile }, - { bluetoothTile }, - { dndTile }, - { colorInversionTile }, - { airplaneTile }, - { workTile }, - { rotationTile }, - { flashlightTile }, - { locationTile }, - { castTile }, - { hotspotTile }, - { batterySaverTile }, - { dataSaverTile }, - { nightDisplayTile }, - { nfcTile }, - { memoryTile }, - { darkModeTile }, - { screenRecordTile }, - { reduceBrightColorsTile }, - { cameraToggleTile }, - { microphoneToggleTile }, - { deviceControlsTile }, - { alarmTile }, - { quickAccessWalletTile }, - { qrCodeScannerTile }, - { oneHandedModeTile }, - { colorCorrectionTile }, - { dreamTile }, - { fontScalingTile } + tileMap, ) - // When adding/removing tiles, fix also [specMap] + // When adding/removing tiles, fix also [specMap] and [tileMap] } @Test @@ -209,4 +213,4 @@ class QSFactoryImplTest : SysuiTestCase() { inOrder.verify(tile).initialize() inOrder.verify(tile).postStale() } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/FontScalingTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt index 57abae0889ca..528978ab5ee2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/FontScalingTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.systemui.qs.tiles.dialog +package com.android.systemui.qs.tiles import android.os.Handler import android.testing.AndroidTestingRunner @@ -27,7 +27,6 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSTileHost import com.android.systemui.qs.logging.QSLogger -import com.android.systemui.qs.tiles.FontScalingTile import com.android.systemui.util.settings.FakeSettings import com.google.common.truth.Truth.assertThat import org.junit.Before diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt index 020a86611552..3fd19ff1827b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt @@ -30,12 +30,14 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat +import java.io.File +import java.nio.file.Files import java.util.concurrent.Executor -import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock +import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.isNull import org.mockito.Mockito.spy import org.mockito.Mockito.verify @@ -61,36 +63,83 @@ class UserFileManagerImplTest : SysuiTestCase() { UserFileManagerImpl(context, userManager, broadcastDispatcher, backgroundExecutor) } - @After - fun end() { - val dir = Environment.buildPath(context.filesDir, UserFileManagerImpl.ID) - dir.deleteRecursively() - } - @Test fun testGetFile() { assertThat(userFileManager.getFile(TEST_FILE_NAME, 0).path) .isEqualTo("${context.filesDir}/$TEST_FILE_NAME") assertThat(userFileManager.getFile(TEST_FILE_NAME, 11).path) - .isEqualTo("${context.filesDir}/${UserFileManagerImpl.ID}/11/files/$TEST_FILE_NAME") + .isEqualTo("${context.filesDir}/__USER_11_$TEST_FILE_NAME") } @Test fun testGetSharedPreferences() { + val primarySharedPref = userFileManager.getSharedPreferences(TEST_FILE_NAME, 0, 0) val secondarySharedPref = userFileManager.getSharedPreferences(TEST_FILE_NAME, 0, 11) - val secondaryUserDir = - Environment.buildPath( - context.filesDir, - UserFileManagerImpl.ID, - "11", + + assertThat(primarySharedPref).isNotEqualTo(secondarySharedPref) + + // Make sure these are different files + primarySharedPref.edit().putString("TEST", "ABC").commit() + assertThat(secondarySharedPref.getString("TEST", null)).isNull() + + context.deleteSharedPreferences("TEST") + context.deleteSharedPreferences("__USER_11_TEST") + } + + @Test + fun testMigrateFile() { + val userId = 12 + val fileName = "myFile.txt" + val fileContents = "TestingFile" + val legacyFile = + UserFileManagerImpl.createLegacyFile( + context, + UserFileManagerImpl.FILES, + fileName, + userId + )!! + + // Write file to legacy area + Files.createDirectories(legacyFile.getParentFile().toPath()) + Files.write(legacyFile.toPath(), fileContents.toByteArray()) + assertThat(legacyFile.exists()).isTrue() + + // getFile() should migrate the legacy file to the new location + val file = userFileManager.getFile(fileName, userId) + val newContents = String(Files.readAllBytes(file.toPath())) + + assertThat(newContents).isEqualTo(fileContents) + assertThat(legacyFile.exists()).isFalse() + assertThat(File(context.filesDir, UserFileManagerImpl.ROOT_DIR).exists()).isFalse() + } + + @Test + fun testMigrateSharedPrefs() { + val userId = 13 + val fileName = "myFile" + val contents = "TestingSharedPrefs" + val legacyFile = + UserFileManagerImpl.createLegacyFile( + context, UserFileManagerImpl.SHARED_PREFS, - TEST_FILE_NAME - ) + "$fileName.xml", + userId + )!! - assertThat(secondarySharedPref).isNotNull() - assertThat(secondaryUserDir.exists()) - assertThat(userFileManager.getSharedPreferences(TEST_FILE_NAME, 0, 0)) - .isNotEqualTo(secondarySharedPref) + // Write a valid shared prefs xml file to legacy area + val tmpPrefs = context.getSharedPreferences("tmp", Context.MODE_PRIVATE) + tmpPrefs.edit().putString(contents, contents).commit() + Files.createDirectories(legacyFile.getParentFile().toPath()) + val tmpFile = + Environment.buildPath(context.dataDir, UserFileManagerImpl.SHARED_PREFS, "tmp.xml") + tmpFile.renameTo(legacyFile) + assertThat(legacyFile.exists()).isTrue() + + // getSharedpreferences() should migrate the legacy file to the new location + val prefs = userFileManager.getSharedPreferences(fileName, Context.MODE_PRIVATE, userId) + assertThat(prefs.getString(contents, "")).isEqualTo(contents) + assertThat(legacyFile.exists()).isFalse() + assertThat(File(context.filesDir, UserFileManagerImpl.ROOT_DIR).exists()).isFalse() } @Test @@ -111,44 +160,14 @@ class UserFileManagerImplTest : SysuiTestCase() { @Test fun testClearDeletedUserData() { - val dir = Environment.buildPath(context.filesDir, UserFileManagerImpl.ID, "11", "files") - dir.mkdirs() - val file = - Environment.buildPath( - context.filesDir, - UserFileManagerImpl.ID, - "11", - "files", - TEST_FILE_NAME - ) - val secondaryUserDir = - Environment.buildPath( - context.filesDir, - UserFileManagerImpl.ID, - "11", - ) + val file = userFileManager.getFile(TEST_FILE_NAME, 11) file.createNewFile() - assertThat(secondaryUserDir.exists()).isTrue() + assertThat(file.exists()).isTrue() userFileManager.clearDeletedUserData() assertThat(backgroundExecutor.runAllReady()).isGreaterThan(0) - verify(userManager).aliveUsers - assertThat(secondaryUserDir.exists()).isFalse() - assertThat(file.exists()).isFalse() - } + verify(userManager, atLeastOnce()).aliveUsers - @Test - fun testEnsureParentDirExists() { - val file = - Environment.buildPath( - context.filesDir, - UserFileManagerImpl.ID, - "11", - "files", - TEST_FILE_NAME - ) - assertThat(file.parentFile.exists()).isFalse() - UserFileManagerImpl.ensureParentDirExists(file) - assertThat(file.parentFile.exists()).isTrue() + assertThat(file.exists()).isFalse() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt index e5d5e3b8433a..d229a08ad7c4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -21,7 +21,7 @@ import android.testing.TestableLooper.RunWithLooper import android.view.MotionEvent import android.view.ViewGroup import androidx.test.filters.SmallTest -import com.android.keyguard.KeyguardHostViewController +import com.android.keyguard.KeyguardSecurityContainerController import com.android.keyguard.LockIconViewController import com.android.keyguard.dagger.KeyguardBouncerComponent import com.android.systemui.R @@ -106,7 +106,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor @Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory @Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent - @Mock lateinit var keyguardHostViewController: KeyguardHostViewController + @Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController @Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler> @@ -122,8 +122,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { .thenReturn(mock(ViewGroup::class.java)) whenever(keyguardBouncerComponentFactory.create(any(ViewGroup::class.java))) .thenReturn(keyguardBouncerComponent) - whenever(keyguardBouncerComponent.keyguardHostViewController) - .thenReturn(keyguardHostViewController) + whenever(keyguardBouncerComponent.securityContainerController) + .thenReturn(keyguardSecurityContainerController) underTest = NotificationShadeWindowViewController( lockscreenShadeTransitionController, FalsingCollectorFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java index 5cc3ef1def9e..5e9c2199897d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java @@ -33,7 +33,7 @@ import android.view.ViewGroup; import androidx.test.filters.SmallTest; -import com.android.keyguard.KeyguardHostViewController; +import com.android.keyguard.KeyguardSecurityContainerController; import com.android.keyguard.LockIconViewController; import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.systemui.R; @@ -97,7 +97,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { @Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel; @Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory; @Mock private KeyguardBouncerComponent mKeyguardBouncerComponent; - @Mock private KeyguardHostViewController mKeyguardHostViewController; + @Mock private KeyguardSecurityContainerController mKeyguardSecurityContainerController; @Mock private NotificationInsetsController mNotificationInsetsController; @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor; @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor; @@ -117,8 +117,8 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { when(mView.findViewById(R.id.keyguard_bouncer_container)).thenReturn(mock(ViewGroup.class)); when(mKeyguardBouncerComponentFactory.create(any(ViewGroup.class))).thenReturn( mKeyguardBouncerComponent); - when(mKeyguardBouncerComponent.getKeyguardHostViewController()).thenReturn( - mKeyguardHostViewController); + when(mKeyguardBouncerComponent.getSecurityContainerController()).thenReturn( + mKeyguardSecurityContainerController); when(mStatusBarStateController.isDozing()).thenReturn(false); mDependency.injectTestDependency(ShadeController.class, mShadeController); diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt index d01edccb6a82..26eff61066ee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt @@ -230,7 +230,7 @@ class ClockRegistryTest : SysuiTestCase() { } @Test - fun pluginRemoved_clockChanged() { + fun pluginRemoved_clockAndListChanged() { val plugin1 = FakeClockPlugin() .addClock("clock_1", "clock 1") .addClock("clock_2", "clock 2") @@ -239,20 +239,36 @@ class ClockRegistryTest : SysuiTestCase() { .addClock("clock_3", "clock 3", { mockClock }) .addClock("clock_4", "clock 4") + + var changeCallCount = 0 + var listChangeCallCount = 0 + registry.registerClockChangeListener(object : ClockRegistry.ClockChangeListener { + override fun onCurrentClockChanged() { changeCallCount++ } + override fun onAvailableClocksChanged() { listChangeCallCount++ } + }) + registry.applySettings(ClockSettings("clock_3", null)) + assertEquals(0, changeCallCount) + assertEquals(0, listChangeCallCount) + pluginListener.onPluginConnected(plugin1, mockContext) - pluginListener.onPluginConnected(plugin2, mockContext) + assertEquals(0, changeCallCount) + assertEquals(1, listChangeCallCount) - var changeCallCount = 0 - registry.registerClockChangeListener { changeCallCount++ } + pluginListener.onPluginConnected(plugin2, mockContext) + assertEquals(1, changeCallCount) + assertEquals(2, listChangeCallCount) pluginListener.onPluginDisconnected(plugin1) - assertEquals(0, changeCallCount) + assertEquals(1, changeCallCount) + assertEquals(3, listChangeCallCount) pluginListener.onPluginDisconnected(plugin2) - assertEquals(1, changeCallCount) + assertEquals(2, changeCallCount) + assertEquals(4, listChangeCallCount) } + @Test fun jsonDeserialization_gotExpectedObject() { val expected = ClockSettings("ID", null).apply { _applied_timestamp = 500 } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt index 49da848baca7..8109e24a1e52 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt @@ -23,6 +23,7 @@ import android.provider.Settings import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.advanceTimeBy import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.StatusBarState @@ -311,17 +312,20 @@ class KeyguardCoordinatorTest : SysuiTestCase() { fun unseenNotificationIsMarkedAsSeenWhenKeyguardGoesAway() { whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true) - // GIVEN: Keyguard is showing, unseen notification is present + // GIVEN: Keyguard is showing, not dozing, unseen notification is present keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setDozing(false) runKeyguardCoordinatorTest { val fakeEntry = NotificationEntryBuilder().build() collectionListener.onEntryAdded(fakeEntry) + // WHEN: five seconds have passed + testScheduler.advanceTimeBy(5.seconds) + testScheduler.runCurrent() + // WHEN: Keyguard is no longer showing keyguardRepository.setKeyguardShowing(false) - - // When: Shade is expanded - statusBarStateListener.onExpandedChanged(true) + testScheduler.runCurrent() // WHEN: Keyguard is shown again keyguardRepository.setKeyguardShowing(true) 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 58325697a408..4d9db8c28e07 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,6 +526,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, + /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -545,7 +546,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() @@ -555,6 +556,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, + /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -578,7 +580,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 + @@ -589,6 +591,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, + /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -608,7 +611,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 @@ -619,6 +622,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, + /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -638,7 +642,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 @@ -650,6 +654,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { // When: updateChildZValue() is called for the top HUN stackScrollAlgorithm.updateChildZValue( /* i= */ 0, + /* childrenOnTop= */ 0.0f, /* StackScrollAlgorithmState= */ algorithmState, /* ambientState= */ ambientState, /* shouldElevateHun= */ true @@ -664,7 +669,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { private fun createHunViewMock( isShadeOpen: Boolean, fullyVisible: Boolean, - headerVisibleAmount: Float, + headerVisibleAmount: Float ) = mock<ExpandableNotificationRow>().apply { val childViewStateMock = createHunChildViewState(isShadeOpen, fullyVisible) @@ -675,10 +680,7 @@ 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/FakeKeyguardStateController.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java index a986777afa22..c669c6f6fb1c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java @@ -53,7 +53,7 @@ public class FakeKeyguardStateController implements KeyguardStateController { } @Override - public boolean isBouncerShowing() { + public boolean isPrimaryBouncerShowing() { return false; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt index 5a6bb301743a..ab888f7c133e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt @@ -18,9 +18,9 @@ package com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.google.common.truth.Truth.assertThat @@ -42,7 +42,7 @@ class AirplaneModeViewModelImplTest : SysuiTestCase() { private lateinit var underTest: AirplaneModeViewModelImpl - @Mock private lateinit var logger: ConnectivityPipelineLogger + @Mock private lateinit var logger: TableLogBuffer private lateinit var airplaneModeRepository: FakeAirplaneModeRepository private lateinit var connectivityRepository: FakeConnectivityRepository private lateinit var interactor: AirplaneModeInteractor diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt index 521c67f20cfd..0145103d55e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt @@ -25,7 +25,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger +import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -53,7 +53,7 @@ class CarrierConfigRepositoryTest : SysuiTestCase() { private lateinit var mockitoSession: MockitoSession private lateinit var carrierConfigCoreStartable: CarrierConfigCoreStartable - @Mock private lateinit var logger: ConnectivityPipelineLogger + @Mock private lateinit var logger: MobileInputLogger @Mock private lateinit var carrierConfigManager: CarrierConfigManager @Mock private lateinit var dumpManager: DumpManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt index 4da2104ca32e..17502f28a479 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt @@ -33,8 +33,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoM import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.validMobileEvent import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl +import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource import com.android.systemui.util.mockito.any @@ -81,7 +81,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() { @Mock private lateinit var connectivityManager: ConnectivityManager @Mock private lateinit var subscriptionManager: SubscriptionManager @Mock private lateinit var telephonyManager: TelephonyManager - @Mock private lateinit var logger: ConnectivityPipelineLogger + @Mock private lateinit var logger: MobileInputLogger @Mock private lateinit var summaryLogger: TableLogBuffer @Mock private lateinit var demoModeController: DemoModeController @Mock private lateinit var dumpManager: DumpManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt index abb45619e1dd..f0f213bc0d58 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt @@ -26,8 +26,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectio import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt index c02ca01cedc4..cd4d8472763f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt @@ -32,8 +32,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameMode import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt index a294088a41c0..b2577e349da7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt @@ -65,8 +65,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrier import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS +import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel import com.android.systemui.util.mockito.any @@ -94,7 +94,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { private lateinit var connectionsRepo: FakeMobileConnectionsRepository @Mock private lateinit var telephonyManager: TelephonyManager - @Mock private lateinit var logger: ConnectivityPipelineLogger + @Mock private lateinit var logger: MobileInputLogger @Mock private lateinit var tableLogger: TableLogBuffer private val scope = CoroutineScope(IMMEDIATE) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt index 3853b99b5c4a..09b7a66c925d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt @@ -42,10 +42,10 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionMod import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName +import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.eq @@ -86,7 +86,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { @Mock private lateinit var connectivityManager: ConnectivityManager @Mock private lateinit var subscriptionManager: SubscriptionManager @Mock private lateinit var telephonyManager: TelephonyManager - @Mock private lateinit var logger: ConnectivityPipelineLogger + @Mock private lateinit var logger: MobileInputLogger @Mock private lateinit var summaryLogger: TableLogBuffer @Mock private lateinit var logBufferFactory: TableLogBufferFactory diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt index bbca0011483f..c51dbf11e751 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt @@ -85,7 +85,6 @@ class MobileIconsInteractorTest : SysuiTestCase() { MobileIconsInteractorImpl( connectionsRepository, carrierConfigTracker, - logger = mock(), tableLogger = mock(), connectivityRepository, userSetupRepository, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt new file mode 100644 index 000000000000..86529dce948a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.mobile.shared + +import android.net.Network +import android.net.NetworkCapabilities +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager +import com.android.systemui.log.LogBufferFactory +import com.android.systemui.plugins.log.LogcatEchoTracker +import com.google.common.truth.Truth.assertThat +import java.io.PrintWriter +import java.io.StringWriter +import org.junit.Test +import org.mockito.Mockito +import org.mockito.Mockito.mock + +@SmallTest +class MobileInputLoggerTest : SysuiTestCase() { + private val buffer = + LogBufferFactory(DumpManager(), mock(LogcatEchoTracker::class.java)).create("buffer", 10) + private val logger = MobileInputLogger(buffer) + + @Test + fun testLogNetworkCapsChange_bufferHasInfo() { + logger.logOnCapabilitiesChanged(NET_1, NET_1_CAPS, isDefaultNetworkCallback = true) + + val stringWriter = StringWriter() + buffer.dump(PrintWriter(stringWriter), tailLength = 0) + val actualString = stringWriter.toString() + + val expectedNetId = NET_1_ID.toString() + val expectedCaps = NET_1_CAPS.toString() + + assertThat(actualString).contains("true") + assertThat(actualString).contains(expectedNetId) + assertThat(actualString).contains(expectedCaps) + } + + @Test + fun testLogOnLost_bufferHasNetIdOfLostNetwork() { + logger.logOnLost(NET_1) + + val stringWriter = StringWriter() + buffer.dump(PrintWriter(stringWriter), tailLength = 0) + val actualString = stringWriter.toString() + + val expectedNetId = NET_1_ID.toString() + + assertThat(actualString).contains(expectedNetId) + } + + companion object { + private const val NET_1_ID = 100 + private val NET_1 = + com.android.systemui.util.mockito.mock<Network>().also { + Mockito.`when`(it.getNetId()).thenReturn(NET_1_ID) + } + private val NET_1_CAPS = + NetworkCapabilities.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + .build() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt index d9268a2c3b94..4628f8410245 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt @@ -26,7 +26,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionMod import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat @@ -51,7 +50,6 @@ class MobileIconsViewModelTest : SysuiTestCase() { private lateinit var airplaneModeInteractor: AirplaneModeInteractor @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags - @Mock private lateinit var logger: ConnectivityPipelineLogger @Mock private lateinit var constants: ConnectivityConstants private val testDispatcher = UnconfinedTestDispatcher() @@ -77,7 +75,6 @@ class MobileIconsViewModelTest : SysuiTestCase() { subscriptionIdsFlow, interactor, airplaneModeInteractor, - logger, constants, testScope.backgroundScope, statusBarPipelineFlags, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt deleted file mode 100644 index 3dccbbf26575..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.statusbar.pipeline.shared - -import android.net.Network -import android.net.NetworkCapabilities -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.dump.DumpManager -import com.android.systemui.log.LogBufferFactory -import com.android.systemui.plugins.log.LogcatEchoTracker -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange -import com.google.common.truth.Truth.assertThat -import java.io.PrintWriter -import java.io.StringWriter -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.runBlocking -import org.junit.Test -import org.mockito.Mockito -import org.mockito.Mockito.mock - -@SmallTest -class ConnectivityPipelineLoggerTest : SysuiTestCase() { - private val buffer = LogBufferFactory(DumpManager(), mock(LogcatEchoTracker::class.java)) - .create("buffer", 10) - private val logger = ConnectivityPipelineLogger(buffer) - - @Test - fun testLogNetworkCapsChange_bufferHasInfo() { - logger.logOnCapabilitiesChanged(NET_1, NET_1_CAPS, isDefaultNetworkCallback = true) - - val stringWriter = StringWriter() - buffer.dump(PrintWriter(stringWriter), tailLength = 0) - val actualString = stringWriter.toString() - - val expectedNetId = NET_1_ID.toString() - val expectedCaps = NET_1_CAPS.toString() - - assertThat(actualString).contains("true") - assertThat(actualString).contains(expectedNetId) - assertThat(actualString).contains(expectedCaps) - } - - @Test - fun testLogOnLost_bufferHasNetIdOfLostNetwork() { - logger.logOnLost(NET_1) - - val stringWriter = StringWriter() - buffer.dump(PrintWriter(stringWriter), tailLength = 0) - val actualString = stringWriter.toString() - - val expectedNetId = NET_1_ID.toString() - - assertThat(actualString).contains(expectedNetId) - } - - @Test - fun logOutputChange_printsValuesAndNulls() = runBlocking(IMMEDIATE) { - val flow: Flow<Int?> = flowOf(1, null, 3) - - val job = flow - .logOutputChange(logger, "testInts") - .launchIn(this) - - val stringWriter = StringWriter() - buffer.dump(PrintWriter(stringWriter), tailLength = 0) - val actualString = stringWriter.toString() - - assertThat(actualString).contains("1") - assertThat(actualString).contains("null") - assertThat(actualString).contains("3") - - job.cancel() - } - - @Test - fun logInputChange_unit_printsInputName() = runBlocking(IMMEDIATE) { - val flow: Flow<Unit> = flowOf(Unit, Unit) - - val job = flow - .logInputChange(logger, "testInputs") - .launchIn(this) - - val stringWriter = StringWriter() - buffer.dump(PrintWriter(stringWriter), tailLength = 0) - val actualString = stringWriter.toString() - - assertThat(actualString).contains("testInputs") - - job.cancel() - } - - @Test - fun logInputChange_any_printsValuesAndNulls() = runBlocking(IMMEDIATE) { - val flow: Flow<Any?> = flowOf(null, 2, "threeString") - - val job = flow - .logInputChange(logger, "testInputs") - .launchIn(this) - - val stringWriter = StringWriter() - buffer.dump(PrintWriter(stringWriter), tailLength = 0) - val actualString = stringWriter.toString() - - assertThat(actualString).contains("null") - assertThat(actualString).contains("2") - assertThat(actualString).contains("threeString") - - job.cancel() - } - - companion object { - private const val NET_1_ID = 100 - private val NET_1 = com.android.systemui.util.mockito.mock<Network>().also { - Mockito.`when`(it.getNetId()).thenReturn(NET_1_ID) - } - private val NET_1_CAPS = NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) - .build() - private val IMMEDIATE = Dispatchers.Main.immediate - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt index 6dbee2f26ff9..496f090da25c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt @@ -19,7 +19,7 @@ package com.android.systemui.statusbar.pipeline.shared.data.repository import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger +import com.android.systemui.statusbar.pipeline.shared.ConnectivityInputLogger import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.DEFAULT_HIDDEN_ICONS_RESOURCE @@ -52,7 +52,7 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() { @Mock private lateinit var connectivitySlots: ConnectivitySlots @Mock private lateinit var dumpManager: DumpManager - @Mock private lateinit var logger: ConnectivityPipelineLogger + @Mock private lateinit var logger: ConnectivityInputLogger private lateinit var scope: CoroutineScope @Mock private lateinit var tunerService: TunerService @@ -61,14 +61,15 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) scope = CoroutineScope(IMMEDIATE) - underTest = ConnectivityRepositoryImpl( - connectivitySlots, - context, - dumpManager, - logger, - scope, - tunerService, - ) + underTest = + ConnectivityRepositoryImpl( + connectivitySlots, + context, + dumpManager, + logger, + scope, + tunerService, + ) } @After @@ -77,199 +78,179 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() { } @Test - fun forceHiddenSlots_initiallyGetsDefault() = runBlocking(IMMEDIATE) { - setUpEthernetWifiMobileSlotNames() - context.getOrCreateTestableResources().addOverride( - DEFAULT_HIDDEN_ICONS_RESOURCE, - arrayOf(SLOT_WIFI, SLOT_ETHERNET) - ) - // Re-create our [ConnectivityRepositoryImpl], since it fetches - // config_statusBarIconsToExclude when it's first constructed - underTest = ConnectivityRepositoryImpl( - connectivitySlots, - context, - dumpManager, - logger, - scope, - tunerService, - ) - - var latest: Set<ConnectivitySlot>? = null - val job = underTest - .forceHiddenSlots - .onEach { latest = it } - .launchIn(this) - - assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI) - - job.cancel() - } + fun forceHiddenSlots_initiallyGetsDefault() = + runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() + context + .getOrCreateTestableResources() + .addOverride(DEFAULT_HIDDEN_ICONS_RESOURCE, arrayOf(SLOT_WIFI, SLOT_ETHERNET)) + // Re-create our [ConnectivityRepositoryImpl], since it fetches + // config_statusBarIconsToExclude when it's first constructed + underTest = + ConnectivityRepositoryImpl( + connectivitySlots, + context, + dumpManager, + logger, + scope, + tunerService, + ) + + var latest: Set<ConnectivitySlot>? = null + val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this) + + assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI) + + job.cancel() + } @Test - fun forceHiddenSlots_slotNamesAdded_flowHasSlots() = runBlocking(IMMEDIATE) { - setUpEthernetWifiMobileSlotNames() + fun forceHiddenSlots_slotNamesAdded_flowHasSlots() = + runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() - var latest: Set<ConnectivitySlot>? = null - val job = underTest - .forceHiddenSlots - .onEach { latest = it } - .launchIn(this) + var latest: Set<ConnectivitySlot>? = null + val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this) - getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE) + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE) - assertThat(latest).containsExactly(ConnectivitySlot.MOBILE) + assertThat(latest).containsExactly(ConnectivitySlot.MOBILE) - job.cancel() - } + job.cancel() + } @Test - fun forceHiddenSlots_wrongKey_doesNotUpdate() = runBlocking(IMMEDIATE) { - setUpEthernetWifiMobileSlotNames() + fun forceHiddenSlots_wrongKey_doesNotUpdate() = + runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() - var latest: Set<ConnectivitySlot>? = null - val job = underTest - .forceHiddenSlots - .onEach { latest = it } - .launchIn(this) + var latest: Set<ConnectivitySlot>? = null + val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this) - getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE) + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE) - // WHEN onTuningChanged with the wrong key - getTunable().onTuningChanged("wrongKey", SLOT_WIFI) - yield() + // WHEN onTuningChanged with the wrong key + getTunable().onTuningChanged("wrongKey", SLOT_WIFI) + yield() - // THEN we didn't update our value and still have the old one - assertThat(latest).containsExactly(ConnectivitySlot.MOBILE) + // THEN we didn't update our value and still have the old one + assertThat(latest).containsExactly(ConnectivitySlot.MOBILE) - job.cancel() - } + job.cancel() + } @Test - fun forceHiddenSlots_slotNamesAddedThenNull_flowHasDefault() = runBlocking(IMMEDIATE) { - setUpEthernetWifiMobileSlotNames() - context.getOrCreateTestableResources().addOverride( - DEFAULT_HIDDEN_ICONS_RESOURCE, - arrayOf(SLOT_WIFI, SLOT_ETHERNET) - ) - // Re-create our [ConnectivityRepositoryImpl], since it fetches - // config_statusBarIconsToExclude when it's first constructed - underTest = ConnectivityRepositoryImpl( - connectivitySlots, - context, - dumpManager, - logger, - scope, - tunerService, - ) - - var latest: Set<ConnectivitySlot>? = null - val job = underTest - .forceHiddenSlots - .onEach { latest = it } - .launchIn(this) - - // First, update the slots - getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE) - assertThat(latest).containsExactly(ConnectivitySlot.MOBILE) - - // WHEN we update to a null value - getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, null) - yield() - - // THEN we go back to our default value - assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI) - - job.cancel() - } + fun forceHiddenSlots_slotNamesAddedThenNull_flowHasDefault() = + runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() + context + .getOrCreateTestableResources() + .addOverride(DEFAULT_HIDDEN_ICONS_RESOURCE, arrayOf(SLOT_WIFI, SLOT_ETHERNET)) + // Re-create our [ConnectivityRepositoryImpl], since it fetches + // config_statusBarIconsToExclude when it's first constructed + underTest = + ConnectivityRepositoryImpl( + connectivitySlots, + context, + dumpManager, + logger, + scope, + tunerService, + ) + + var latest: Set<ConnectivitySlot>? = null + val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this) + + // First, update the slots + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE) + assertThat(latest).containsExactly(ConnectivitySlot.MOBILE) + + // WHEN we update to a null value + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, null) + yield() + + // THEN we go back to our default value + assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI) + + job.cancel() + } @Test - fun forceHiddenSlots_someInvalidSlotNames_flowHasValidSlotsOnly() = runBlocking(IMMEDIATE) { - var latest: Set<ConnectivitySlot>? = null - val job = underTest - .forceHiddenSlots - .onEach { latest = it } - .launchIn(this) + fun forceHiddenSlots_someInvalidSlotNames_flowHasValidSlotsOnly() = + runBlocking(IMMEDIATE) { + var latest: Set<ConnectivitySlot>? = null + val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this) - whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)) - .thenReturn(ConnectivitySlot.WIFI) - whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null) + whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)).thenReturn(ConnectivitySlot.WIFI) + whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null) - getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_MOBILE") + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_MOBILE") - assertThat(latest).containsExactly(ConnectivitySlot.WIFI) + assertThat(latest).containsExactly(ConnectivitySlot.WIFI) - job.cancel() - } + job.cancel() + } @Test - fun forceHiddenSlots_someEmptySlotNames_flowHasValidSlotsOnly() = runBlocking(IMMEDIATE) { - setUpEthernetWifiMobileSlotNames() + fun forceHiddenSlots_someEmptySlotNames_flowHasValidSlotsOnly() = + runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() - var latest: Set<ConnectivitySlot>? = null - val job = underTest - .forceHiddenSlots - .onEach { latest = it } - .launchIn(this) + var latest: Set<ConnectivitySlot>? = null + val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this) - // WHEN there's empty and blank slot names - getTunable().onTuningChanged( - HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_MOBILE, ,,$SLOT_WIFI" - ) + // WHEN there's empty and blank slot names + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_MOBILE, ,,$SLOT_WIFI") - // THEN we skip that slot but still process the other ones - assertThat(latest).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.MOBILE) + // THEN we skip that slot but still process the other ones + assertThat(latest).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.MOBILE) - job.cancel() - } + job.cancel() + } @Test - fun forceHiddenSlots_allInvalidOrEmptySlotNames_flowHasEmpty() = runBlocking(IMMEDIATE) { - var latest: Set<ConnectivitySlot>? = null - val job = underTest - .forceHiddenSlots - .onEach { latest = it } - .launchIn(this) + fun forceHiddenSlots_allInvalidOrEmptySlotNames_flowHasEmpty() = + runBlocking(IMMEDIATE) { + var latest: Set<ConnectivitySlot>? = null + val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this) - whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)).thenReturn(null) - whenever(connectivitySlots.getSlotFromName(SLOT_ETHERNET)).thenReturn(null) - whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null) + whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)).thenReturn(null) + whenever(connectivitySlots.getSlotFromName(SLOT_ETHERNET)).thenReturn(null) + whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null) - getTunable().onTuningChanged( - HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_MOBILE,,$SLOT_WIFI,$SLOT_ETHERNET,,," - ) + getTunable() + .onTuningChanged( + HIDDEN_ICONS_TUNABLE_KEY, + "$SLOT_MOBILE,,$SLOT_WIFI,$SLOT_ETHERNET,,," + ) - assertThat(latest).isEmpty() + assertThat(latest).isEmpty() - job.cancel() - } + job.cancel() + } @Test - fun forceHiddenSlots_newSubscriberGetsCurrentValue() = runBlocking(IMMEDIATE) { - setUpEthernetWifiMobileSlotNames() + fun forceHiddenSlots_newSubscriberGetsCurrentValue() = + runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() - var latest1: Set<ConnectivitySlot>? = null - val job1 = underTest - .forceHiddenSlots - .onEach { latest1 = it } - .launchIn(this) + var latest1: Set<ConnectivitySlot>? = null + val job1 = underTest.forceHiddenSlots.onEach { latest1 = it }.launchIn(this) - getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_ETHERNET") + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_ETHERNET") - assertThat(latest1).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET) + assertThat(latest1).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET) - // WHEN we add a second subscriber after having already emitted a value - var latest2: Set<ConnectivitySlot>? = null - val job2 = underTest - .forceHiddenSlots - .onEach { latest2 = it } - .launchIn(this) + // WHEN we add a second subscriber after having already emitted a value + var latest2: Set<ConnectivitySlot>? = null + val job2 = underTest.forceHiddenSlots.onEach { latest2 = it }.launchIn(this) - // THEN the second subscribe receives the already-emitted value - assertThat(latest2).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET) + // THEN the second subscribe receives the already-emitted value + assertThat(latest2).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET) - job1.cancel() - job2.cancel() - } + job1.cancel() + job2.cancel() + } private fun getTunable(): TunerService.Tunable { val callbackCaptor = argumentCaptor<TunerService.Tunable>() @@ -280,10 +261,8 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() { private fun setUpEthernetWifiMobileSlotNames() { whenever(connectivitySlots.getSlotFromName(SLOT_ETHERNET)) .thenReturn(ConnectivitySlot.ETHERNET) - whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)) - .thenReturn(ConnectivitySlot.WIFI) - whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)) - .thenReturn(ConnectivitySlot.MOBILE) + whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)).thenReturn(ConnectivitySlot.WIFI) + whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(ConnectivitySlot.MOBILE) } companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt index f5837d698c51..1bf431b4ea13 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt @@ -17,8 +17,8 @@ package com.android.systemui.statusbar.pipeline.wifi.data.repository import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.ACTIVITY_DEFAULT +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt index 1085c2b1a5d5..25678b0530f6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt @@ -23,11 +23,11 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.demomode.DemoMode import com.android.systemui.demomode.DemoModeController import com.android.systemui.log.table.TableLogBuffer -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl +import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.kotlinArgumentCaptor import com.android.systemui.util.mockito.whenever @@ -47,6 +47,7 @@ import org.mockito.Mockito import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) +@Suppress("EXPERIMENTAL_IS_NOT_ENABLED") @SmallTest class WifiRepositorySwitcherTest : SysuiTestCase() { private lateinit var underTest: WifiRepositorySwitcher @@ -54,7 +55,7 @@ class WifiRepositorySwitcherTest : SysuiTestCase() { private lateinit var demoImpl: DemoWifiRepository @Mock private lateinit var demoModeController: DemoModeController - @Mock private lateinit var logger: ConnectivityPipelineLogger + @Mock private lateinit var logger: WifiInputLogger @Mock private lateinit var tableLogger: TableLogBuffer @Mock private lateinit var connectivityManager: ConnectivityManager @Mock private lateinit var wifiManager: WifiManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt index 3c4e85bd231e..9cf08c03b5d1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt @@ -19,7 +19,7 @@ package com.android.systemui.statusbar.pipeline.wifi.data.repository.prod import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt index 7099f1f0af2d..c7b31bcf9a0c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt @@ -34,10 +34,10 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.log.table.TableLogBuffer -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT +import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor @@ -72,7 +72,7 @@ class WifiRepositoryImplTest : SysuiTestCase() { private lateinit var underTest: WifiRepositoryImpl @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher - @Mock private lateinit var logger: ConnectivityPipelineLogger + @Mock private lateinit var logger: WifiInputLogger @Mock private lateinit var tableLogger: TableLogBuffer @Mock private lateinit var connectivityManager: ConnectivityManager @Mock private lateinit var wifiManager: WifiManager @@ -83,13 +83,14 @@ class WifiRepositoryImplTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) whenever( - broadcastDispatcher.broadcastFlow( - any(), - nullable(), - anyInt(), - nullable(), + broadcastDispatcher.broadcastFlow( + any(), + nullable(), + anyInt(), + nullable(), + ) ) - ).thenReturn(flowOf(Unit)) + .thenReturn(flowOf(Unit)) executor = FakeExecutor(FakeSystemClock()) scope = CoroutineScope(IMMEDIATE) underTest = createRepo() @@ -101,150 +102,152 @@ class WifiRepositoryImplTest : SysuiTestCase() { } @Test - fun isWifiEnabled_initiallyGetsWifiManagerValue() = runBlocking(IMMEDIATE) { - whenever(wifiManager.isWifiEnabled).thenReturn(true) + fun isWifiEnabled_initiallyGetsWifiManagerValue() = + runBlocking(IMMEDIATE) { + whenever(wifiManager.isWifiEnabled).thenReturn(true) - underTest = createRepo() + underTest = createRepo() - assertThat(underTest.isWifiEnabled.value).isTrue() - } + assertThat(underTest.isWifiEnabled.value).isTrue() + } @Test - fun isWifiEnabled_networkCapabilitiesChanged_valueUpdated() = runBlocking(IMMEDIATE) { - // We need to call launch on the flows so that they start updating - val networkJob = underTest.wifiNetwork.launchIn(this) - val enabledJob = underTest.isWifiEnabled.launchIn(this) + fun isWifiEnabled_networkCapabilitiesChanged_valueUpdated() = + runBlocking(IMMEDIATE) { + // We need to call launch on the flows so that they start updating + val networkJob = underTest.wifiNetwork.launchIn(this) + val enabledJob = underTest.isWifiEnabled.launchIn(this) - whenever(wifiManager.isWifiEnabled).thenReturn(true) - getNetworkCallback().onCapabilitiesChanged( - NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO) - ) + whenever(wifiManager.isWifiEnabled).thenReturn(true) + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) - assertThat(underTest.isWifiEnabled.value).isTrue() + assertThat(underTest.isWifiEnabled.value).isTrue() - whenever(wifiManager.isWifiEnabled).thenReturn(false) - getNetworkCallback().onCapabilitiesChanged( - NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO) - ) + whenever(wifiManager.isWifiEnabled).thenReturn(false) + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) - assertThat(underTest.isWifiEnabled.value).isFalse() + assertThat(underTest.isWifiEnabled.value).isFalse() - networkJob.cancel() - enabledJob.cancel() - } + networkJob.cancel() + enabledJob.cancel() + } @Test - fun isWifiEnabled_networkLost_valueUpdated() = runBlocking(IMMEDIATE) { - // We need to call launch on the flows so that they start updating - val networkJob = underTest.wifiNetwork.launchIn(this) - val enabledJob = underTest.isWifiEnabled.launchIn(this) + fun isWifiEnabled_networkLost_valueUpdated() = + runBlocking(IMMEDIATE) { + // We need to call launch on the flows so that they start updating + val networkJob = underTest.wifiNetwork.launchIn(this) + val enabledJob = underTest.isWifiEnabled.launchIn(this) - whenever(wifiManager.isWifiEnabled).thenReturn(true) - getNetworkCallback().onLost(NETWORK) + whenever(wifiManager.isWifiEnabled).thenReturn(true) + getNetworkCallback().onLost(NETWORK) - assertThat(underTest.isWifiEnabled.value).isTrue() + assertThat(underTest.isWifiEnabled.value).isTrue() - whenever(wifiManager.isWifiEnabled).thenReturn(false) - getNetworkCallback().onLost(NETWORK) + whenever(wifiManager.isWifiEnabled).thenReturn(false) + getNetworkCallback().onLost(NETWORK) - assertThat(underTest.isWifiEnabled.value).isFalse() + assertThat(underTest.isWifiEnabled.value).isFalse() - networkJob.cancel() - enabledJob.cancel() - } + networkJob.cancel() + enabledJob.cancel() + } @Test - fun isWifiEnabled_intentsReceived_valueUpdated() = runBlocking(IMMEDIATE) { - val intentFlow = MutableSharedFlow<Unit>() - whenever( - broadcastDispatcher.broadcastFlow( - any(), - nullable(), - anyInt(), - nullable(), - ) - ).thenReturn(intentFlow) - underTest = createRepo() + fun isWifiEnabled_intentsReceived_valueUpdated() = + runBlocking(IMMEDIATE) { + val intentFlow = MutableSharedFlow<Unit>() + whenever( + broadcastDispatcher.broadcastFlow( + any(), + nullable(), + anyInt(), + nullable(), + ) + ) + .thenReturn(intentFlow) + underTest = createRepo() - val job = underTest.isWifiEnabled.launchIn(this) + val job = underTest.isWifiEnabled.launchIn(this) - whenever(wifiManager.isWifiEnabled).thenReturn(true) - intentFlow.emit(Unit) + whenever(wifiManager.isWifiEnabled).thenReturn(true) + intentFlow.emit(Unit) - assertThat(underTest.isWifiEnabled.value).isTrue() + assertThat(underTest.isWifiEnabled.value).isTrue() - whenever(wifiManager.isWifiEnabled).thenReturn(false) - intentFlow.emit(Unit) + whenever(wifiManager.isWifiEnabled).thenReturn(false) + intentFlow.emit(Unit) - assertThat(underTest.isWifiEnabled.value).isFalse() + assertThat(underTest.isWifiEnabled.value).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun isWifiEnabled_bothIntentAndNetworkUpdates_valueAlwaysUpdated() = runBlocking(IMMEDIATE) { - val intentFlow = MutableSharedFlow<Unit>() - whenever( - broadcastDispatcher.broadcastFlow( - any(), - nullable(), - anyInt(), - nullable(), - ) - ).thenReturn(intentFlow) - underTest = createRepo() - - val networkJob = underTest.wifiNetwork.launchIn(this) - val enabledJob = underTest.isWifiEnabled.launchIn(this) - - whenever(wifiManager.isWifiEnabled).thenReturn(false) - intentFlow.emit(Unit) - assertThat(underTest.isWifiEnabled.value).isFalse() - - whenever(wifiManager.isWifiEnabled).thenReturn(true) - getNetworkCallback().onLost(NETWORK) - assertThat(underTest.isWifiEnabled.value).isTrue() - - whenever(wifiManager.isWifiEnabled).thenReturn(false) - getNetworkCallback().onCapabilitiesChanged( - NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO) - ) - assertThat(underTest.isWifiEnabled.value).isFalse() + fun isWifiEnabled_bothIntentAndNetworkUpdates_valueAlwaysUpdated() = + runBlocking(IMMEDIATE) { + val intentFlow = MutableSharedFlow<Unit>() + whenever( + broadcastDispatcher.broadcastFlow( + any(), + nullable(), + anyInt(), + nullable(), + ) + ) + .thenReturn(intentFlow) + underTest = createRepo() + + val networkJob = underTest.wifiNetwork.launchIn(this) + val enabledJob = underTest.isWifiEnabled.launchIn(this) + + whenever(wifiManager.isWifiEnabled).thenReturn(false) + intentFlow.emit(Unit) + assertThat(underTest.isWifiEnabled.value).isFalse() + + whenever(wifiManager.isWifiEnabled).thenReturn(true) + getNetworkCallback().onLost(NETWORK) + assertThat(underTest.isWifiEnabled.value).isTrue() + + whenever(wifiManager.isWifiEnabled).thenReturn(false) + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + assertThat(underTest.isWifiEnabled.value).isFalse() - whenever(wifiManager.isWifiEnabled).thenReturn(true) - intentFlow.emit(Unit) - assertThat(underTest.isWifiEnabled.value).isTrue() + whenever(wifiManager.isWifiEnabled).thenReturn(true) + intentFlow.emit(Unit) + assertThat(underTest.isWifiEnabled.value).isTrue() - networkJob.cancel() - enabledJob.cancel() - } + networkJob.cancel() + enabledJob.cancel() + } @Test - fun isWifiDefault_initiallyGetsDefault() = runBlocking(IMMEDIATE) { - val job = underTest.isWifiDefault.launchIn(this) + fun isWifiDefault_initiallyGetsDefault() = + runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) - assertThat(underTest.isWifiDefault.value).isFalse() + assertThat(underTest.isWifiDefault.value).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun isWifiDefault_wifiNetwork_isTrue() = runBlocking(IMMEDIATE) { - val job = underTest.isWifiDefault.launchIn(this) + fun isWifiDefault_wifiNetwork_isTrue() = + runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) - val wifiInfo = mock<WifiInfo>().apply { - whenever(this.ssid).thenReturn(SSID) - } + val wifiInfo = mock<WifiInfo>().apply { whenever(this.ssid).thenReturn(SSID) } - getDefaultNetworkCallback().onCapabilitiesChanged( - NETWORK, - createWifiNetworkCapabilities(wifiInfo) - ) + getDefaultNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo)) - assertThat(underTest.isWifiDefault.value).isTrue() + assertThat(underTest.isWifiDefault.value).isTrue() - job.cancel() - } + job.cancel() + } /** Regression test for b/266628069. */ @Test @@ -252,16 +255,18 @@ class WifiRepositoryImplTest : SysuiTestCase() { runBlocking(IMMEDIATE) { val job = underTest.isWifiDefault.launchIn(this) - val transportInfo = VpnTransportInfo( - /* type= */ 0, - /* sessionId= */ "sessionId", - ) - val networkCapabilities = mock<NetworkCapabilities>().also { - whenever(it.hasTransport(TRANSPORT_VPN)).thenReturn(true) - whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false) - whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false) - whenever(it.transportInfo).thenReturn(transportInfo) - } + val transportInfo = + VpnTransportInfo( + /* type= */ 0, + /* sessionId= */ "sessionId", + ) + val networkCapabilities = + mock<NetworkCapabilities>().also { + whenever(it.hasTransport(TRANSPORT_VPN)).thenReturn(true) + whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false) + whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false) + whenever(it.transportInfo).thenReturn(transportInfo) + } getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, networkCapabilities) @@ -276,16 +281,18 @@ class WifiRepositoryImplTest : SysuiTestCase() { runBlocking(IMMEDIATE) { val job = underTest.isWifiDefault.launchIn(this) - val transportInfo = VpnTransportInfo( - /* type= */ 0, - /* sessionId= */ "sessionId", - ) - val networkCapabilities = mock<NetworkCapabilities>().also { - whenever(it.hasTransport(TRANSPORT_VPN)).thenReturn(true) - whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true) - whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false) - whenever(it.transportInfo).thenReturn(transportInfo) - } + val transportInfo = + VpnTransportInfo( + /* type= */ 0, + /* sessionId= */ "sessionId", + ) + val networkCapabilities = + mock<NetworkCapabilities>().also { + whenever(it.hasTransport(TRANSPORT_VPN)).thenReturn(true) + whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true) + whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false) + whenever(it.transportInfo).thenReturn(transportInfo) + } getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, networkCapabilities) @@ -295,31 +302,34 @@ class WifiRepositoryImplTest : SysuiTestCase() { } @Test - fun isWifiDefault_cellularVcnNetwork_isTrue() = runBlocking(IMMEDIATE) { - val job = underTest.isWifiDefault.launchIn(this) + fun isWifiDefault_cellularVcnNetwork_isTrue() = + runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) - val capabilities = mock<NetworkCapabilities>().apply { - whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) - whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO)) - } + val capabilities = + mock<NetworkCapabilities>().apply { + whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO)) + } - getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) - assertThat(underTest.isWifiDefault.value).isTrue() + assertThat(underTest.isWifiDefault.value).isTrue() - job.cancel() - } + job.cancel() + } @Test fun wifiNetwork_cellularAndWifiTransports_usesCellular_isTrue() = runBlocking(IMMEDIATE) { val job = underTest.isWifiDefault.launchIn(this) - val capabilities = mock<NetworkCapabilities>().apply { - whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) - whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true) - whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO)) - } + val capabilities = + mock<NetworkCapabilities>().apply { + whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true) + whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO)) + } getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) @@ -329,117 +339,115 @@ class WifiRepositoryImplTest : SysuiTestCase() { } @Test - fun isWifiDefault_cellularNotVcnNetwork_isFalse() = runBlocking(IMMEDIATE) { - val job = underTest.isWifiDefault.launchIn(this) + fun isWifiDefault_cellularNotVcnNetwork_isFalse() = + runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) - val capabilities = mock<NetworkCapabilities>().apply { - whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) - whenever(this.transportInfo).thenReturn(mock()) - } + val capabilities = + mock<NetworkCapabilities>().apply { + whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(this.transportInfo).thenReturn(mock()) + } - getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) - assertThat(underTest.isWifiDefault.value).isFalse() + assertThat(underTest.isWifiDefault.value).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun isWifiDefault_wifiNetworkLost_isFalse() = runBlocking(IMMEDIATE) { - val job = underTest.isWifiDefault.launchIn(this) + fun isWifiDefault_wifiNetworkLost_isFalse() = + runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) - // First, add a network - getDefaultNetworkCallback() - .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) - assertThat(underTest.isWifiDefault.value).isTrue() + // First, add a network + getDefaultNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + assertThat(underTest.isWifiDefault.value).isTrue() - // WHEN the network is lost - getDefaultNetworkCallback().onLost(NETWORK) + // WHEN the network is lost + getDefaultNetworkCallback().onLost(NETWORK) - // THEN we update to false - assertThat(underTest.isWifiDefault.value).isFalse() + // THEN we update to false + assertThat(underTest.isWifiDefault.value).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_initiallyGetsDefault() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_initiallyGetsDefault() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - assertThat(latest).isEqualTo(WIFI_NETWORK_DEFAULT) + assertThat(latest).isEqualTo(WIFI_NETWORK_DEFAULT) - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_primaryWifiNetworkAdded_flowHasNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_primaryWifiNetworkAdded_flowHasNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - val wifiInfo = mock<WifiInfo>().apply { - whenever(this.ssid).thenReturn(SSID) - whenever(this.isPrimary).thenReturn(true) - } - val network = mock<Network>().apply { - whenever(this.getNetId()).thenReturn(NETWORK_ID) - } + val wifiInfo = + mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(SSID) + whenever(this.isPrimary).thenReturn(true) + } + val network = mock<Network>().apply { whenever(this.getNetId()).thenReturn(NETWORK_ID) } - getNetworkCallback().onCapabilitiesChanged(network, createWifiNetworkCapabilities(wifiInfo)) + getNetworkCallback() + .onCapabilitiesChanged(network, createWifiNetworkCapabilities(wifiInfo)) - assertThat(latest is WifiNetworkModel.Active).isTrue() - val latestActive = latest as WifiNetworkModel.Active - assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) - assertThat(latestActive.ssid).isEqualTo(SSID) + assertThat(latest is WifiNetworkModel.Active).isTrue() + val latestActive = latest as WifiNetworkModel.Active + assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) + assertThat(latestActive.ssid).isEqualTo(SSID) - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - val wifiInfo = mock<WifiInfo>().apply { - whenever(this.isPrimary).thenReturn(true) - whenever(this.isCarrierMerged).thenReturn(true) - } + val wifiInfo = + mock<WifiInfo>().apply { + whenever(this.isPrimary).thenReturn(true) + whenever(this.isCarrierMerged).thenReturn(true) + } - getNetworkCallback().onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo)) + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo)) - assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue() + assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue() - job.cancel() - } + job.cancel() + } @Test fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() = runBlocking(IMMEDIATE) { var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - val wifiInfo = mock<WifiInfo>().apply { - whenever(this.isPrimary).thenReturn(true) - whenever(this.isCarrierMerged).thenReturn(true) - whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID) - } + val wifiInfo = + mock<WifiInfo>().apply { + whenever(this.isPrimary).thenReturn(true) + whenever(this.isCarrierMerged).thenReturn(true) + whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID) + } - getNetworkCallback().onCapabilitiesChanged( - NETWORK, - createWifiNetworkCapabilities(wifiInfo), - ) + getNetworkCallback() + .onCapabilitiesChanged( + NETWORK, + createWifiNetworkCapabilities(wifiInfo), + ) assertThat(latest).isInstanceOf(WifiNetworkModel.Invalid::class.java) @@ -450,26 +458,25 @@ class WifiRepositoryImplTest : SysuiTestCase() { fun wifiNetwork_isCarrierMerged_getsCorrectValues() = runBlocking(IMMEDIATE) { var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) val rssi = -57 - val wifiInfo = mock<WifiInfo>().apply { - whenever(this.isPrimary).thenReturn(true) - whenever(this.isCarrierMerged).thenReturn(true) - whenever(this.rssi).thenReturn(rssi) - whenever(this.subscriptionId).thenReturn(567) - } + val wifiInfo = + mock<WifiInfo>().apply { + whenever(this.isPrimary).thenReturn(true) + whenever(this.isCarrierMerged).thenReturn(true) + whenever(this.rssi).thenReturn(rssi) + whenever(this.subscriptionId).thenReturn(567) + } whenever(wifiManager.calculateSignalLevel(rssi)).thenReturn(2) whenever(wifiManager.maxSignalLevel).thenReturn(5) - getNetworkCallback().onCapabilitiesChanged( - NETWORK, - createWifiNetworkCapabilities(wifiInfo), - ) + getNetworkCallback() + .onCapabilitiesChanged( + NETWORK, + createWifiNetworkCapabilities(wifiInfo), + ) assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue() val latestCarrierMerged = latest as WifiNetworkModel.CarrierMerged @@ -483,73 +490,71 @@ class WifiRepositoryImplTest : SysuiTestCase() { } @Test - fun wifiNetwork_notValidated_networkNotValidated() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_notValidated_networkNotValidated() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - getNetworkCallback().onCapabilitiesChanged( - NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = false) - ) + getNetworkCallback() + .onCapabilitiesChanged( + NETWORK, + createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = false) + ) - assertThat((latest as WifiNetworkModel.Active).isValidated).isFalse() + assertThat((latest as WifiNetworkModel.Active).isValidated).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_validated_networkValidated() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_validated_networkValidated() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - getNetworkCallback().onCapabilitiesChanged( - NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = true) - ) + getNetworkCallback() + .onCapabilitiesChanged( + NETWORK, + createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = true) + ) - assertThat((latest as WifiNetworkModel.Active).isValidated).isTrue() + assertThat((latest as WifiNetworkModel.Active).isValidated).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_nonPrimaryWifiNetworkAdded_flowHasNoNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_nonPrimaryWifiNetworkAdded_flowHasNoNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - val wifiInfo = mock<WifiInfo>().apply { - whenever(this.ssid).thenReturn(SSID) - whenever(this.isPrimary).thenReturn(false) - } + val wifiInfo = + mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(SSID) + whenever(this.isPrimary).thenReturn(false) + } - getNetworkCallback().onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo)) + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo)) - assertThat(latest is WifiNetworkModel.Inactive).isTrue() + assertThat(latest is WifiNetworkModel.Inactive).isTrue() - job.cancel() - } + job.cancel() + } /** Regression test for b/266628069. */ @Test fun wifiNetwork_transportInfoIsNotWifi_flowHasNoNetwork() = runBlocking(IMMEDIATE) { var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) - - val transportInfo = VpnTransportInfo( - /* type= */ 0, - /* sessionId= */ "sessionId", - ) + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) + + val transportInfo = + VpnTransportInfo( + /* type= */ 0, + /* sessionId= */ "sessionId", + ) getNetworkCallback() .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(transportInfo)) @@ -559,86 +564,82 @@ class WifiRepositoryImplTest : SysuiTestCase() { } @Test - fun wifiNetwork_cellularVcnNetworkAdded_flowHasNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_cellularVcnNetworkAdded_flowHasNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - val capabilities = mock<NetworkCapabilities>().apply { - whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) - whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO)) - } + val capabilities = + mock<NetworkCapabilities>().apply { + whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO)) + } - getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) + getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) - assertThat(latest is WifiNetworkModel.Active).isTrue() - val latestActive = latest as WifiNetworkModel.Active - assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) - assertThat(latestActive.ssid).isEqualTo(SSID) + assertThat(latest is WifiNetworkModel.Active).isTrue() + val latestActive = latest as WifiNetworkModel.Active + assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) + assertThat(latestActive.ssid).isEqualTo(SSID) - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_nonPrimaryCellularVcnNetworkAdded_flowHasNoNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) - - val wifiInfo = mock<WifiInfo>().apply { - whenever(this.ssid).thenReturn(SSID) - whenever(this.isPrimary).thenReturn(false) - } - val capabilities = mock<NetworkCapabilities>().apply { - whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) - whenever(this.transportInfo).thenReturn(VcnTransportInfo(wifiInfo)) - } + fun wifiNetwork_nonPrimaryCellularVcnNetworkAdded_flowHasNoNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) + + val wifiInfo = + mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(SSID) + whenever(this.isPrimary).thenReturn(false) + } + val capabilities = + mock<NetworkCapabilities>().apply { + whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(this.transportInfo).thenReturn(VcnTransportInfo(wifiInfo)) + } - getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) + getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) - assertThat(latest is WifiNetworkModel.Inactive).isTrue() + assertThat(latest is WifiNetworkModel.Inactive).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_cellularNotVcnNetworkAdded_flowHasNoNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_cellularNotVcnNetworkAdded_flowHasNoNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - val capabilities = mock<NetworkCapabilities>().apply { - whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) - whenever(this.transportInfo).thenReturn(mock()) - } + val capabilities = + mock<NetworkCapabilities>().apply { + whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(this.transportInfo).thenReturn(mock()) + } - getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) + getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) - assertThat(latest is WifiNetworkModel.Inactive).isTrue() + assertThat(latest is WifiNetworkModel.Inactive).isTrue() - job.cancel() - } + job.cancel() + } @Test fun wifiNetwork_cellularAndWifiTransports_usesCellular() = runBlocking(IMMEDIATE) { var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) - - val capabilities = mock<NetworkCapabilities>().apply { - whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) - whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true) - whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO)) - } + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) + + val capabilities = + mock<NetworkCapabilities>().apply { + whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true) + whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO)) + } getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) @@ -651,309 +652,280 @@ class WifiRepositoryImplTest : SysuiTestCase() { } @Test - fun wifiNetwork_newPrimaryWifiNetwork_flowHasNewNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) - - // Start with the original network - getNetworkCallback() - .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + fun wifiNetwork_newPrimaryWifiNetwork_flowHasNewNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - // WHEN we update to a new primary network - val newNetworkId = 456 - val newNetwork = mock<Network>().apply { - whenever(this.getNetId()).thenReturn(newNetworkId) - } - val newSsid = "CD" - val newWifiInfo = mock<WifiInfo>().apply { - whenever(this.ssid).thenReturn(newSsid) - whenever(this.isPrimary).thenReturn(true) - } + // Start with the original network + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + + // WHEN we update to a new primary network + val newNetworkId = 456 + val newNetwork = + mock<Network>().apply { whenever(this.getNetId()).thenReturn(newNetworkId) } + val newSsid = "CD" + val newWifiInfo = + mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(newSsid) + whenever(this.isPrimary).thenReturn(true) + } - getNetworkCallback().onCapabilitiesChanged( - newNetwork, createWifiNetworkCapabilities(newWifiInfo) - ) + getNetworkCallback() + .onCapabilitiesChanged(newNetwork, createWifiNetworkCapabilities(newWifiInfo)) - // THEN we use the new network - assertThat(latest is WifiNetworkModel.Active).isTrue() - val latestActive = latest as WifiNetworkModel.Active - assertThat(latestActive.networkId).isEqualTo(newNetworkId) - assertThat(latestActive.ssid).isEqualTo(newSsid) + // THEN we use the new network + assertThat(latest is WifiNetworkModel.Active).isTrue() + val latestActive = latest as WifiNetworkModel.Active + assertThat(latestActive.networkId).isEqualTo(newNetworkId) + assertThat(latestActive.ssid).isEqualTo(newSsid) - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_newNonPrimaryWifiNetwork_flowHasOldNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) - - // Start with the original network - getNetworkCallback() - .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + fun wifiNetwork_newNonPrimaryWifiNetwork_flowHasOldNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - // WHEN we notify of a new but non-primary network - val newNetworkId = 456 - val newNetwork = mock<Network>().apply { - whenever(this.getNetId()).thenReturn(newNetworkId) - } - val newSsid = "EF" - val newWifiInfo = mock<WifiInfo>().apply { - whenever(this.ssid).thenReturn(newSsid) - whenever(this.isPrimary).thenReturn(false) - } + // Start with the original network + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + + // WHEN we notify of a new but non-primary network + val newNetworkId = 456 + val newNetwork = + mock<Network>().apply { whenever(this.getNetId()).thenReturn(newNetworkId) } + val newSsid = "EF" + val newWifiInfo = + mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(newSsid) + whenever(this.isPrimary).thenReturn(false) + } - getNetworkCallback().onCapabilitiesChanged( - newNetwork, createWifiNetworkCapabilities(newWifiInfo) - ) + getNetworkCallback() + .onCapabilitiesChanged(newNetwork, createWifiNetworkCapabilities(newWifiInfo)) - // THEN we still use the original network - assertThat(latest is WifiNetworkModel.Active).isTrue() - val latestActive = latest as WifiNetworkModel.Active - assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) - assertThat(latestActive.ssid).isEqualTo(SSID) + // THEN we still use the original network + assertThat(latest is WifiNetworkModel.Active).isTrue() + val latestActive = latest as WifiNetworkModel.Active + assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) + assertThat(latestActive.ssid).isEqualTo(SSID) - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_newNetworkCapabilities_flowHasNewData() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) - - val wifiInfo = mock<WifiInfo>().apply { - whenever(this.ssid).thenReturn(SSID) - whenever(this.isPrimary).thenReturn(true) - } + fun wifiNetwork_newNetworkCapabilities_flowHasNewData() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - // Start with the original network - getNetworkCallback().onCapabilitiesChanged( - NETWORK, createWifiNetworkCapabilities(wifiInfo, isValidated = true) - ) + val wifiInfo = + mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(SSID) + whenever(this.isPrimary).thenReturn(true) + } - // WHEN we keep the same network ID but change the SSID - val newSsid = "CD" - val newWifiInfo = mock<WifiInfo>().apply { - whenever(this.ssid).thenReturn(newSsid) - whenever(this.isPrimary).thenReturn(true) - } + // Start with the original network + getNetworkCallback() + .onCapabilitiesChanged( + NETWORK, + createWifiNetworkCapabilities(wifiInfo, isValidated = true) + ) + + // WHEN we keep the same network ID but change the SSID + val newSsid = "CD" + val newWifiInfo = + mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(newSsid) + whenever(this.isPrimary).thenReturn(true) + } - getNetworkCallback().onCapabilitiesChanged( - NETWORK, createWifiNetworkCapabilities(newWifiInfo, isValidated = false) - ) + getNetworkCallback() + .onCapabilitiesChanged( + NETWORK, + createWifiNetworkCapabilities(newWifiInfo, isValidated = false) + ) - // THEN we've updated to the new SSID - assertThat(latest is WifiNetworkModel.Active).isTrue() - val latestActive = latest as WifiNetworkModel.Active - assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) - assertThat(latestActive.ssid).isEqualTo(newSsid) - assertThat(latestActive.isValidated).isFalse() + // THEN we've updated to the new SSID + assertThat(latest is WifiNetworkModel.Active).isTrue() + val latestActive = latest as WifiNetworkModel.Active + assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) + assertThat(latestActive.ssid).isEqualTo(newSsid) + assertThat(latestActive.isValidated).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_noCurrentNetwork_networkLost_flowHasNoNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_noCurrentNetwork_networkLost_flowHasNoNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - // WHEN we receive #onLost without any #onCapabilitiesChanged beforehand - getNetworkCallback().onLost(NETWORK) + // WHEN we receive #onLost without any #onCapabilitiesChanged beforehand + getNetworkCallback().onLost(NETWORK) - // THEN there's no crash and we still have no network - assertThat(latest is WifiNetworkModel.Inactive).isTrue() + // THEN there's no crash and we still have no network + assertThat(latest is WifiNetworkModel.Inactive).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_currentNetworkLost_flowHasNoNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_currentNetworkLost_flowHasNoNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - getNetworkCallback() - .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) - assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(NETWORK_ID) + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(NETWORK_ID) - // WHEN we lose our current network - getNetworkCallback().onLost(NETWORK) + // WHEN we lose our current network + getNetworkCallback().onLost(NETWORK) - // THEN we update to no network - assertThat(latest is WifiNetworkModel.Inactive).isTrue() + // THEN we update to no network + assertThat(latest is WifiNetworkModel.Inactive).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_unknownNetworkLost_flowHasPreviousNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_unknownNetworkLost_flowHasPreviousNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - getNetworkCallback() - .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) - assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(NETWORK_ID) + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(NETWORK_ID) - // WHEN we lose an unknown network - val unknownNetwork = mock<Network>().apply { - whenever(this.getNetId()).thenReturn(543) - } - getNetworkCallback().onLost(unknownNetwork) + // WHEN we lose an unknown network + val unknownNetwork = mock<Network>().apply { whenever(this.getNetId()).thenReturn(543) } + getNetworkCallback().onLost(unknownNetwork) - // THEN we still have our previous network - assertThat(latest is WifiNetworkModel.Active).isTrue() - val latestActive = latest as WifiNetworkModel.Active - assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) - assertThat(latestActive.ssid).isEqualTo(SSID) + // THEN we still have our previous network + assertThat(latest is WifiNetworkModel.Active).isTrue() + val latestActive = latest as WifiNetworkModel.Active + assertThat(latestActive.networkId).isEqualTo(NETWORK_ID) + assertThat(latestActive.ssid).isEqualTo(SSID) - job.cancel() - } + job.cancel() + } @Test - fun wifiNetwork_notCurrentNetworkLost_flowHasCurrentNetwork() = runBlocking(IMMEDIATE) { - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) + fun wifiNetwork_notCurrentNetworkLost_flowHasCurrentNetwork() = + runBlocking(IMMEDIATE) { + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) - getNetworkCallback() - .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) - assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(NETWORK_ID) + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(NETWORK_ID) - // WHEN we update to a new network... - val newNetworkId = 89 - val newNetwork = mock<Network>().apply { - whenever(this.getNetId()).thenReturn(newNetworkId) - } - getNetworkCallback().onCapabilitiesChanged( - newNetwork, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO) - ) - // ...and lose the old network - getNetworkCallback().onLost(NETWORK) + // WHEN we update to a new network... + val newNetworkId = 89 + val newNetwork = + mock<Network>().apply { whenever(this.getNetId()).thenReturn(newNetworkId) } + getNetworkCallback() + .onCapabilitiesChanged(newNetwork, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + // ...and lose the old network + getNetworkCallback().onLost(NETWORK) - // THEN we still have the new network - assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(newNetworkId) + // THEN we still have the new network + assertThat((latest as WifiNetworkModel.Active).networkId).isEqualTo(newNetworkId) - job.cancel() - } + job.cancel() + } /** Regression test for b/244173280. */ @Test - fun wifiNetwork_multipleSubscribers_newSubscribersGetCurrentValue() = runBlocking(IMMEDIATE) { - var latest1: WifiNetworkModel? = null - val job1 = underTest - .wifiNetwork - .onEach { latest1 = it } - .launchIn(this) - - getNetworkCallback() - .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) - - assertThat(latest1 is WifiNetworkModel.Active).isTrue() - val latest1Active = latest1 as WifiNetworkModel.Active - assertThat(latest1Active.networkId).isEqualTo(NETWORK_ID) - assertThat(latest1Active.ssid).isEqualTo(SSID) - - // WHEN we add a second subscriber after having already emitted a value - var latest2: WifiNetworkModel? = null - val job2 = underTest - .wifiNetwork - .onEach { latest2 = it } - .launchIn(this) - - // THEN the second subscribe receives the already-emitted value - assertThat(latest2 is WifiNetworkModel.Active).isTrue() - val latest2Active = latest2 as WifiNetworkModel.Active - assertThat(latest2Active.networkId).isEqualTo(NETWORK_ID) - assertThat(latest2Active.ssid).isEqualTo(SSID) - - job1.cancel() - job2.cancel() - } + fun wifiNetwork_multipleSubscribers_newSubscribersGetCurrentValue() = + runBlocking(IMMEDIATE) { + var latest1: WifiNetworkModel? = null + val job1 = underTest.wifiNetwork.onEach { latest1 = it }.launchIn(this) + + getNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + + assertThat(latest1 is WifiNetworkModel.Active).isTrue() + val latest1Active = latest1 as WifiNetworkModel.Active + assertThat(latest1Active.networkId).isEqualTo(NETWORK_ID) + assertThat(latest1Active.ssid).isEqualTo(SSID) + + // WHEN we add a second subscriber after having already emitted a value + var latest2: WifiNetworkModel? = null + val job2 = underTest.wifiNetwork.onEach { latest2 = it }.launchIn(this) + + // THEN the second subscribe receives the already-emitted value + assertThat(latest2 is WifiNetworkModel.Active).isTrue() + val latest2Active = latest2 as WifiNetworkModel.Active + assertThat(latest2Active.networkId).isEqualTo(NETWORK_ID) + assertThat(latest2Active.ssid).isEqualTo(SSID) + + job1.cancel() + job2.cancel() + } @Test - fun wifiActivity_callbackGivesNone_activityFlowHasNone() = runBlocking(IMMEDIATE) { - var latest: DataActivityModel? = null - val job = underTest - .wifiActivity - .onEach { latest = it } - .launchIn(this) + fun wifiActivity_callbackGivesNone_activityFlowHasNone() = + runBlocking(IMMEDIATE) { + var latest: DataActivityModel? = null + val job = underTest.wifiActivity.onEach { latest = it }.launchIn(this) - getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_NONE) + getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_NONE) - assertThat(latest).isEqualTo( - DataActivityModel(hasActivityIn = false, hasActivityOut = false) - ) + assertThat(latest) + .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false)) - job.cancel() - } + job.cancel() + } @Test - fun wifiActivity_callbackGivesIn_activityFlowHasIn() = runBlocking(IMMEDIATE) { - var latest: DataActivityModel? = null - val job = underTest - .wifiActivity - .onEach { latest = it } - .launchIn(this) + fun wifiActivity_callbackGivesIn_activityFlowHasIn() = + runBlocking(IMMEDIATE) { + var latest: DataActivityModel? = null + val job = underTest.wifiActivity.onEach { latest = it }.launchIn(this) - getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_IN) + getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_IN) - assertThat(latest).isEqualTo( - DataActivityModel(hasActivityIn = true, hasActivityOut = false) - ) + assertThat(latest) + .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = false)) - job.cancel() - } + job.cancel() + } @Test - fun wifiActivity_callbackGivesOut_activityFlowHasOut() = runBlocking(IMMEDIATE) { - var latest: DataActivityModel? = null - val job = underTest - .wifiActivity - .onEach { latest = it } - .launchIn(this) + fun wifiActivity_callbackGivesOut_activityFlowHasOut() = + runBlocking(IMMEDIATE) { + var latest: DataActivityModel? = null + val job = underTest.wifiActivity.onEach { latest = it }.launchIn(this) - getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_OUT) + getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_OUT) - assertThat(latest).isEqualTo( - DataActivityModel(hasActivityIn = false, hasActivityOut = true) - ) + assertThat(latest) + .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = true)) - job.cancel() - } + job.cancel() + } @Test - fun wifiActivity_callbackGivesInout_activityFlowHasInAndOut() = runBlocking(IMMEDIATE) { - var latest: DataActivityModel? = null - val job = underTest - .wifiActivity - .onEach { latest = it } - .launchIn(this) + fun wifiActivity_callbackGivesInout_activityFlowHasInAndOut() = + runBlocking(IMMEDIATE) { + var latest: DataActivityModel? = null + val job = underTest.wifiActivity.onEach { latest = it }.launchIn(this) - getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT) + getTrafficStateCallback().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT) - assertThat(latest).isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = true)) + assertThat(latest) + .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = true)) - job.cancel() - } + job.cancel() + } private fun createRepo(): WifiRepositoryImpl { return WifiRepositoryImpl( @@ -998,14 +970,13 @@ class WifiRepositoryImplTest : SysuiTestCase() { private companion object { const val NETWORK_ID = 45 - val NETWORK = mock<Network>().apply { - whenever(this.getNetId()).thenReturn(NETWORK_ID) - } + val NETWORK = mock<Network>().apply { whenever(this.getNetId()).thenReturn(NETWORK_ID) } const val SSID = "AB" - val PRIMARY_WIFI_INFO: WifiInfo = mock<WifiInfo>().apply { - whenever(this.ssid).thenReturn(SSID) - whenever(this.isPrimary).thenReturn(true) - } + val PRIMARY_WIFI_INFO: WifiInfo = + mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(SSID) + whenever(this.isPrimary).thenReturn(true) + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt index 089a170aa2be..fc2277b9c803 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt @@ -22,8 +22,8 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -57,10 +57,7 @@ class WifiInteractorImplTest : SysuiTestCase() { wifiRepository.setWifiNetwork(WifiNetworkModel.Unavailable) var latest: String? = "default" - val job = underTest - .ssid - .onEach { latest = it } - .launchIn(this) + val job = underTest.ssid.onEach { latest = it }.launchIn(this) assertThat(latest).isNull() @@ -68,238 +65,223 @@ class WifiInteractorImplTest : SysuiTestCase() { } @Test - fun ssid_inactiveNetwork_outputsNull() = runBlocking(IMMEDIATE) { - wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive) + fun ssid_inactiveNetwork_outputsNull() = + runBlocking(IMMEDIATE) { + wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive) - var latest: String? = "default" - val job = underTest - .ssid - .onEach { latest = it } - .launchIn(this) + var latest: String? = "default" + val job = underTest.ssid.onEach { latest = it }.launchIn(this) - assertThat(latest).isNull() + assertThat(latest).isNull() - job.cancel() - } + job.cancel() + } @Test - fun ssid_carrierMergedNetwork_outputsNull() = runBlocking(IMMEDIATE) { - wifiRepository.setWifiNetwork( - WifiNetworkModel.CarrierMerged(networkId = 1, subscriptionId = 2, level = 1) - ) + fun ssid_carrierMergedNetwork_outputsNull() = + runBlocking(IMMEDIATE) { + wifiRepository.setWifiNetwork( + WifiNetworkModel.CarrierMerged(networkId = 1, subscriptionId = 2, level = 1) + ) - var latest: String? = "default" - val job = underTest - .ssid - .onEach { latest = it } - .launchIn(this) + var latest: String? = "default" + val job = underTest.ssid.onEach { latest = it }.launchIn(this) - assertThat(latest).isNull() + assertThat(latest).isNull() - job.cancel() - } + job.cancel() + } @Test - fun ssid_isPasspointAccessPoint_outputsPasspointName() = runBlocking(IMMEDIATE) { - wifiRepository.setWifiNetwork(WifiNetworkModel.Active( - networkId = 1, - level = 1, - isPasspointAccessPoint = true, - passpointProviderFriendlyName = "friendly", - )) - - var latest: String? = null - val job = underTest - .ssid - .onEach { latest = it } - .launchIn(this) - - assertThat(latest).isEqualTo("friendly") - - job.cancel() - } + fun ssid_isPasspointAccessPoint_outputsPasspointName() = + runBlocking(IMMEDIATE) { + wifiRepository.setWifiNetwork( + WifiNetworkModel.Active( + networkId = 1, + level = 1, + isPasspointAccessPoint = true, + passpointProviderFriendlyName = "friendly", + ) + ) + + var latest: String? = null + val job = underTest.ssid.onEach { latest = it }.launchIn(this) + + assertThat(latest).isEqualTo("friendly") + + job.cancel() + } @Test - fun ssid_isOnlineSignUpForPasspoint_outputsPasspointName() = runBlocking(IMMEDIATE) { - wifiRepository.setWifiNetwork(WifiNetworkModel.Active( - networkId = 1, - level = 1, - isOnlineSignUpForPasspointAccessPoint = true, - passpointProviderFriendlyName = "friendly", - )) - - var latest: String? = null - val job = underTest - .ssid - .onEach { latest = it } - .launchIn(this) - - assertThat(latest).isEqualTo("friendly") - - job.cancel() - } + fun ssid_isOnlineSignUpForPasspoint_outputsPasspointName() = + runBlocking(IMMEDIATE) { + wifiRepository.setWifiNetwork( + WifiNetworkModel.Active( + networkId = 1, + level = 1, + isOnlineSignUpForPasspointAccessPoint = true, + passpointProviderFriendlyName = "friendly", + ) + ) + + var latest: String? = null + val job = underTest.ssid.onEach { latest = it }.launchIn(this) + + assertThat(latest).isEqualTo("friendly") + + job.cancel() + } @Test - fun ssid_unknownSsid_outputsNull() = runBlocking(IMMEDIATE) { - wifiRepository.setWifiNetwork(WifiNetworkModel.Active( - networkId = 1, - level = 1, - ssid = WifiManager.UNKNOWN_SSID, - )) - - var latest: String? = "default" - val job = underTest - .ssid - .onEach { latest = it } - .launchIn(this) - - assertThat(latest).isNull() - - job.cancel() - } + fun ssid_unknownSsid_outputsNull() = + runBlocking(IMMEDIATE) { + wifiRepository.setWifiNetwork( + WifiNetworkModel.Active( + networkId = 1, + level = 1, + ssid = WifiManager.UNKNOWN_SSID, + ) + ) + + var latest: String? = "default" + val job = underTest.ssid.onEach { latest = it }.launchIn(this) + + assertThat(latest).isNull() + + job.cancel() + } @Test - fun ssid_validSsid_outputsSsid() = runBlocking(IMMEDIATE) { - wifiRepository.setWifiNetwork(WifiNetworkModel.Active( - networkId = 1, - level = 1, - ssid = "MyAwesomeWifiNetwork", - )) - - var latest: String? = null - val job = underTest - .ssid - .onEach { latest = it } - .launchIn(this) - - assertThat(latest).isEqualTo("MyAwesomeWifiNetwork") - - job.cancel() - } + fun ssid_validSsid_outputsSsid() = + runBlocking(IMMEDIATE) { + wifiRepository.setWifiNetwork( + WifiNetworkModel.Active( + networkId = 1, + level = 1, + ssid = "MyAwesomeWifiNetwork", + ) + ) + + var latest: String? = null + val job = underTest.ssid.onEach { latest = it }.launchIn(this) + + assertThat(latest).isEqualTo("MyAwesomeWifiNetwork") + + job.cancel() + } @Test - fun isEnabled_matchesRepoIsEnabled() = runBlocking(IMMEDIATE) { - var latest: Boolean? = null - val job = underTest - .isEnabled - .onEach { latest = it } - .launchIn(this) - - wifiRepository.setIsWifiEnabled(true) - yield() - assertThat(latest).isTrue() - - wifiRepository.setIsWifiEnabled(false) - yield() - assertThat(latest).isFalse() - - wifiRepository.setIsWifiEnabled(true) - yield() - assertThat(latest).isTrue() - - job.cancel() - } + fun isEnabled_matchesRepoIsEnabled() = + runBlocking(IMMEDIATE) { + var latest: Boolean? = null + val job = underTest.isEnabled.onEach { latest = it }.launchIn(this) + + wifiRepository.setIsWifiEnabled(true) + yield() + assertThat(latest).isTrue() + + wifiRepository.setIsWifiEnabled(false) + yield() + assertThat(latest).isFalse() + + wifiRepository.setIsWifiEnabled(true) + yield() + assertThat(latest).isTrue() + + job.cancel() + } @Test - fun isDefault_matchesRepoIsDefault() = runBlocking(IMMEDIATE) { - var latest: Boolean? = null - val job = underTest - .isDefault - .onEach { latest = it } - .launchIn(this) - - wifiRepository.setIsWifiDefault(true) - yield() - assertThat(latest).isTrue() - - wifiRepository.setIsWifiDefault(false) - yield() - assertThat(latest).isFalse() - - wifiRepository.setIsWifiDefault(true) - yield() - assertThat(latest).isTrue() - - job.cancel() - } + fun isDefault_matchesRepoIsDefault() = + runBlocking(IMMEDIATE) { + var latest: Boolean? = null + val job = underTest.isDefault.onEach { latest = it }.launchIn(this) + + wifiRepository.setIsWifiDefault(true) + yield() + assertThat(latest).isTrue() + + wifiRepository.setIsWifiDefault(false) + yield() + assertThat(latest).isFalse() + + wifiRepository.setIsWifiDefault(true) + yield() + assertThat(latest).isTrue() + + job.cancel() + } @Test - fun wifiNetwork_matchesRepoWifiNetwork() = runBlocking(IMMEDIATE) { - val wifiNetwork = WifiNetworkModel.Active( - networkId = 45, - isValidated = true, - level = 3, - ssid = "AB", - passpointProviderFriendlyName = "friendly" - ) - wifiRepository.setWifiNetwork(wifiNetwork) - - var latest: WifiNetworkModel? = null - val job = underTest - .wifiNetwork - .onEach { latest = it } - .launchIn(this) - - assertThat(latest).isEqualTo(wifiNetwork) - - job.cancel() - } + fun wifiNetwork_matchesRepoWifiNetwork() = + runBlocking(IMMEDIATE) { + val wifiNetwork = + WifiNetworkModel.Active( + networkId = 45, + isValidated = true, + level = 3, + ssid = "AB", + passpointProviderFriendlyName = "friendly" + ) + wifiRepository.setWifiNetwork(wifiNetwork) + + var latest: WifiNetworkModel? = null + val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this) + + assertThat(latest).isEqualTo(wifiNetwork) + + job.cancel() + } @Test - fun activity_matchesRepoWifiActivity() = runBlocking(IMMEDIATE) { - var latest: DataActivityModel? = null - val job = underTest - .activity - .onEach { latest = it } - .launchIn(this) - - val activity1 = DataActivityModel(hasActivityIn = true, hasActivityOut = true) - wifiRepository.setWifiActivity(activity1) - yield() - assertThat(latest).isEqualTo(activity1) - - val activity2 = DataActivityModel(hasActivityIn = false, hasActivityOut = false) - wifiRepository.setWifiActivity(activity2) - yield() - assertThat(latest).isEqualTo(activity2) - - val activity3 = DataActivityModel(hasActivityIn = true, hasActivityOut = false) - wifiRepository.setWifiActivity(activity3) - yield() - assertThat(latest).isEqualTo(activity3) - - job.cancel() - } + fun activity_matchesRepoWifiActivity() = + runBlocking(IMMEDIATE) { + var latest: DataActivityModel? = null + val job = underTest.activity.onEach { latest = it }.launchIn(this) + + val activity1 = DataActivityModel(hasActivityIn = true, hasActivityOut = true) + wifiRepository.setWifiActivity(activity1) + yield() + assertThat(latest).isEqualTo(activity1) + + val activity2 = DataActivityModel(hasActivityIn = false, hasActivityOut = false) + wifiRepository.setWifiActivity(activity2) + yield() + assertThat(latest).isEqualTo(activity2) + + val activity3 = DataActivityModel(hasActivityIn = true, hasActivityOut = false) + wifiRepository.setWifiActivity(activity3) + yield() + assertThat(latest).isEqualTo(activity3) + + job.cancel() + } @Test - fun isForceHidden_repoHasWifiHidden_outputsTrue() = runBlocking(IMMEDIATE) { - connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.WIFI)) + fun isForceHidden_repoHasWifiHidden_outputsTrue() = + runBlocking(IMMEDIATE) { + connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.WIFI)) - var latest: Boolean? = null - val job = underTest - .isForceHidden - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this) - assertThat(latest).isTrue() + assertThat(latest).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun isForceHidden_repoDoesNotHaveWifiHidden_outputsFalse() = runBlocking(IMMEDIATE) { - connectivityRepository.setForceHiddenIcons(setOf()) + fun isForceHidden_repoDoesNotHaveWifiHidden_outputsFalse() = + runBlocking(IMMEDIATE) { + connectivityRepository.setForceHiddenIcons(setOf()) - var latest: Boolean? = null - val job = underTest - .isForceHidden - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this) - assertThat(latest).isFalse() + assertThat(latest).isFalse() - job.cancel() - } + job.cancel() + } } private val IMMEDIATE = Dispatchers.Main.immediate diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt index 824cebdc3c08..ab4e93ceee84 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt @@ -14,14 +14,14 @@ * limitations under the License. */ -package com.android.systemui.statusbar.pipeline.wifi.data.model +package com.android.systemui.statusbar.pipeline.wifi.shared.model import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableRowLogger -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel.Active.Companion.MAX_VALID_LEVEL -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel.Companion.MIN_VALID_LEVEL +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel.Active.Companion.MAX_VALID_LEVEL +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel.Companion.MIN_VALID_LEVEL import com.google.common.truth.Truth.assertThat import org.junit.Test 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 b8ace2f04a61..64810d2a9308 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 @@ -36,13 +36,12 @@ import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.Airpla import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel 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 @@ -62,16 +61,10 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() { private lateinit var testableLooper: TestableLooper - @Mock - private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags - @Mock - private lateinit var logger: ConnectivityPipelineLogger - @Mock - private lateinit var tableLogBuffer: TableLogBuffer - @Mock - private lateinit var connectivityConstants: ConnectivityConstants - @Mock - private lateinit var wifiConstants: WifiConstants + @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags + @Mock private lateinit var tableLogBuffer: TableLogBuffer + @Mock private lateinit var connectivityConstants: ConnectivityConstants + @Mock private lateinit var wifiConstants: WifiConstants private lateinit var airplaneModeRepository: FakeAirplaneModeRepository private lateinit var connectivityRepository: FakeConnectivityRepository private lateinit var wifiRepository: FakeWifiRepository @@ -91,25 +84,27 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() { wifiRepository.setIsWifiEnabled(true) interactor = WifiInteractorImpl(connectivityRepository, wifiRepository) scope = CoroutineScope(Dispatchers.Unconfined) - airplaneModeViewModel = AirplaneModeViewModelImpl( - AirplaneModeInteractor( - airplaneModeRepository, - connectivityRepository, - ), - logger, - scope, - ) - viewModel = WifiViewModel( - airplaneModeViewModel, - connectivityConstants, - context, - logger, - tableLogBuffer, - interactor, - scope, - statusBarPipelineFlags, - wifiConstants, - ).home + airplaneModeViewModel = + AirplaneModeViewModelImpl( + AirplaneModeInteractor( + airplaneModeRepository, + connectivityRepository, + ), + tableLogBuffer, + scope, + ) + viewModel = + WifiViewModel( + airplaneModeViewModel, + connectivityConstants, + context, + tableLogBuffer, + interactor, + scope, + statusBarPipelineFlags, + wifiConstants, + ) + .home } // Note: The following tests are more like integration tests, since they stand up a full diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt index b9328377772a..12b16640c0c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt @@ -33,14 +33,13 @@ import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.Airpla import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel.Companion.NO_INTERNET import com.google.common.truth.Truth.assertThat @@ -68,7 +67,6 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase private lateinit var underTest: WifiViewModel @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags - @Mock private lateinit var logger: ConnectivityPipelineLogger @Mock private lateinit var tableLogBuffer: TableLogBuffer @Mock private lateinit var connectivityConstants: ConnectivityConstants @Mock private lateinit var wifiConstants: WifiConstants @@ -94,7 +92,7 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase airplaneModeRepository, connectivityRepository, ), - logger, + tableLogBuffer, scope, ) } @@ -125,7 +123,6 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase airplaneModeViewModel, connectivityConstants, context, - logger, tableLogBuffer, interactor, scope, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt index e5cfec9c08c0..7a62cb8a377d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt @@ -25,15 +25,14 @@ import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.Airpla import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository -import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.CoroutineScope @@ -59,7 +58,6 @@ class WifiViewModelTest : SysuiTestCase() { private lateinit var underTest: WifiViewModel @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags - @Mock private lateinit var logger: ConnectivityPipelineLogger @Mock private lateinit var tableLogBuffer: TableLogBuffer @Mock private lateinit var connectivityConstants: ConnectivityConstants @Mock private lateinit var wifiConstants: WifiConstants @@ -79,14 +77,15 @@ class WifiViewModelTest : SysuiTestCase() { wifiRepository.setIsWifiEnabled(true) interactor = WifiInteractorImpl(connectivityRepository, wifiRepository) scope = CoroutineScope(IMMEDIATE) - airplaneModeViewModel = AirplaneModeViewModelImpl( - AirplaneModeInteractor( - airplaneModeRepository, - connectivityRepository, - ), - logger, - scope, - ) + airplaneModeViewModel = + AirplaneModeViewModelImpl( + AirplaneModeInteractor( + airplaneModeRepository, + connectivityRepository, + ), + tableLogBuffer, + scope, + ) createAndSetViewModel() } @@ -104,451 +103,385 @@ class WifiViewModelTest : SysuiTestCase() { // instances. There are also some tests that verify all 3 instances received the same data. @Test - fun wifiIcon_allLocationViewModelsReceiveSameData() = runBlocking(IMMEDIATE) { - var latestHome: WifiIcon? = null - val jobHome = underTest - .home - .wifiIcon - .onEach { latestHome = it } - .launchIn(this) - - var latestKeyguard: WifiIcon? = null - val jobKeyguard = underTest - .keyguard - .wifiIcon - .onEach { latestKeyguard = it } - .launchIn(this) - - var latestQs: WifiIcon? = null - val jobQs = underTest - .qs - .wifiIcon - .onEach { latestQs = it } - .launchIn(this) - - wifiRepository.setWifiNetwork( - WifiNetworkModel.Active( - NETWORK_ID, - isValidated = true, - level = 1 + fun wifiIcon_allLocationViewModelsReceiveSameData() = + runBlocking(IMMEDIATE) { + var latestHome: WifiIcon? = null + val jobHome = underTest.home.wifiIcon.onEach { latestHome = it }.launchIn(this) + + var latestKeyguard: WifiIcon? = null + val jobKeyguard = + underTest.keyguard.wifiIcon.onEach { latestKeyguard = it }.launchIn(this) + + var latestQs: WifiIcon? = null + val jobQs = underTest.qs.wifiIcon.onEach { latestQs = it }.launchIn(this) + + wifiRepository.setWifiNetwork( + WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 1) ) - ) - yield() + yield() - assertThat(latestHome).isInstanceOf(WifiIcon.Visible::class.java) - assertThat(latestHome).isEqualTo(latestKeyguard) - assertThat(latestKeyguard).isEqualTo(latestQs) + assertThat(latestHome).isInstanceOf(WifiIcon.Visible::class.java) + assertThat(latestHome).isEqualTo(latestKeyguard) + assertThat(latestKeyguard).isEqualTo(latestQs) - jobHome.cancel() - jobKeyguard.cancel() - jobQs.cancel() - } + jobHome.cancel() + jobKeyguard.cancel() + jobQs.cancel() + } @Test - fun activity_showActivityConfigFalse_outputsFalse() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(false) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - - var activityIn: Boolean? = null - val activityInJob = underTest - .home - .isActivityInViewVisible - .onEach { activityIn = it } - .launchIn(this) - - var activityOut: Boolean? = null - val activityOutJob = underTest - .home - .isActivityOutViewVisible - .onEach { activityOut = it } - .launchIn(this) - - var activityContainer: Boolean? = null - val activityContainerJob = underTest - .home - .isActivityContainerVisible - .onEach { activityContainer = it } - .launchIn(this) - - // Verify that on launch, we receive false. - assertThat(activityIn).isFalse() - assertThat(activityOut).isFalse() - assertThat(activityContainer).isFalse() - - activityInJob.cancel() - activityOutJob.cancel() - activityContainerJob.cancel() - } + fun activity_showActivityConfigFalse_outputsFalse() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(false) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + + var activityIn: Boolean? = null + val activityInJob = + underTest.home.isActivityInViewVisible.onEach { activityIn = it }.launchIn(this) + + var activityOut: Boolean? = null + val activityOutJob = + underTest.home.isActivityOutViewVisible.onEach { activityOut = it }.launchIn(this) + + var activityContainer: Boolean? = null + val activityContainerJob = + underTest.home.isActivityContainerVisible + .onEach { activityContainer = it } + .launchIn(this) + + // Verify that on launch, we receive false. + assertThat(activityIn).isFalse() + assertThat(activityOut).isFalse() + assertThat(activityContainer).isFalse() + + activityInJob.cancel() + activityOutJob.cancel() + activityContainerJob.cancel() + } @Test - fun activity_showActivityConfigFalse_noUpdatesReceived() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(false) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - - var activityIn: Boolean? = null - val activityInJob = underTest - .home - .isActivityInViewVisible - .onEach { activityIn = it } - .launchIn(this) - - var activityOut: Boolean? = null - val activityOutJob = underTest - .home - .isActivityOutViewVisible - .onEach { activityOut = it } - .launchIn(this) - - var activityContainer: Boolean? = null - val activityContainerJob = underTest - .home - .isActivityContainerVisible - .onEach { activityContainer = it } - .launchIn(this) - - // WHEN we update the repo to have activity - val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true) - wifiRepository.setWifiActivity(activity) - yield() - - // THEN we didn't update to the new activity (because our config is false) - assertThat(activityIn).isFalse() - assertThat(activityOut).isFalse() - assertThat(activityContainer).isFalse() - - activityInJob.cancel() - activityOutJob.cancel() - activityContainerJob.cancel() - } + fun activity_showActivityConfigFalse_noUpdatesReceived() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(false) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + + var activityIn: Boolean? = null + val activityInJob = + underTest.home.isActivityInViewVisible.onEach { activityIn = it }.launchIn(this) + + var activityOut: Boolean? = null + val activityOutJob = + underTest.home.isActivityOutViewVisible.onEach { activityOut = it }.launchIn(this) + + var activityContainer: Boolean? = null + val activityContainerJob = + underTest.home.isActivityContainerVisible + .onEach { activityContainer = it } + .launchIn(this) + + // WHEN we update the repo to have activity + val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true) + wifiRepository.setWifiActivity(activity) + yield() + + // THEN we didn't update to the new activity (because our config is false) + assertThat(activityIn).isFalse() + assertThat(activityOut).isFalse() + assertThat(activityContainer).isFalse() + + activityInJob.cancel() + activityOutJob.cancel() + activityContainerJob.cancel() + } @Test - fun activity_nullSsid_outputsFalse() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() + fun activity_nullSsid_outputsFalse() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() - wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, ssid = null, level = 1)) - - var activityIn: Boolean? = null - val activityInJob = underTest - .home - .isActivityInViewVisible - .onEach { activityIn = it } - .launchIn(this) - - var activityOut: Boolean? = null - val activityOutJob = underTest - .home - .isActivityOutViewVisible - .onEach { activityOut = it } - .launchIn(this) - - var activityContainer: Boolean? = null - val activityContainerJob = underTest - .home - .isActivityContainerVisible - .onEach { activityContainer = it } - .launchIn(this) - - // WHEN we update the repo to have activity - val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true) - wifiRepository.setWifiActivity(activity) - yield() - - // THEN we still output false because our network's SSID is null - assertThat(activityIn).isFalse() - assertThat(activityOut).isFalse() - assertThat(activityContainer).isFalse() - - activityInJob.cancel() - activityOutJob.cancel() - activityContainerJob.cancel() - } + wifiRepository.setWifiNetwork( + WifiNetworkModel.Active(NETWORK_ID, ssid = null, level = 1) + ) + + var activityIn: Boolean? = null + val activityInJob = + underTest.home.isActivityInViewVisible.onEach { activityIn = it }.launchIn(this) + + var activityOut: Boolean? = null + val activityOutJob = + underTest.home.isActivityOutViewVisible.onEach { activityOut = it }.launchIn(this) + + var activityContainer: Boolean? = null + val activityContainerJob = + underTest.home.isActivityContainerVisible + .onEach { activityContainer = it } + .launchIn(this) + + // WHEN we update the repo to have activity + val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true) + wifiRepository.setWifiActivity(activity) + yield() + + // THEN we still output false because our network's SSID is null + assertThat(activityIn).isFalse() + assertThat(activityOut).isFalse() + assertThat(activityContainer).isFalse() + + activityInJob.cancel() + activityOutJob.cancel() + activityContainerJob.cancel() + } @Test - fun activity_allLocationViewModelsReceiveSameData() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - - var latestHome: Boolean? = null - val jobHome = underTest - .home - .isActivityInViewVisible - .onEach { latestHome = it } - .launchIn(this) - - var latestKeyguard: Boolean? = null - val jobKeyguard = underTest - .keyguard - .isActivityInViewVisible - .onEach { latestKeyguard = it } - .launchIn(this) - - var latestQs: Boolean? = null - val jobQs = underTest - .qs - .isActivityInViewVisible - .onEach { latestQs = it } - .launchIn(this) - - val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true) - wifiRepository.setWifiActivity(activity) - yield() - - assertThat(latestHome).isTrue() - assertThat(latestKeyguard).isTrue() - assertThat(latestQs).isTrue() - - jobHome.cancel() - jobKeyguard.cancel() - jobQs.cancel() - } + fun activity_allLocationViewModelsReceiveSameData() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + + var latestHome: Boolean? = null + val jobHome = + underTest.home.isActivityInViewVisible.onEach { latestHome = it }.launchIn(this) + + var latestKeyguard: Boolean? = null + val jobKeyguard = + underTest.keyguard.isActivityInViewVisible + .onEach { latestKeyguard = it } + .launchIn(this) + + var latestQs: Boolean? = null + val jobQs = underTest.qs.isActivityInViewVisible.onEach { latestQs = it }.launchIn(this) + + val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true) + wifiRepository.setWifiActivity(activity) + yield() + + assertThat(latestHome).isTrue() + assertThat(latestKeyguard).isTrue() + assertThat(latestQs).isTrue() + + jobHome.cancel() + jobKeyguard.cancel() + jobQs.cancel() + } @Test - fun activityIn_hasActivityInTrue_outputsTrue() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + fun activityIn_hasActivityInTrue_outputsTrue() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - var latest: Boolean? = null - val job = underTest - .home - .isActivityInViewVisible - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = underTest.home.isActivityInViewVisible.onEach { latest = it }.launchIn(this) - val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = false) - wifiRepository.setWifiActivity(activity) - yield() + val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = false) + wifiRepository.setWifiActivity(activity) + yield() - assertThat(latest).isTrue() + assertThat(latest).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun activityIn_hasActivityInFalse_outputsFalse() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + fun activityIn_hasActivityInFalse_outputsFalse() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - var latest: Boolean? = null - val job = underTest - .home - .isActivityInViewVisible - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = underTest.home.isActivityInViewVisible.onEach { latest = it }.launchIn(this) - val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = true) - wifiRepository.setWifiActivity(activity) - yield() + val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = true) + wifiRepository.setWifiActivity(activity) + yield() - assertThat(latest).isFalse() + assertThat(latest).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun activityOut_hasActivityOutTrue_outputsTrue() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + fun activityOut_hasActivityOutTrue_outputsTrue() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - var latest: Boolean? = null - val job = underTest - .home - .isActivityOutViewVisible - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = underTest.home.isActivityOutViewVisible.onEach { latest = it }.launchIn(this) - val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = true) - wifiRepository.setWifiActivity(activity) - yield() + val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = true) + wifiRepository.setWifiActivity(activity) + yield() - assertThat(latest).isTrue() + assertThat(latest).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun activityOut_hasActivityOutFalse_outputsFalse() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + fun activityOut_hasActivityOutFalse_outputsFalse() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - var latest: Boolean? = null - val job = underTest - .home - .isActivityOutViewVisible - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = underTest.home.isActivityOutViewVisible.onEach { latest = it }.launchIn(this) - val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = false) - wifiRepository.setWifiActivity(activity) - yield() + val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = false) + wifiRepository.setWifiActivity(activity) + yield() - assertThat(latest).isFalse() + assertThat(latest).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun activityContainer_hasActivityInTrue_outputsTrue() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + fun activityContainer_hasActivityInTrue_outputsTrue() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - var latest: Boolean? = null - val job = underTest - .home - .isActivityContainerVisible - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = + underTest.home.isActivityContainerVisible.onEach { latest = it }.launchIn(this) - val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = false) - wifiRepository.setWifiActivity(activity) - yield() + val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = false) + wifiRepository.setWifiActivity(activity) + yield() - assertThat(latest).isTrue() + assertThat(latest).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun activityContainer_hasActivityOutTrue_outputsTrue() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + fun activityContainer_hasActivityOutTrue_outputsTrue() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - var latest: Boolean? = null - val job = underTest - .home - .isActivityContainerVisible - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = + underTest.home.isActivityContainerVisible.onEach { latest = it }.launchIn(this) - val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = true) - wifiRepository.setWifiActivity(activity) - yield() + val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = true) + wifiRepository.setWifiActivity(activity) + yield() - assertThat(latest).isTrue() + assertThat(latest).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun activityContainer_inAndOutTrue_outputsTrue() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + fun activityContainer_inAndOutTrue_outputsTrue() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - var latest: Boolean? = null - val job = underTest - .home - .isActivityContainerVisible - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = + underTest.home.isActivityContainerVisible.onEach { latest = it }.launchIn(this) - val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true) - wifiRepository.setWifiActivity(activity) - yield() + val activity = DataActivityModel(hasActivityIn = true, hasActivityOut = true) + wifiRepository.setWifiActivity(activity) + yield() - assertThat(latest).isTrue() + assertThat(latest).isTrue() - job.cancel() - } + job.cancel() + } @Test - fun activityContainer_inAndOutFalse_outputsFalse() = runBlocking(IMMEDIATE) { - whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) - createAndSetViewModel() - wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + fun activityContainer_inAndOutFalse_outputsFalse() = + runBlocking(IMMEDIATE) { + whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true) + createAndSetViewModel() + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) - var latest: Boolean? = null - val job = underTest - .home - .isActivityContainerVisible - .onEach { latest = it } - .launchIn(this) + var latest: Boolean? = null + val job = + underTest.home.isActivityContainerVisible.onEach { latest = it }.launchIn(this) - val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = false) - wifiRepository.setWifiActivity(activity) - yield() + val activity = DataActivityModel(hasActivityIn = false, hasActivityOut = false) + wifiRepository.setWifiActivity(activity) + yield() - assertThat(latest).isFalse() + assertThat(latest).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun airplaneSpacer_notAirplaneMode_outputsFalse() = runBlocking(IMMEDIATE) { - var latest: Boolean? = null - val job = underTest - .qs - .isAirplaneSpacerVisible - .onEach { latest = it } - .launchIn(this) + fun airplaneSpacer_notAirplaneMode_outputsFalse() = + runBlocking(IMMEDIATE) { + var latest: Boolean? = null + val job = underTest.qs.isAirplaneSpacerVisible.onEach { latest = it }.launchIn(this) - airplaneModeRepository.setIsAirplaneMode(false) - yield() + airplaneModeRepository.setIsAirplaneMode(false) + yield() - assertThat(latest).isFalse() + assertThat(latest).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun airplaneSpacer_airplaneForceHidden_outputsFalse() = runBlocking(IMMEDIATE) { - var latest: Boolean? = null - val job = underTest - .qs - .isAirplaneSpacerVisible - .onEach { latest = it } - .launchIn(this) + fun airplaneSpacer_airplaneForceHidden_outputsFalse() = + runBlocking(IMMEDIATE) { + var latest: Boolean? = null + val job = underTest.qs.isAirplaneSpacerVisible.onEach { latest = it }.launchIn(this) - airplaneModeRepository.setIsAirplaneMode(true) - connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.AIRPLANE)) - yield() + airplaneModeRepository.setIsAirplaneMode(true) + connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.AIRPLANE)) + yield() - assertThat(latest).isFalse() + assertThat(latest).isFalse() - job.cancel() - } + job.cancel() + } @Test - fun airplaneSpacer_airplaneIconVisible_outputsTrue() = runBlocking(IMMEDIATE) { - var latest: Boolean? = null - val job = underTest - .qs - .isAirplaneSpacerVisible - .onEach { latest = it } - .launchIn(this) + fun airplaneSpacer_airplaneIconVisible_outputsTrue() = + runBlocking(IMMEDIATE) { + var latest: Boolean? = null + val job = underTest.qs.isAirplaneSpacerVisible.onEach { latest = it }.launchIn(this) - airplaneModeRepository.setIsAirplaneMode(true) - yield() + airplaneModeRepository.setIsAirplaneMode(true) + yield() - assertThat(latest).isTrue() + assertThat(latest).isTrue() - job.cancel() - } + job.cancel() + } private fun createAndSetViewModel() { // [WifiViewModel] creates its flows as soon as it's instantiated, and some of those flow // creations rely on certain config values that we mock out in individual tests. This method // allows tests to create the view model only after those configs are correctly set up. - underTest = WifiViewModel( - airplaneModeViewModel, - connectivityConstants, - context, - logger, - tableLogBuffer, - interactor, - scope, - statusBarPipelineFlags, - wifiConstants, - ) + underTest = + WifiViewModel( + airplaneModeViewModel, + connectivityConstants, + context, + tableLogBuffer, + interactor, + scope, + statusBarPipelineFlags, + wifiConstants, + ) } companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt index 3d75967f0c98..a87e61aae207 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt @@ -28,6 +28,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.shade.NotificationPanelViewController @@ -112,7 +113,8 @@ class FoldAodAnimationControllerTest : SysuiTestCase() { KeyguardInteractor( repository = keyguardRepository, commandQueue = commandQueue, - featureFlags = featureFlags + featureFlags = featureFlags, + bouncerRepository = FakeKeyguardBouncerRepository(), ) // Needs to be run on the main thread diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt index 0257ebd5c6d4..d00acb89d228 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt @@ -38,6 +38,7 @@ import com.android.systemui.common.shared.model.Text import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.plugins.ActivityStarter @@ -143,6 +144,7 @@ class UserInteractorTest : SysuiTestCase() { repository = keyguardRepository, commandQueue = commandQueue, featureFlags = featureFlags, + bouncerRepository = FakeKeyguardBouncerRepository(), ), manager = manager, headlessSystemUserMode = headlessSystemUserMode, diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt index 2fedb875b3e3..22fc32af1b80 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt @@ -31,6 +31,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.Text import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.plugins.ActivityStarter @@ -251,6 +252,7 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() { repository = keyguardRepository, commandQueue = commandQueue, featureFlags = featureFlags, + bouncerRepository = FakeKeyguardBouncerRepository(), ), featureFlags = featureFlags, manager = manager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt index 166b90943847..a2bd8d365192 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt @@ -29,6 +29,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.Text import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.plugins.ActivityStarter @@ -152,7 +153,8 @@ class UserSwitcherViewModelTest : SysuiTestCase() { KeyguardInteractor( repository = keyguardRepository, commandQueue = commandQueue, - featureFlags = featureFlags + featureFlags = featureFlags, + bouncerRepository = FakeKeyguardBouncerRepository(), ), featureFlags = featureFlags, manager = manager, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/TestCoroutineSchedulerUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/TestCoroutineSchedulerUtils.kt new file mode 100644 index 000000000000..84e2a5c7d4c2 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/TestCoroutineSchedulerUtils.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.coroutines + +import kotlin.time.Duration +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestCoroutineScheduler + +/** + * Moves the virtual clock of this dispatcher forward by the specified [Duration]. + * + * @see [TestCoroutineScheduler.advanceTimeBy] + */ +fun TestCoroutineScheduler.advanceTimeBy(duration: Duration) { + advanceTimeBy(duration.inWholeMilliseconds) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt index d0383e996121..337421974562 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt @@ -57,10 +57,10 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository { override val bouncerPromptReason = 0 override val bouncerErrorMessage: CharSequence? = null private val _isAlternateBouncerVisible = MutableStateFlow(false) - override val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow() + override val alternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow() override var lastAlternateBouncerVisibleTime: Long = 0L private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false) - override val isAlternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow() + override val alternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow() override fun setPrimaryScrimmed(isScrimmed: Boolean) { _primaryBouncerScrimmed.value = isScrimmed diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt index 065fe8903e40..1a371c73550c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt @@ -84,9 +84,6 @@ class FakeKeyguardRepository : KeyguardRepository { private val _isUdfpsSupported = MutableStateFlow(false) - private val _isBouncerShowing = MutableStateFlow(false) - override val isBouncerShowing: Flow<Boolean> = _isBouncerShowing - private val _isKeyguardGoingAway = MutableStateFlow(false) override val isKeyguardGoingAway: Flow<Boolean> = _isKeyguardGoingAway @@ -153,10 +150,6 @@ class FakeKeyguardRepository : KeyguardRepository { _wakefulnessModel.value = model } - fun setBouncerShowing(isShowing: Boolean) { - _isBouncerShowing.value = isShowing - } - fun setBiometricUnlockState(state: BiometricUnlockModel) { _biometricUnlockState.tryEmit(state) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java index 95b62a12c621..bdf1aff7f985 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java @@ -49,7 +49,7 @@ public class FakeKeyguardStateController implements KeyguardStateController { } @Override - public boolean isBouncerShowing() { + public boolean isPrimaryBouncerShowing() { return false; } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java index 787bfb00a554..7d390415952e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java @@ -228,7 +228,16 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession> @Override public void onError(int errorCode, int vendorCode) { - super.onError(errorCode, vendorCode); + if (getContext().getResources().getBoolean(R.bool.config_powerPressMapping) + && errorCode == BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR + && vendorCode == getContext().getResources() + .getInteger(R.integer.config_powerPressCode)) { + // Translating vendor code to internal code + super.onError(BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED, + 0 /* vendorCode */); + } else { + super.onError(errorCode, vendorCode); + } if (errorCode == BiometricFingerprintConstants.FINGERPRINT_ERROR_BAD_CALIBRATION) { BiometricNotificationUtils.showBadCalibrationNotification(getContext()); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index 612d90670888..14b19fb9461a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -37,6 +37,7 @@ import android.os.RemoteException; import android.util.Slog; import android.view.accessibility.AccessibilityManager; +import com.android.internal.R; import com.android.server.biometrics.HardwareAuthTokenUtils; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; @@ -143,7 +144,17 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps } }); mCallback.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH); - super.onAcquired(acquiredInfo, vendorCode); + + if (getContext().getResources().getBoolean(R.bool.config_powerPressMapping) + && acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR + && vendorCode == getContext().getResources() + .getInteger(R.integer.config_powerPressCode)) { + // Translating vendor code to internal code + super.onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED, + 0 /* vendorCode */); + } else { + super.onAcquired(acquiredInfo, vendorCode); + } } @Override @@ -270,8 +281,5 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps } @Override - public void onPowerPressed() { - onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED, - 0 /* vendorCode */); - } + public void onPowerPressed() {} } diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index bb44ddf98394..482dd7a726b2 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -135,10 +135,10 @@ import javax.xml.datatype.DatatypeConfigurationException; * </thermalThrottling> * * <refreshRate> + * <defaultRefreshRateInHbmHdr>75</defaultRefreshRateInHbmHdr> + * <defaultRefreshRateInHbmSunlight>75</defaultRefreshRateInHbmSunlight> * <lowerBlockingZoneConfigs> * <defaultRefreshRate>75</defaultRefreshRate> - * <defaultRefreshRateInHbmHdr>75</defaultRefreshRateInHbmHdr> - * <defaultRefreshRateInHbmSunlight>75</defaultRefreshRateInHbmSunlight> * <blockingZoneThreshold> * <displayBrightnessPoint> * <lux>50</lux> diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java index f74356debd0f..97ab58764e1e 100644 --- a/services/core/java/com/android/server/dreams/DreamController.java +++ b/services/core/java/com/android/server/dreams/DreamController.java @@ -42,6 +42,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Iterator; import java.util.NoSuchElementException; +import java.util.Objects; /** * Internal controller for starting and stopping the current dream and managing related state. @@ -119,10 +120,20 @@ final class DreamController { + ", isPreviewMode=" + isPreviewMode + ", canDoze=" + canDoze + ", userId=" + userId + ", reason='" + reason + "'"); - if (mCurrentDream != null) { - mPreviousDreams.add(mCurrentDream); - } + final DreamRecord oldDream = mCurrentDream; mCurrentDream = new DreamRecord(token, name, isPreviewMode, canDoze, userId, wakeLock); + if (oldDream != null) { + if (!oldDream.mWakingGently) { + // We will stop these previous dreams once the new dream is started. + mPreviousDreams.add(oldDream); + } else if (Objects.equals(oldDream.mName, mCurrentDream.mName)) { + // We are attempting to start a dream that is currently waking up gently. + // Let's silently stop the old instance here to clear the dream state. + // This should happen after the new mCurrentDream is set to avoid announcing + // a "dream stopped" state. + stopDreamInstance(/* immediately */ true, "restarting same dream", oldDream); + } + } mCurrentDream.mDreamStartTime = SystemClock.elapsedRealtime(); MetricsLogger.visible(mContext, diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index e37222f406a9..8b04c3adf34b 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -22,6 +22,7 @@ import static android.app.PendingIntent.FLAG_MUTABLE; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; +import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION; import static android.content.pm.LauncherApps.FLAG_CACHE_BUBBLE_SHORTCUTS; import static android.content.pm.LauncherApps.FLAG_CACHE_NOTIFICATION_SHORTCUTS; import static android.content.pm.LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS; @@ -1123,6 +1124,9 @@ public class LauncherAppsService extends SystemService { if (options.isApplyMultipleTaskFlagForShortcut()) { intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); } + if (options.isApplyNoUserActionFlagForShortcut()) { + intents[0].addFlags(FLAG_ACTIVITY_NO_USER_ACTION); + } } intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intents[0].setSourceBounds(sourceBounds); diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 0ea6157dd2a4..87f985ac42eb 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -181,6 +181,42 @@ public class AppTransitionController { || !transitionGoodToGoForTaskFragments()) { return; } + final boolean isRecentsInOpening = mDisplayContent.mOpeningApps.stream().anyMatch( + ConfigurationContainer::isActivityTypeRecents); + // In order to avoid visual clutter caused by a conflict between app transition + // animation and recents animation, app transition is delayed until recents finishes. + // One exceptional case. When 3P launcher is used and a user taps a task screenshot in + // task switcher (isRecentsInOpening=true), app transition must start even though + // recents is running. Otherwise app transition is blocked until timeout (b/232984498). + // When 1P launcher is used, this animation is controlled by the launcher outside of + // the app transition, so delaying app transition doesn't cause visible delay. After + // recents finishes, app transition is handled just to commit visibility on apps. + if (!isRecentsInOpening) { + final ArraySet<WindowContainer> participants = new ArraySet<>(); + participants.addAll(mDisplayContent.mOpeningApps); + participants.addAll(mDisplayContent.mChangingContainers); + boolean deferForRecents = false; + for (int i = 0; i < participants.size(); i++) { + WindowContainer wc = participants.valueAt(i); + final ActivityRecord activity = getAppFromContainer(wc); + if (activity == null) { + continue; + } + // Don't defer recents animation if one of activity isn't running for it, that one + // might be started from quickstep. + if (!activity.isAnimating(PARENTS, ANIMATION_TYPE_RECENTS)) { + deferForRecents = false; + break; + } + deferForRecents = true; + } + if (deferForRecents) { + ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, + "Delaying app transition for recents animation to finish"); + return; + } + } + Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady"); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "**** GOOD TO GO"); @@ -1249,27 +1285,12 @@ public class AppTransitionController { "Delaying app transition for screen rotation animation to finish"); return false; } - final boolean isRecentsInOpening = mDisplayContent.mOpeningApps.stream().anyMatch( - ConfigurationContainer::isActivityTypeRecents); for (int i = 0; i < apps.size(); i++) { WindowContainer wc = apps.valueAt(i); final ActivityRecord activity = getAppFromContainer(wc); if (activity == null) { continue; } - // In order to avoid visual clutter caused by a conflict between app transition - // animation and recents animation, app transition is delayed until recents finishes. - // One exceptional case. When 3P launcher is used and a user taps a task screenshot in - // task switcher (isRecentsInOpening=true), app transition must start even though - // recents is running. Otherwise app transition is blocked until timeout (b/232984498). - // When 1P launcher is used, this animation is controlled by the launcher outside of - // the app transition, so delaying app transition doesn't cause visible delay. After - // recents finishes, app transition is handled just to commit visibility on apps. - if (!isRecentsInOpening && activity.isAnimating(PARENTS, ANIMATION_TYPE_RECENTS)) { - ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, - "Delaying app transition for recents animation to finish"); - return false; - } ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Check opening app=%s: allDrawn=%b startingDisplayed=%b " + "startingMoved=%b isRelaunching()=%b startingWindow=%s", diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index d2e8ad1f66b9..5a481f438827 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -648,10 +648,9 @@ final class LetterboxUiController { if (mLetterbox != null) { outBounds.set(mLetterbox.getInnerFrame()); final WindowState w = mActivityRecord.findMainWindow(); - if (w == null) { - return; + if (w != null) { + adjustBoundsForTaskbar(w, outBounds); } - adjustBoundsIfNeeded(w, outBounds); } else { outBounds.setEmpty(); } @@ -1001,7 +1000,7 @@ final class LetterboxUiController { @VisibleForTesting boolean shouldShowLetterboxUi(WindowState mainWindow) { - return isSurfaceReadyAndVisible(mainWindow) && mainWindow.areAppWindowBoundsLetterboxed() + return isSurfaceVisible(mainWindow) && mainWindow.areAppWindowBoundsLetterboxed() // Check for FLAG_SHOW_WALLPAPER explicitly instead of using // WindowContainer#showWallpaper because the later will return true when this // activity is using blurred wallpaper for letterbox background. @@ -1009,11 +1008,8 @@ final class LetterboxUiController { } @VisibleForTesting - boolean isSurfaceReadyAndVisible(WindowState mainWindow) { - boolean surfaceReady = mainWindow.isDrawn() // Regular case - // Waiting for relayoutWindow to call preserveSurface - || mainWindow.isDragResizeChanged(); - return surfaceReady && (mActivityRecord.isVisible() + boolean isSurfaceVisible(WindowState mainWindow) { + return mainWindow.isOnScreen() && (mActivityRecord.isVisible() || mActivityRecord.isVisibleRequested()); } @@ -1086,7 +1082,12 @@ final class LetterboxUiController { // It is important to call {@link #adjustBoundsIfNeeded} before {@link cropBounds.offsetTo} // because taskbar bounds used in {@link #adjustBoundsIfNeeded} // are in screen coordinates - adjustBoundsIfNeeded(mainWindow, cropBounds); + adjustBoundsForTaskbar(mainWindow, cropBounds); + + final float scale = mainWindow.mInvGlobalScale; + if (scale != 1f && scale > 0f) { + cropBounds.scale(scale); + } // ActivityRecord bounds are in screen coordinates while (0,0) for activity's surface // control is in the top left corner of an app window so offsetting bounds @@ -1139,7 +1140,7 @@ final class LetterboxUiController { return null; } - private void adjustBoundsIfNeeded(final WindowState mainWindow, final Rect bounds) { + private void adjustBoundsForTaskbar(final WindowState mainWindow, final Rect bounds) { // Rounded corners should be displayed above the taskbar. When taskbar is hidden, // an insets frame is equal to a navigation bar which shouldn't affect position of // rounded corners since apps are expected to handle navigation bar inset. @@ -1153,11 +1154,6 @@ final class LetterboxUiController { // Rounded corners should be displayed above the expanded taskbar. bounds.bottom = Math.min(bounds.bottom, expandedTaskbarOrNull.getFrame().top); } - - final float scale = mainWindow.mInvGlobalScale; - if (scale != 1f && scale > 0f) { - bounds.scale(scale); - } } private int getInsetsStateCornerRadius( diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java index 3c735e335e75..4915c642abd9 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; +import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -35,6 +37,7 @@ import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.content.ComponentName; +import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.common.ICancellationSignal; import android.hardware.biometrics.common.OperationContext; @@ -54,6 +57,7 @@ import android.testing.TestableContext; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.internal.R; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.CallbackWithProbe; @@ -335,6 +339,21 @@ public class FingerprintAuthenticationClientTest { showHideOverlay(c -> c.onLockoutPermanent()); } + @Test + public void testPowerPressForwardsErrorMessage() throws RemoteException { + final FingerprintAuthenticationClient client = createClient(); + final int testVendorPowerPressCode = 1; + when(mContext.getOrCreateTestableResources().getResources() + .getBoolean(R.bool.config_powerPressMapping)).thenReturn(true); + when(mContext.getOrCreateTestableResources().getResources() + .getInteger(R.integer.config_powerPressCode)).thenReturn(testVendorPowerPressCode); + + client.onError(FINGERPRINT_ERROR_VENDOR, testVendorPowerPressCode); + + verify(mClientMonitorCallbackConverter).onError(anyInt(), anyInt(), + eq(BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED), anyInt()); + } + private void showHideOverlay(Consumer<FingerprintAuthenticationClient> block) throws RemoteException { final FingerprintAuthenticationClient client = createClient(); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java index 837b55397416..7e29a768db4a 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java @@ -16,7 +16,7 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; -import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED; +import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR; import static com.google.common.truth.Truth.assertThat; @@ -28,10 +28,10 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.same; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.fingerprint.ISession; import android.hardware.biometrics.fingerprint.PointerContext; @@ -48,6 +48,7 @@ import android.testing.TestableContext; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.internal.R; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.CallbackWithProbe; @@ -66,7 +67,6 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import java.util.ArrayList; import java.util.function.Consumer; @Presubmit @@ -258,11 +258,16 @@ public class FingerprintEnrollClientTest { @Test public void testPowerPressForwardsAcquireMessage() throws RemoteException { final FingerprintEnrollClient client = createClient(); - client.start(mCallback); - client.onPowerPressed(); + final int testVendorPowerPressCode = 1; + when(mContext.getOrCreateTestableResources().getResources() + .getBoolean(R.bool.config_powerPressMapping)).thenReturn(true); + when(mContext.getOrCreateTestableResources().getResources() + .getInteger(R.integer.config_powerPressCode)).thenReturn(testVendorPowerPressCode); + + client.onAcquired(FINGERPRINT_ACQUIRED_VENDOR, testVendorPowerPressCode); verify(mClientMonitorCallbackConverter).onAcquired(anyInt(), - eq(FINGERPRINT_ACQUIRED_POWER_PRESSED), anyInt()); + eq(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED), anyInt()); } private void showHideOverlay(Consumer<FingerprintEnrollClient> block) diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java index 0d20f1772d0b..656c07b1acee 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java @@ -494,6 +494,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase { doReturn(insets).when(mainWindow).getInsetsState(); doReturn(attrs).when(mainWindow).getAttrs(); doReturn(true).when(mainWindow).isDrawn(); + doReturn(true).when(mainWindow).isOnScreen(); doReturn(false).when(mainWindow).isLetterboxedForDisplayCutout(); doReturn(true).when(mainWindow).areAppWindowBoundsLetterboxed(); doReturn(true).when(mLetterboxConfiguration).isLetterboxActivityCornersRounded(); 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 c4269137199e..de84655986ef 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -502,7 +502,7 @@ public class SizeCompatTests extends WindowTestsBase { spyOn(mActivity.mLetterboxUiController); doReturn(true).when(mActivity.mLetterboxUiController) - .isSurfaceReadyAndVisible(any()); + .isSurfaceVisible(any()); assertTrue(mActivity.mLetterboxUiController.shouldShowLetterboxUi( mActivity.findMainWindow())); @@ -1434,6 +1434,65 @@ public class SizeCompatTests extends WindowTestsBase { } @Test + public void testGetLetterboxInnerBounds_noScalingApplied() { + // Set up a display in portrait and ignoring orientation request. + final int dw = 1400; + final int dh = 2800; + setUpDisplaySizeWithApp(dw, dh); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + + // Rotate display to landscape. + rotateDisplay(mActivity.mDisplayContent, ROTATION_90); + + // Portrait fixed app without max aspect. + prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE); + + // Need a window to call adjustBoundsForTaskbar with. + addWindowToActivity(mActivity); + + // App should launch in fullscreen. + assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio()); + assertFalse(mActivity.inSizeCompatMode()); + + // Activity inherits max bounds from TaskDisplayArea. + assertMaxBoundsInheritDisplayAreaBounds(); + + // Rotate display to portrait. + rotateDisplay(mActivity.mDisplayContent, ROTATION_0); + + final Rect rotatedDisplayBounds = new Rect(mActivity.mDisplayContent.getBounds()); + final Rect rotatedActivityBounds = new Rect(mActivity.getBounds()); + assertTrue(rotatedDisplayBounds.width() < rotatedDisplayBounds.height()); + + // App should be in size compat. + assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio()); + assertScaled(); + assertThat(mActivity.inSizeCompatMode()).isTrue(); + assertActivityMaxBoundsSandboxed(); + + + final int scale = dh / dw; + + // App bounds should be dh / scale x dw / scale + assertEquals(dw, rotatedDisplayBounds.width()); + assertEquals(dh, rotatedDisplayBounds.height()); + + assertEquals(dh / scale, rotatedActivityBounds.width()); + assertEquals(dw / scale, rotatedActivityBounds.height()); + + // Compute the frames of the window and invoke {@link ActivityRecord#layoutLetterbox}. + mActivity.mRootWindowContainer.performSurfacePlacement(); + + LetterboxDetails letterboxDetails = mActivity.mLetterboxUiController.getLetterboxDetails(); + + assertEquals(dh / scale, letterboxDetails.getLetterboxInnerBounds().width()); + assertEquals(dw / scale, letterboxDetails.getLetterboxInnerBounds().height()); + + assertEquals(dw, letterboxDetails.getLetterboxFullBounds().width()); + assertEquals(dh, letterboxDetails.getLetterboxFullBounds().height()); + } + + @Test public void testLaunchWithFixedRotationTransform() { final int dw = 1000; final int dh = 2500; |